diff options
author | Adrian Hunter <adrian.hunter@intel.com> | 2016-08-16 03:59:35 -0400 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2016-08-16 11:16:51 -0400 |
commit | 7afafc8a44bf0ab841b17d450b02aedb3a138985 (patch) | |
tree | a879b43681ee39a3f3ace3aeacb81f30c96ca00d | |
parent | f6b6a28e2dbc401416ff12f775d75281c9b41918 (diff) |
block: Fix secure erase
Commit 288dab8a35a0 ("block: add a separate operation type for secure
erase") split REQ_OP_SECURE_ERASE from REQ_OP_DISCARD without considering
all the places REQ_OP_DISCARD was being used to mean either. Fix those.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Fixes: 288dab8a35a0 ("block: add a separate operation type for secure erase")
Signed-off-by: Jens Axboe <axboe@fb.com>
-rw-r--r-- | block/bio.c | 21 | ||||
-rw-r--r-- | block/blk-merge.c | 33 | ||||
-rw-r--r-- | block/elevator.c | 2 | ||||
-rw-r--r-- | drivers/mmc/card/block.c | 1 | ||||
-rw-r--r-- | drivers/mmc/card/queue.c | 3 | ||||
-rw-r--r-- | drivers/mmc/card/queue.h | 4 | ||||
-rw-r--r-- | include/linux/bio.h | 10 | ||||
-rw-r--r-- | include/linux/blkdev.h | 6 | ||||
-rw-r--r-- | kernel/trace/blktrace.c | 2 |
9 files changed, 50 insertions, 32 deletions
diff --git a/block/bio.c b/block/bio.c index f39477538fef..aa7354088008 100644 --- a/block/bio.c +++ b/block/bio.c | |||
@@ -667,18 +667,19 @@ struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask, | |||
667 | bio->bi_iter.bi_sector = bio_src->bi_iter.bi_sector; | 667 | bio->bi_iter.bi_sector = bio_src->bi_iter.bi_sector; |
668 | bio->bi_iter.bi_size = bio_src->bi_iter.bi_size; | 668 | bio->bi_iter.bi_size = bio_src->bi_iter.bi_size; |
669 | 669 | ||
670 | if (bio_op(bio) == REQ_OP_DISCARD) | 670 | switch (bio_op(bio)) { |
671 | goto integrity_clone; | 671 | case REQ_OP_DISCARD: |
672 | 672 | case REQ_OP_SECURE_ERASE: | |
673 | if (bio_op(bio) == REQ_OP_WRITE_SAME) { | 673 | break; |
674 | case REQ_OP_WRITE_SAME: | ||
674 | bio->bi_io_vec[bio->bi_vcnt++] = bio_src->bi_io_vec[0]; | 675 | bio->bi_io_vec[bio->bi_vcnt++] = bio_src->bi_io_vec[0]; |
675 | goto integrity_clone; | 676 | break; |
677 | default: | ||
678 | bio_for_each_segment(bv, bio_src, iter) | ||
679 | bio->bi_io_vec[bio->bi_vcnt++] = bv; | ||
680 | break; | ||
676 | } | 681 | } |
677 | 682 | ||
678 | bio_for_each_segment(bv, bio_src, iter) | ||
679 | bio->bi_io_vec[bio->bi_vcnt++] = bv; | ||
680 | |||
681 | integrity_clone: | ||
682 | if (bio_integrity(bio_src)) { | 683 | if (bio_integrity(bio_src)) { |
683 | int ret; | 684 | int ret; |
684 | 685 | ||
@@ -1788,7 +1789,7 @@ struct bio *bio_split(struct bio *bio, int sectors, | |||
1788 | * Discards need a mutable bio_vec to accommodate the payload | 1789 | * Discards need a mutable bio_vec to accommodate the payload |
1789 | * required by the DSM TRIM and UNMAP commands. | 1790 | * required by the DSM TRIM and UNMAP commands. |
1790 | */ | 1791 | */ |
1791 | if (bio_op(bio) == REQ_OP_DISCARD) | 1792 | if (bio_op(bio) == REQ_OP_DISCARD || bio_op(bio) == REQ_OP_SECURE_ERASE) |
1792 | split = bio_clone_bioset(bio, gfp, bs); | 1793 | split = bio_clone_bioset(bio, gfp, bs); |
1793 | else | 1794 | else |
1794 | split = bio_clone_fast(bio, gfp, bs); | 1795 | split = bio_clone_fast(bio, gfp, bs); |
diff --git a/block/blk-merge.c b/block/blk-merge.c index 3eec75a9e91d..72627e3cf91e 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c | |||
@@ -172,12 +172,18 @@ void blk_queue_split(struct request_queue *q, struct bio **bio, | |||
172 | struct bio *split, *res; | 172 | struct bio *split, *res; |
173 | unsigned nsegs; | 173 | unsigned nsegs; |
174 | 174 | ||
175 | if (bio_op(*bio) == REQ_OP_DISCARD) | 175 | switch (bio_op(*bio)) { |
176 | case REQ_OP_DISCARD: | ||
177 | case REQ_OP_SECURE_ERASE: | ||
176 | split = blk_bio_discard_split(q, *bio, bs, &nsegs); | 178 | split = blk_bio_discard_split(q, *bio, bs, &nsegs); |
177 | else if (bio_op(*bio) == REQ_OP_WRITE_SAME) | 179 | break; |
180 | case REQ_OP_WRITE_SAME: | ||
178 | split = blk_bio_write_same_split(q, *bio, bs, &nsegs); | 181 | split = blk_bio_write_same_split(q, *bio, bs, &nsegs); |
179 | else | 182 | break; |
183 | default: | ||
180 | split = blk_bio_segment_split(q, *bio, q->bio_split, &nsegs); | 184 | split = blk_bio_segment_split(q, *bio, q->bio_split, &nsegs); |
185 | break; | ||
186 | } | ||
181 | 187 | ||
182 | /* physical segments can be figured out during splitting */ | 188 | /* physical segments can be figured out during splitting */ |
183 | res = split ? split : *bio; | 189 | res = split ? split : *bio; |
@@ -213,7 +219,7 @@ static unsigned int __blk_recalc_rq_segments(struct request_queue *q, | |||
213 | * This should probably be returning 0, but blk_add_request_payload() | 219 | * This should probably be returning 0, but blk_add_request_payload() |
214 | * (Christoph!!!!) | 220 | * (Christoph!!!!) |
215 | */ | 221 | */ |
216 | if (bio_op(bio) == REQ_OP_DISCARD) | 222 | if (bio_op(bio) == REQ_OP_DISCARD || bio_op(bio) == REQ_OP_SECURE_ERASE) |
217 | return 1; | 223 | return 1; |
218 | 224 | ||
219 | if (bio_op(bio) == REQ_OP_WRITE_SAME) | 225 | if (bio_op(bio) == REQ_OP_WRITE_SAME) |
@@ -385,7 +391,9 @@ static int __blk_bios_map_sg(struct request_queue *q, struct bio *bio, | |||
385 | nsegs = 0; | 391 | nsegs = 0; |
386 | cluster = blk_queue_cluster(q); | 392 | cluster = blk_queue_cluster(q); |
387 | 393 | ||
388 | if (bio_op(bio) == REQ_OP_DISCARD) { | 394 | switch (bio_op(bio)) { |
395 | case REQ_OP_DISCARD: | ||
396 | case REQ_OP_SECURE_ERASE: | ||
389 | /* | 397 | /* |
390 | * This is a hack - drivers should be neither modifying the | 398 | * This is a hack - drivers should be neither modifying the |
391 | * biovec, nor relying on bi_vcnt - but because of | 399 | * biovec, nor relying on bi_vcnt - but because of |
@@ -393,19 +401,16 @@ static int __blk_bios_map_sg(struct request_queue *q, struct bio *bio, | |||
393 | * a payload we need to set up here (thank you Christoph) and | 401 | * a payload we need to set up here (thank you Christoph) and |
394 | * bi_vcnt is really the only way of telling if we need to. | 402 | * bi_vcnt is really the only way of telling if we need to. |
395 | */ | 403 | */ |
396 | 404 | if (!bio->bi_vcnt) | |
397 | if (bio->bi_vcnt) | 405 | return 0; |
398 | goto single_segment; | 406 | /* Fall through */ |
399 | 407 | case REQ_OP_WRITE_SAME: | |
400 | return 0; | ||
401 | } | ||
402 | |||
403 | if (bio_op(bio) == REQ_OP_WRITE_SAME) { | ||
404 | single_segment: | ||
405 | *sg = sglist; | 408 | *sg = sglist; |
406 | bvec = bio_iovec(bio); | 409 | bvec = bio_iovec(bio); |
407 | sg_set_page(*sg, bvec.bv_page, bvec.bv_len, bvec.bv_offset); | 410 | sg_set_page(*sg, bvec.bv_page, bvec.bv_len, bvec.bv_offset); |
408 | return 1; | 411 | return 1; |
412 | default: | ||
413 | break; | ||
409 | } | 414 | } |
410 | 415 | ||
411 | for_each_bio(bio) | 416 | for_each_bio(bio) |
diff --git a/block/elevator.c b/block/elevator.c index 7096c22041e7..f7d973a56fd7 100644 --- a/block/elevator.c +++ b/block/elevator.c | |||
@@ -366,7 +366,7 @@ void elv_dispatch_sort(struct request_queue *q, struct request *rq) | |||
366 | list_for_each_prev(entry, &q->queue_head) { | 366 | list_for_each_prev(entry, &q->queue_head) { |
367 | struct request *pos = list_entry_rq(entry); | 367 | struct request *pos = list_entry_rq(entry); |
368 | 368 | ||
369 | if ((req_op(rq) == REQ_OP_DISCARD) != (req_op(pos) == REQ_OP_DISCARD)) | 369 | if (req_op(rq) != req_op(pos)) |
370 | break; | 370 | break; |
371 | if (rq_data_dir(rq) != rq_data_dir(pos)) | 371 | if (rq_data_dir(rq) != rq_data_dir(pos)) |
372 | break; | 372 | break; |
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 48a5dd740f3b..82503e6f04b3 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c | |||
@@ -1726,6 +1726,7 @@ static u8 mmc_blk_prep_packed_list(struct mmc_queue *mq, struct request *req) | |||
1726 | break; | 1726 | break; |
1727 | 1727 | ||
1728 | if (req_op(next) == REQ_OP_DISCARD || | 1728 | if (req_op(next) == REQ_OP_DISCARD || |
1729 | req_op(next) == REQ_OP_SECURE_ERASE || | ||
1729 | req_op(next) == REQ_OP_FLUSH) | 1730 | req_op(next) == REQ_OP_FLUSH) |
1730 | break; | 1731 | break; |
1731 | 1732 | ||
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index bf14642a576a..29578e98603d 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c | |||
@@ -33,7 +33,8 @@ static int mmc_prep_request(struct request_queue *q, struct request *req) | |||
33 | /* | 33 | /* |
34 | * We only like normal block requests and discards. | 34 | * We only like normal block requests and discards. |
35 | */ | 35 | */ |
36 | if (req->cmd_type != REQ_TYPE_FS && req_op(req) != REQ_OP_DISCARD) { | 36 | if (req->cmd_type != REQ_TYPE_FS && req_op(req) != REQ_OP_DISCARD && |
37 | req_op(req) != REQ_OP_SECURE_ERASE) { | ||
37 | blk_dump_rq_flags(req, "MMC bad request"); | 38 | blk_dump_rq_flags(req, "MMC bad request"); |
38 | return BLKPREP_KILL; | 39 | return BLKPREP_KILL; |
39 | } | 40 | } |
diff --git a/drivers/mmc/card/queue.h b/drivers/mmc/card/queue.h index d62531124d54..fee5e1271465 100644 --- a/drivers/mmc/card/queue.h +++ b/drivers/mmc/card/queue.h | |||
@@ -4,7 +4,9 @@ | |||
4 | static inline bool mmc_req_is_special(struct request *req) | 4 | static inline bool mmc_req_is_special(struct request *req) |
5 | { | 5 | { |
6 | return req && | 6 | return req && |
7 | (req_op(req) == REQ_OP_FLUSH || req_op(req) == REQ_OP_DISCARD); | 7 | (req_op(req) == REQ_OP_FLUSH || |
8 | req_op(req) == REQ_OP_DISCARD || | ||
9 | req_op(req) == REQ_OP_SECURE_ERASE); | ||
8 | } | 10 | } |
9 | 11 | ||
10 | struct request; | 12 | struct request; |
diff --git a/include/linux/bio.h b/include/linux/bio.h index 59ffaa68b11b..23ddf4b46a9b 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h | |||
@@ -71,7 +71,8 @@ static inline bool bio_has_data(struct bio *bio) | |||
71 | { | 71 | { |
72 | if (bio && | 72 | if (bio && |
73 | bio->bi_iter.bi_size && | 73 | bio->bi_iter.bi_size && |
74 | bio_op(bio) != REQ_OP_DISCARD) | 74 | bio_op(bio) != REQ_OP_DISCARD && |
75 | bio_op(bio) != REQ_OP_SECURE_ERASE) | ||
75 | return true; | 76 | return true; |
76 | 77 | ||
77 | return false; | 78 | return false; |
@@ -79,7 +80,9 @@ static inline bool bio_has_data(struct bio *bio) | |||
79 | 80 | ||
80 | static inline bool bio_no_advance_iter(struct bio *bio) | 81 | static inline bool bio_no_advance_iter(struct bio *bio) |
81 | { | 82 | { |
82 | return bio_op(bio) == REQ_OP_DISCARD || bio_op(bio) == REQ_OP_WRITE_SAME; | 83 | return bio_op(bio) == REQ_OP_DISCARD || |
84 | bio_op(bio) == REQ_OP_SECURE_ERASE || | ||
85 | bio_op(bio) == REQ_OP_WRITE_SAME; | ||
83 | } | 86 | } |
84 | 87 | ||
85 | static inline bool bio_is_rw(struct bio *bio) | 88 | static inline bool bio_is_rw(struct bio *bio) |
@@ -199,6 +202,9 @@ static inline unsigned bio_segments(struct bio *bio) | |||
199 | if (bio_op(bio) == REQ_OP_DISCARD) | 202 | if (bio_op(bio) == REQ_OP_DISCARD) |
200 | return 1; | 203 | return 1; |
201 | 204 | ||
205 | if (bio_op(bio) == REQ_OP_SECURE_ERASE) | ||
206 | return 1; | ||
207 | |||
202 | if (bio_op(bio) == REQ_OP_WRITE_SAME) | 208 | if (bio_op(bio) == REQ_OP_WRITE_SAME) |
203 | return 1; | 209 | return 1; |
204 | 210 | ||
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 2c210b6a7bcf..e79055c8b577 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h | |||
@@ -882,7 +882,7 @@ static inline unsigned int blk_rq_cur_sectors(const struct request *rq) | |||
882 | static inline unsigned int blk_queue_get_max_sectors(struct request_queue *q, | 882 | static inline unsigned int blk_queue_get_max_sectors(struct request_queue *q, |
883 | int op) | 883 | int op) |
884 | { | 884 | { |
885 | if (unlikely(op == REQ_OP_DISCARD)) | 885 | if (unlikely(op == REQ_OP_DISCARD || op == REQ_OP_SECURE_ERASE)) |
886 | return min(q->limits.max_discard_sectors, UINT_MAX >> 9); | 886 | return min(q->limits.max_discard_sectors, UINT_MAX >> 9); |
887 | 887 | ||
888 | if (unlikely(op == REQ_OP_WRITE_SAME)) | 888 | if (unlikely(op == REQ_OP_WRITE_SAME)) |
@@ -913,7 +913,9 @@ static inline unsigned int blk_rq_get_max_sectors(struct request *rq, | |||
913 | if (unlikely(rq->cmd_type != REQ_TYPE_FS)) | 913 | if (unlikely(rq->cmd_type != REQ_TYPE_FS)) |
914 | return q->limits.max_hw_sectors; | 914 | return q->limits.max_hw_sectors; |
915 | 915 | ||
916 | if (!q->limits.chunk_sectors || (req_op(rq) == REQ_OP_DISCARD)) | 916 | if (!q->limits.chunk_sectors || |
917 | req_op(rq) == REQ_OP_DISCARD || | ||
918 | req_op(rq) == REQ_OP_SECURE_ERASE) | ||
917 | return blk_queue_get_max_sectors(q, req_op(rq)); | 919 | return blk_queue_get_max_sectors(q, req_op(rq)); |
918 | 920 | ||
919 | return min(blk_max_size_offset(q, offset), | 921 | return min(blk_max_size_offset(q, offset), |
diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c index 7598e6ca817a..dbafc5df03f3 100644 --- a/kernel/trace/blktrace.c +++ b/kernel/trace/blktrace.c | |||
@@ -223,7 +223,7 @@ static void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes, | |||
223 | what |= MASK_TC_BIT(op_flags, META); | 223 | what |= MASK_TC_BIT(op_flags, META); |
224 | what |= MASK_TC_BIT(op_flags, PREFLUSH); | 224 | what |= MASK_TC_BIT(op_flags, PREFLUSH); |
225 | what |= MASK_TC_BIT(op_flags, FUA); | 225 | what |= MASK_TC_BIT(op_flags, FUA); |
226 | if (op == REQ_OP_DISCARD) | 226 | if (op == REQ_OP_DISCARD || op == REQ_OP_SECURE_ERASE) |
227 | what |= BLK_TC_ACT(BLK_TC_DISCARD); | 227 | what |= BLK_TC_ACT(BLK_TC_DISCARD); |
228 | if (op == REQ_OP_FLUSH) | 228 | if (op == REQ_OP_FLUSH) |
229 | what |= BLK_TC_ACT(BLK_TC_FLUSH); | 229 | what |= BLK_TC_ACT(BLK_TC_FLUSH); |