diff options
author | Christoph Hellwig <hch@lst.de> | 2016-04-16 14:55:28 -0400 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2016-05-02 11:19:46 -0400 |
commit | 38f252553300ee1d3346a5273e95fe1dd60ca50a (patch) | |
tree | ddd79bcd6c509dc804374d250a38a0ebd5c3b7c1 /block/blk-lib.c | |
parent | 9082e87bfbf83579b97e3bfc45d81f3e50da2177 (diff) |
block: add __blkdev_issue_discard
This is a version of blkdev_issue_discard which doesn't wait for
the I/O to complete, but instead allows the caller to submit
the final bio and/or chain it to others.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Ming Lin <ming.l@ssi.samsung.com>
Signed-off-by: Sagi Grimberg <sagig@grimberg.me>
Reviewed-by: Ming Lei <tom.leiming@gmail.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'block/blk-lib.c')
-rw-r--r-- | block/blk-lib.c | 63 |
1 files changed, 37 insertions, 26 deletions
diff --git a/block/blk-lib.c b/block/blk-lib.c index 700d248cbde5..ccbce2b2ea05 100644 --- a/block/blk-lib.c +++ b/block/blk-lib.c | |||
@@ -22,45 +22,25 @@ static struct bio *next_bio(struct bio *bio, int rw, unsigned int nr_pages, | |||
22 | return new; | 22 | return new; |
23 | } | 23 | } |
24 | 24 | ||
25 | /** | 25 | int __blkdev_issue_discard(struct block_device *bdev, sector_t sector, |
26 | * blkdev_issue_discard - queue a discard | 26 | sector_t nr_sects, gfp_t gfp_mask, int type, struct bio **biop) |
27 | * @bdev: blockdev to issue discard for | ||
28 | * @sector: start sector | ||
29 | * @nr_sects: number of sectors to discard | ||
30 | * @gfp_mask: memory allocation flags (for bio_alloc) | ||
31 | * @flags: BLKDEV_IFL_* flags to control behaviour | ||
32 | * | ||
33 | * Description: | ||
34 | * Issue a discard request for the sectors in question. | ||
35 | */ | ||
36 | int blkdev_issue_discard(struct block_device *bdev, sector_t sector, | ||
37 | sector_t nr_sects, gfp_t gfp_mask, unsigned long flags) | ||
38 | { | 27 | { |
39 | struct request_queue *q = bdev_get_queue(bdev); | 28 | struct request_queue *q = bdev_get_queue(bdev); |
40 | int type = REQ_WRITE | REQ_DISCARD; | 29 | struct bio *bio = *biop; |
41 | unsigned int granularity; | 30 | unsigned int granularity; |
42 | int alignment; | 31 | int alignment; |
43 | struct bio *bio = NULL; | ||
44 | int ret = 0; | ||
45 | struct blk_plug plug; | ||
46 | 32 | ||
47 | if (!q) | 33 | if (!q) |
48 | return -ENXIO; | 34 | return -ENXIO; |
49 | |||
50 | if (!blk_queue_discard(q)) | 35 | if (!blk_queue_discard(q)) |
51 | return -EOPNOTSUPP; | 36 | return -EOPNOTSUPP; |
37 | if ((type & REQ_SECURE) && !blk_queue_secdiscard(q)) | ||
38 | return -EOPNOTSUPP; | ||
52 | 39 | ||
53 | /* Zero-sector (unknown) and one-sector granularities are the same. */ | 40 | /* Zero-sector (unknown) and one-sector granularities are the same. */ |
54 | granularity = max(q->limits.discard_granularity >> 9, 1U); | 41 | granularity = max(q->limits.discard_granularity >> 9, 1U); |
55 | alignment = (bdev_discard_alignment(bdev) >> 9) % granularity; | 42 | alignment = (bdev_discard_alignment(bdev) >> 9) % granularity; |
56 | 43 | ||
57 | if (flags & BLKDEV_DISCARD_SECURE) { | ||
58 | if (!blk_queue_secdiscard(q)) | ||
59 | return -EOPNOTSUPP; | ||
60 | type |= REQ_SECURE; | ||
61 | } | ||
62 | |||
63 | blk_start_plug(&plug); | ||
64 | while (nr_sects) { | 44 | while (nr_sects) { |
65 | unsigned int req_sects; | 45 | unsigned int req_sects; |
66 | sector_t end_sect, tmp; | 46 | sector_t end_sect, tmp; |
@@ -98,7 +78,38 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector, | |||
98 | */ | 78 | */ |
99 | cond_resched(); | 79 | cond_resched(); |
100 | } | 80 | } |
101 | if (bio) | 81 | |
82 | *biop = bio; | ||
83 | return 0; | ||
84 | } | ||
85 | EXPORT_SYMBOL(__blkdev_issue_discard); | ||
86 | |||
87 | /** | ||
88 | * blkdev_issue_discard - queue a discard | ||
89 | * @bdev: blockdev to issue discard for | ||
90 | * @sector: start sector | ||
91 | * @nr_sects: number of sectors to discard | ||
92 | * @gfp_mask: memory allocation flags (for bio_alloc) | ||
93 | * @flags: BLKDEV_IFL_* flags to control behaviour | ||
94 | * | ||
95 | * Description: | ||
96 | * Issue a discard request for the sectors in question. | ||
97 | */ | ||
98 | int blkdev_issue_discard(struct block_device *bdev, sector_t sector, | ||
99 | sector_t nr_sects, gfp_t gfp_mask, unsigned long flags) | ||
100 | { | ||
101 | int type = REQ_WRITE | REQ_DISCARD; | ||
102 | struct bio *bio = NULL; | ||
103 | struct blk_plug plug; | ||
104 | int ret; | ||
105 | |||
106 | if (flags & BLKDEV_DISCARD_SECURE) | ||
107 | type |= REQ_SECURE; | ||
108 | |||
109 | blk_start_plug(&plug); | ||
110 | ret = __blkdev_issue_discard(bdev, sector, nr_sects, gfp_mask, type, | ||
111 | &bio); | ||
112 | if (!ret && bio) | ||
102 | ret = submit_bio_wait(type, bio); | 113 | ret = submit_bio_wait(type, bio); |
103 | blk_finish_plug(&plug); | 114 | blk_finish_plug(&plug); |
104 | 115 | ||