Skip to content

Commit c52abf5

Browse files
Evan Greenaxboe
authored andcommitted
loop: Better discard support for block devices
If the backing device for a loop device is itself a block device, then mirror the "write zeroes" capabilities of the underlying block device into the loop device. Copy this capability into both max_write_zeroes_sectors and max_discard_sectors of the loop device. The reason for this is that REQ_OP_DISCARD on a loop device translates into blkdev_issue_zeroout(), rather than blkdev_issue_discard(). This presents a consistent interface for loop devices (that discarded data is zeroed), regardless of the backing device type of the loop device. There should be no behavior change for loop devices backed by regular files. This change fixes blktest block/003, and removes an extraneous error print in block/013 when testing on a loop device backed by a block device that does not support discard. Signed-off-by: Evan Green <[email protected]> Reviewed-by: Gwendal Grignou <[email protected]> Reviewed-by: Chaitanya Kulkarni <[email protected]> [used updated version of Evan's comment in loop_config_discard()] [moved backingq to local scope, removed redundant braces] Signed-off-by: Andrzej Pietrasiewicz <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent 8cd5508 commit c52abf5

File tree

1 file changed

+31
-11
lines changed

1 file changed

+31
-11
lines changed

drivers/block/loop.c

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -429,11 +429,12 @@ static int lo_fallocate(struct loop_device *lo, struct request *rq, loff_t pos,
429429
* information.
430430
*/
431431
struct file *file = lo->lo_backing_file;
432+
struct request_queue *q = lo->lo_queue;
432433
int ret;
433434

434435
mode |= FALLOC_FL_KEEP_SIZE;
435436

436-
if ((!file->f_op->fallocate) || lo->lo_encrypt_key_size) {
437+
if (!blk_queue_discard(q)) {
437438
ret = -EOPNOTSUPP;
438439
goto out;
439440
}
@@ -867,28 +868,47 @@ static void loop_config_discard(struct loop_device *lo)
867868
struct inode *inode = file->f_mapping->host;
868869
struct request_queue *q = lo->lo_queue;
869870

871+
/*
872+
* If the backing device is a block device, mirror its zeroing
873+
* capability. Set the discard sectors to the block device's zeroing
874+
* capabilities because loop discards result in blkdev_issue_zeroout(),
875+
* not blkdev_issue_discard(). This maintains consistent behavior with
876+
* file-backed loop devices: discarded regions read back as zero.
877+
*/
878+
if (S_ISBLK(inode->i_mode) && !lo->lo_encrypt_key_size) {
879+
struct request_queue *backingq;
880+
881+
backingq = bdev_get_queue(inode->i_bdev);
882+
blk_queue_max_discard_sectors(q,
883+
backingq->limits.max_write_zeroes_sectors);
884+
885+
blk_queue_max_write_zeroes_sectors(q,
886+
backingq->limits.max_write_zeroes_sectors);
887+
870888
/*
871889
* We use punch hole to reclaim the free space used by the
872890
* image a.k.a. discard. However we do not support discard if
873891
* encryption is enabled, because it may give an attacker
874892
* useful information.
875893
*/
876-
if ((!file->f_op->fallocate) ||
877-
lo->lo_encrypt_key_size) {
894+
} else if (!file->f_op->fallocate || lo->lo_encrypt_key_size) {
878895
q->limits.discard_granularity = 0;
879896
q->limits.discard_alignment = 0;
880897
blk_queue_max_discard_sectors(q, 0);
881898
blk_queue_max_write_zeroes_sectors(q, 0);
882-
blk_queue_flag_clear(QUEUE_FLAG_DISCARD, q);
883-
return;
884-
}
885899

886-
q->limits.discard_granularity = inode->i_sb->s_blocksize;
887-
q->limits.discard_alignment = 0;
900+
} else {
901+
q->limits.discard_granularity = inode->i_sb->s_blocksize;
902+
q->limits.discard_alignment = 0;
888903

889-
blk_queue_max_discard_sectors(q, UINT_MAX >> 9);
890-
blk_queue_max_write_zeroes_sectors(q, UINT_MAX >> 9);
891-
blk_queue_flag_set(QUEUE_FLAG_DISCARD, q);
904+
blk_queue_max_discard_sectors(q, UINT_MAX >> 9);
905+
blk_queue_max_write_zeroes_sectors(q, UINT_MAX >> 9);
906+
}
907+
908+
if (q->limits.max_write_zeroes_sectors)
909+
blk_queue_flag_set(QUEUE_FLAG_DISCARD, q);
910+
else
911+
blk_queue_flag_clear(QUEUE_FLAG_DISCARD, q);
892912
}
893913

894914
static void loop_unprepare_queue(struct loop_device *lo)

0 commit comments

Comments
 (0)