@@ -154,6 +154,7 @@ struct ubd {
154154 struct openflags openflags ;
155155 unsigned shared :1 ;
156156 unsigned no_cow :1 ;
157+ unsigned no_trim :1 ;
157158 struct cow cow ;
158159 struct platform_device pdev ;
159160 struct request_queue * queue ;
@@ -177,6 +178,7 @@ struct ubd {
177178 .boot_openflags = OPEN_FLAGS, \
178179 .openflags = OPEN_FLAGS, \
179180 .no_cow = 0, \
181+ .no_trim = 0, \
180182 .shared = 0, \
181183 .cow = DEFAULT_COW, \
182184 .lock = __SPIN_LOCK_UNLOCKED(ubd_devs.lock), \
@@ -323,7 +325,7 @@ static int ubd_setup_common(char *str, int *index_out, char **error_out)
323325 * index_out = n ;
324326
325327 err = - EINVAL ;
326- for (i = 0 ; i < sizeof ("rscd =" ); i ++ ) {
328+ for (i = 0 ; i < sizeof ("rscdt =" ); i ++ ) {
327329 switch (* str ) {
328330 case 'r' :
329331 flags .w = 0 ;
@@ -337,12 +339,15 @@ static int ubd_setup_common(char *str, int *index_out, char **error_out)
337339 case 'c' :
338340 ubd_dev -> shared = 1 ;
339341 break ;
342+ case 't' :
343+ ubd_dev -> no_trim = 1 ;
344+ break ;
340345 case '=' :
341346 str ++ ;
342347 goto break_loop ;
343348 default :
344349 * error_out = "Expected '=' or flag letter "
345- "(r, s, c, or d)" ;
350+ "(r, s, c, t or d)" ;
346351 goto out ;
347352 }
348353 str ++ ;
@@ -415,6 +420,7 @@ __uml_help(ubd_setup,
415420" 'c' will cause the device to be treated as being shared between multiple\n"
416421" UMLs and file locking will be turned off - this is appropriate for a\n"
417422" cluster filesystem and inappropriate at almost all other times.\n\n"
423+ " 't' will disable trim/discard support on the device (enabled by default).\n\n"
418424);
419425
420426static int udb_setup (char * str )
@@ -513,9 +519,17 @@ static void ubd_handler(void)
513519 for (count = 0 ; count < n /sizeof (struct io_thread_req * ); count ++ ) {
514520 struct io_thread_req * io_req = (* irq_req_buffer )[count ];
515521
516- if (!blk_update_request (io_req -> req , io_req -> error , io_req -> length ))
517- __blk_mq_end_request (io_req -> req , io_req -> error );
518-
522+ if ((io_req -> error == BLK_STS_NOTSUPP ) && (req_op (io_req -> req ) == REQ_OP_DISCARD )) {
523+ blk_queue_max_discard_sectors (io_req -> req -> q , 0 );
524+ blk_queue_max_write_zeroes_sectors (io_req -> req -> q , 0 );
525+ blk_queue_flag_clear (QUEUE_FLAG_DISCARD , io_req -> req -> q );
526+ }
527+ if ((io_req -> error ) || (io_req -> buffer == NULL ))
528+ blk_mq_end_request (io_req -> req , io_req -> error );
529+ else {
530+ if (!blk_update_request (io_req -> req , io_req -> error , io_req -> length ))
531+ __blk_mq_end_request (io_req -> req , io_req -> error );
532+ }
519533 kfree (io_req );
520534 }
521535 }
@@ -829,6 +843,13 @@ static int ubd_open_dev(struct ubd *ubd_dev)
829843 if (err < 0 ) goto error ;
830844 ubd_dev -> cow .fd = err ;
831845 }
846+ if (ubd_dev -> no_trim == 0 ) {
847+ ubd_dev -> queue -> limits .discard_granularity = SECTOR_SIZE ;
848+ ubd_dev -> queue -> limits .discard_alignment = SECTOR_SIZE ;
849+ blk_queue_max_discard_sectors (ubd_dev -> queue , UBD_MAX_REQUEST );
850+ blk_queue_max_write_zeroes_sectors (ubd_dev -> queue , UBD_MAX_REQUEST );
851+ blk_queue_flag_set (QUEUE_FLAG_DISCARD , ubd_dev -> queue );
852+ }
832853 blk_queue_flag_set (QUEUE_FLAG_NONROT , ubd_dev -> queue );
833854 return 0 ;
834855 error :
@@ -1372,6 +1393,10 @@ static blk_status_t ubd_queue_rq(struct blk_mq_hw_ctx *hctx,
13721393 case REQ_OP_WRITE :
13731394 ret = queue_rw_req (hctx , req );
13741395 break ;
1396+ case REQ_OP_DISCARD :
1397+ case REQ_OP_WRITE_ZEROES :
1398+ ret = ubd_queue_one_vec (hctx , req , (u64 )blk_rq_pos (req ) << 9 , NULL );
1399+ break ;
13751400 default :
13761401 WARN_ON_ONCE (1 );
13771402 res = BLK_STS_NOTSUPP ;
@@ -1463,19 +1488,21 @@ static int update_bitmap(struct io_thread_req *req)
14631488
14641489 n = os_pwrite_file (req -> fds [1 ], & req -> bitmap_words ,
14651490 sizeof (req -> bitmap_words ), req -> cow_offset );
1466- if (n != sizeof (req -> bitmap_words ))
1491+ if (n != sizeof (req -> bitmap_words ))
14671492 return map_error (- n );
14681493
14691494 return map_error (0 );
14701495}
14711496
14721497static void do_io (struct io_thread_req * req )
14731498{
1474- char * buf ;
1499+ char * buf = NULL ;
14751500 unsigned long len ;
14761501 int n , nsectors , start , end , bit ;
14771502 __u64 off ;
14781503
1504+ /* FLUSH is really a special case, we cannot "case" it with others */
1505+
14791506 if (req_op (req -> req ) == REQ_OP_FLUSH ) {
14801507 /* fds[0] is always either the rw image or our cow file */
14811508 req -> error = map_error (- os_sync_file (req -> fds [0 ]));
@@ -1495,26 +1522,42 @@ static void do_io(struct io_thread_req *req)
14951522 off = req -> offset + req -> offsets [bit ] +
14961523 start * req -> sectorsize ;
14971524 len = (end - start ) * req -> sectorsize ;
1498- buf = & req -> buffer [start * req -> sectorsize ];
1525+ if (req -> buffer != NULL )
1526+ buf = & req -> buffer [start * req -> sectorsize ];
14991527
1500- if (req_op (req -> req ) == REQ_OP_READ ) {
1528+ switch (req_op (req -> req )) {
1529+ case REQ_OP_READ :
15011530 n = 0 ;
15021531 do {
15031532 buf = & buf [n ];
15041533 len -= n ;
15051534 n = os_pread_file (req -> fds [bit ], buf , len , off );
1506- if (n < 0 ){
1535+ if (n < 0 ) {
15071536 req -> error = map_error (- n );
15081537 return ;
15091538 }
15101539 } while ((n < len ) && (n != 0 ));
15111540 if (n < len ) memset (& buf [n ], 0 , len - n );
1512- } else {
1541+ break ;
1542+ case REQ_OP_WRITE :
15131543 n = os_pwrite_file (req -> fds [bit ], buf , len , off );
15141544 if (n != len ){
15151545 req -> error = map_error (- n );
15161546 return ;
15171547 }
1548+ break ;
1549+ case REQ_OP_DISCARD :
1550+ case REQ_OP_WRITE_ZEROES :
1551+ n = os_falloc_punch (req -> fds [bit ], off , len );
1552+ if (n ) {
1553+ req -> error = map_error (- n );
1554+ return ;
1555+ }
1556+ break ;
1557+ default :
1558+ WARN_ON_ONCE (1 );
1559+ req -> error = BLK_STS_NOTSUPP ;
1560+ return ;
15181561 }
15191562
15201563 start = end ;
0 commit comments