diff options
author | Christoph Hellwig <hch@lst.de> | 2016-07-19 05:23:33 -0400 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2016-07-20 19:35:20 -0400 |
commit | e950fdf71c9b4a6b63b58fed78956a96cc907402 (patch) | |
tree | eadcf71a0abf034caaab5b019fe8f290df7fbc14 /block/blk-lib.c | |
parent | b09dcf585df959cf26270e65941ea1f79a1345aa (diff) |
block: introduce BLKDEV_DISCARD_ZERO to fix zeroout
Currently blkdev_issue_zeroout cascades down from discards (if the driver
guarantees that discards zero data), to WRITE SAME and then to a loop
writing zeroes. Unfortunately we ignore run-time EOPNOTSUPP errors in the
block layer blkdev_issue_discard helper to work around DM volumes that
may have mixed discard support underneath.
This patch intoroduces a new BLKDEV_DISCARD_ZERO flag to
blkdev_issue_discard that indicates we are called for zeroing operation.
This allows both to ignore the EOPNOTSUPP hack and actually consolidating
the discard_zeroes_data check into the function.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'block/blk-lib.c')
-rw-r--r-- | block/blk-lib.c | 17 |
1 files changed, 11 insertions, 6 deletions
diff --git a/block/blk-lib.c b/block/blk-lib.c index 78626c2fde33..45b35b15496f 100644 --- a/block/blk-lib.c +++ b/block/blk-lib.c | |||
@@ -36,12 +36,17 @@ int __blkdev_issue_discard(struct block_device *bdev, sector_t sector, | |||
36 | return -ENXIO; | 36 | return -ENXIO; |
37 | 37 | ||
38 | if (flags & BLKDEV_DISCARD_SECURE) { | 38 | if (flags & BLKDEV_DISCARD_SECURE) { |
39 | if (flags & BLKDEV_DISCARD_ZERO) | ||
40 | return -EOPNOTSUPP; | ||
39 | if (!blk_queue_secure_erase(q)) | 41 | if (!blk_queue_secure_erase(q)) |
40 | return -EOPNOTSUPP; | 42 | return -EOPNOTSUPP; |
41 | op = REQ_OP_SECURE_ERASE; | 43 | op = REQ_OP_SECURE_ERASE; |
42 | } else { | 44 | } else { |
43 | if (!blk_queue_discard(q)) | 45 | if (!blk_queue_discard(q)) |
44 | return -EOPNOTSUPP; | 46 | return -EOPNOTSUPP; |
47 | if ((flags & BLKDEV_DISCARD_ZERO) && | ||
48 | !q->limits.discard_zeroes_data) | ||
49 | return -EOPNOTSUPP; | ||
45 | op = REQ_OP_DISCARD; | 50 | op = REQ_OP_DISCARD; |
46 | } | 51 | } |
47 | 52 | ||
@@ -116,7 +121,7 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector, | |||
116 | &bio); | 121 | &bio); |
117 | if (!ret && bio) { | 122 | if (!ret && bio) { |
118 | ret = submit_bio_wait(bio); | 123 | ret = submit_bio_wait(bio); |
119 | if (ret == -EOPNOTSUPP) | 124 | if (ret == -EOPNOTSUPP && !(flags & BLKDEV_DISCARD_ZERO)) |
120 | ret = 0; | 125 | ret = 0; |
121 | } | 126 | } |
122 | blk_finish_plug(&plug); | 127 | blk_finish_plug(&plug); |
@@ -241,11 +246,11 @@ static int __blkdev_issue_zeroout(struct block_device *bdev, sector_t sector, | |||
241 | int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector, | 246 | int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector, |
242 | sector_t nr_sects, gfp_t gfp_mask, bool discard) | 247 | sector_t nr_sects, gfp_t gfp_mask, bool discard) |
243 | { | 248 | { |
244 | struct request_queue *q = bdev_get_queue(bdev); | 249 | if (discard) { |
245 | 250 | if (!blkdev_issue_discard(bdev, sector, nr_sects, gfp_mask, | |
246 | if (discard && blk_queue_discard(q) && q->limits.discard_zeroes_data && | 251 | BLKDEV_DISCARD_ZERO)) |
247 | blkdev_issue_discard(bdev, sector, nr_sects, gfp_mask, 0) == 0) | 252 | return 0; |
248 | return 0; | 253 | } |
249 | 254 | ||
250 | if (bdev_write_same(bdev) && | 255 | if (bdev_write_same(bdev) && |
251 | blkdev_issue_write_same(bdev, sector, nr_sects, gfp_mask, | 256 | blkdev_issue_write_same(bdev, sector, nr_sects, gfp_mask, |