aboutsummaryrefslogtreecommitdiffstats
path: root/block/blk-lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'block/blk-lib.c')
-rw-r--r--block/blk-lib.c69
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
12static void blkdev_discard_end_io(struct bio *bio, int err) 12struct bio_batch {
13 atomic_t done;
14 unsigned long flags;
15 struct completion *wait;
16};
17
18static 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}
105EXPORT_SYMBOL(blkdev_issue_discard); 117EXPORT_SYMBOL(blkdev_issue_discard);
106 118
107struct bio_batch
108{
109 atomic_t done;
110 unsigned long flags;
111 struct completion *wait;
112};
113
114static 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