diff options
Diffstat (limited to 'block/blk-lib.c')
-rw-r--r-- | block/blk-lib.c | 69 |
1 files changed, 29 insertions, 40 deletions
diff --git a/block/blk-lib.c b/block/blk-lib.c index 25de73e4759b..9260cb0b209b 100644 --- a/block/blk-lib.c +++ b/block/blk-lib.c | |||
@@ -9,17 +9,23 @@ | |||
9 | 9 | ||
10 | #include "blk.h" | 10 | #include "blk.h" |
11 | 11 | ||
12 | static void blkdev_discard_end_io(struct bio *bio, int err) | 12 | struct bio_batch { |
13 | atomic_t done; | ||
14 | unsigned long flags; | ||
15 | struct completion *wait; | ||
16 | }; | ||
17 | |||
18 | static void bio_batch_end_io(struct bio *bio, int err) | ||
13 | { | 19 | { |
20 | struct bio_batch *bb = bio->bi_private; | ||
21 | |||
14 | if (err) { | 22 | if (err) { |
15 | if (err == -EOPNOTSUPP) | 23 | if (err == -EOPNOTSUPP) |
16 | set_bit(BIO_EOPNOTSUPP, &bio->bi_flags); | 24 | set_bit(BIO_EOPNOTSUPP, &bb->flags); |
17 | clear_bit(BIO_UPTODATE, &bio->bi_flags); | 25 | clear_bit(BIO_UPTODATE, &bb->flags); |
18 | } | 26 | } |
19 | 27 | if (atomic_dec_and_test(&bb->done)) | |
20 | if (bio->bi_private) | 28 | complete(bb->wait); |
21 | complete(bio->bi_private); | ||
22 | |||
23 | bio_put(bio); | 29 | bio_put(bio); |
24 | } | 30 | } |
25 | 31 | ||
@@ -41,6 +47,7 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector, | |||
41 | struct request_queue *q = bdev_get_queue(bdev); | 47 | struct request_queue *q = bdev_get_queue(bdev); |
42 | int type = REQ_WRITE | REQ_DISCARD; | 48 | int type = REQ_WRITE | REQ_DISCARD; |
43 | unsigned int max_discard_sectors; | 49 | unsigned int max_discard_sectors; |
50 | struct bio_batch bb; | ||
44 | struct bio *bio; | 51 | struct bio *bio; |
45 | int ret = 0; | 52 | int ret = 0; |
46 | 53 | ||
@@ -67,7 +74,11 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector, | |||
67 | type |= REQ_SECURE; | 74 | type |= REQ_SECURE; |
68 | } | 75 | } |
69 | 76 | ||
70 | while (nr_sects && !ret) { | 77 | atomic_set(&bb.done, 1); |
78 | bb.flags = 1 << BIO_UPTODATE; | ||
79 | bb.wait = &wait; | ||
80 | |||
81 | while (nr_sects) { | ||
71 | bio = bio_alloc(gfp_mask, 1); | 82 | bio = bio_alloc(gfp_mask, 1); |
72 | if (!bio) { | 83 | if (!bio) { |
73 | ret = -ENOMEM; | 84 | ret = -ENOMEM; |
@@ -75,9 +86,9 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector, | |||
75 | } | 86 | } |
76 | 87 | ||
77 | bio->bi_sector = sector; | 88 | bio->bi_sector = sector; |
78 | bio->bi_end_io = blkdev_discard_end_io; | 89 | bio->bi_end_io = bio_batch_end_io; |
79 | bio->bi_bdev = bdev; | 90 | bio->bi_bdev = bdev; |
80 | bio->bi_private = &wait; | 91 | bio->bi_private = &bb; |
81 | 92 | ||
82 | if (nr_sects > max_discard_sectors) { | 93 | if (nr_sects > max_discard_sectors) { |
83 | bio->bi_size = max_discard_sectors << 9; | 94 | bio->bi_size = max_discard_sectors << 9; |
@@ -88,45 +99,23 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector, | |||
88 | nr_sects = 0; | 99 | nr_sects = 0; |
89 | } | 100 | } |
90 | 101 | ||
91 | bio_get(bio); | 102 | atomic_inc(&bb.done); |
92 | submit_bio(type, bio); | 103 | submit_bio(type, bio); |
104 | } | ||
93 | 105 | ||
106 | /* Wait for bios in-flight */ | ||
107 | if (!atomic_dec_and_test(&bb.done)) | ||
94 | wait_for_completion(&wait); | 108 | wait_for_completion(&wait); |
95 | 109 | ||
96 | if (bio_flagged(bio, BIO_EOPNOTSUPP)) | 110 | if (test_bit(BIO_EOPNOTSUPP, &bb.flags)) |
97 | ret = -EOPNOTSUPP; | 111 | ret = -EOPNOTSUPP; |
98 | else if (!bio_flagged(bio, BIO_UPTODATE)) | 112 | else if (!test_bit(BIO_UPTODATE, &bb.flags)) |
99 | ret = -EIO; | 113 | ret = -EIO; |
100 | bio_put(bio); | ||
101 | } | ||
102 | 114 | ||
103 | return ret; | 115 | return ret; |
104 | } | 116 | } |
105 | EXPORT_SYMBOL(blkdev_issue_discard); | 117 | EXPORT_SYMBOL(blkdev_issue_discard); |
106 | 118 | ||
107 | struct bio_batch | ||
108 | { | ||
109 | atomic_t done; | ||
110 | unsigned long flags; | ||
111 | struct completion *wait; | ||
112 | }; | ||
113 | |||
114 | static void bio_batch_end_io(struct bio *bio, int err) | ||
115 | { | ||
116 | struct bio_batch *bb = bio->bi_private; | ||
117 | |||
118 | if (err) { | ||
119 | if (err == -EOPNOTSUPP) | ||
120 | set_bit(BIO_EOPNOTSUPP, &bb->flags); | ||
121 | else | ||
122 | clear_bit(BIO_UPTODATE, &bb->flags); | ||
123 | } | ||
124 | if (bb) | ||
125 | if (atomic_dec_and_test(&bb->done)) | ||
126 | complete(bb->wait); | ||
127 | bio_put(bio); | ||
128 | } | ||
129 | |||
130 | /** | 119 | /** |
131 | * blkdev_issue_zeroout - generate number of zero filed write bios | 120 | * blkdev_issue_zeroout - generate number of zero filed write bios |
132 | * @bdev: blockdev to issue | 121 | * @bdev: blockdev to issue |