diff options
author | Christoph Hellwig <hch@infradead.org> | 2009-09-12 01:35:43 -0400 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2009-09-14 02:24:53 -0400 |
commit | 746cd1e7e4a555ddaee53b19a46e05c9c61eaf09 (patch) | |
tree | d129194669e0122113a5cc86003a4a7711450284 /block/ioctl.c | |
parent | 3d2257f157c2324acbc0fa0fa54e8626a987edd2 (diff) |
block: use blkdev_issue_discard in blk_ioctl_discard
blk_ioctl_discard duplicates large amounts of code from blkdev_issue_discard,
the only difference between the two is that blkdev_issue_discard needs to
send a barrier discard request and blk_ioctl_discard a non-barrier one,
and blk_ioctl_discard needs to wait on the request. To facilitates this
add a flags argument to blkdev_issue_discard to control both aspects of the
behaviour. This will be very useful later on for using the waiting
funcitonality for other callers.
Based on an earlier patch from Matthew Wilcox <matthew@wil.cx>.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'block/ioctl.c')
-rw-r--r-- | block/ioctl.c | 49 |
1 files changed, 2 insertions, 47 deletions
diff --git a/block/ioctl.c b/block/ioctl.c index 500e4c73cc52..d3e6b5827a34 100644 --- a/block/ioctl.c +++ b/block/ioctl.c | |||
@@ -112,22 +112,9 @@ static int blkdev_reread_part(struct block_device *bdev) | |||
112 | return res; | 112 | return res; |
113 | } | 113 | } |
114 | 114 | ||
115 | static void blk_ioc_discard_endio(struct bio *bio, int err) | ||
116 | { | ||
117 | if (err) { | ||
118 | if (err == -EOPNOTSUPP) | ||
119 | set_bit(BIO_EOPNOTSUPP, &bio->bi_flags); | ||
120 | clear_bit(BIO_UPTODATE, &bio->bi_flags); | ||
121 | } | ||
122 | complete(bio->bi_private); | ||
123 | } | ||
124 | |||
125 | static int blk_ioctl_discard(struct block_device *bdev, uint64_t start, | 115 | static int blk_ioctl_discard(struct block_device *bdev, uint64_t start, |
126 | uint64_t len) | 116 | uint64_t len) |
127 | { | 117 | { |
128 | struct request_queue *q = bdev_get_queue(bdev); | ||
129 | int ret = 0; | ||
130 | |||
131 | if (start & 511) | 118 | if (start & 511) |
132 | return -EINVAL; | 119 | return -EINVAL; |
133 | if (len & 511) | 120 | if (len & 511) |
@@ -137,40 +124,8 @@ static int blk_ioctl_discard(struct block_device *bdev, uint64_t start, | |||
137 | 124 | ||
138 | if (start + len > (bdev->bd_inode->i_size >> 9)) | 125 | if (start + len > (bdev->bd_inode->i_size >> 9)) |
139 | return -EINVAL; | 126 | return -EINVAL; |
140 | 127 | return blkdev_issue_discard(bdev, start, len, GFP_KERNEL, | |
141 | if (!q->prepare_discard_fn) | 128 | DISCARD_FL_WAIT); |
142 | return -EOPNOTSUPP; | ||
143 | |||
144 | while (len && !ret) { | ||
145 | DECLARE_COMPLETION_ONSTACK(wait); | ||
146 | struct bio *bio; | ||
147 | |||
148 | bio = bio_alloc(GFP_KERNEL, 0); | ||
149 | |||
150 | bio->bi_end_io = blk_ioc_discard_endio; | ||
151 | bio->bi_bdev = bdev; | ||
152 | bio->bi_private = &wait; | ||
153 | bio->bi_sector = start; | ||
154 | |||
155 | if (len > queue_max_hw_sectors(q)) { | ||
156 | bio->bi_size = queue_max_hw_sectors(q) << 9; | ||
157 | len -= queue_max_hw_sectors(q); | ||
158 | start += queue_max_hw_sectors(q); | ||
159 | } else { | ||
160 | bio->bi_size = len << 9; | ||
161 | len = 0; | ||
162 | } | ||
163 | submit_bio(DISCARD_NOBARRIER, bio); | ||
164 | |||
165 | wait_for_completion(&wait); | ||
166 | |||
167 | if (bio_flagged(bio, BIO_EOPNOTSUPP)) | ||
168 | ret = -EOPNOTSUPP; | ||
169 | else if (!bio_flagged(bio, BIO_UPTODATE)) | ||
170 | ret = -EIO; | ||
171 | bio_put(bio); | ||
172 | } | ||
173 | return ret; | ||
174 | } | 129 | } |
175 | 130 | ||
176 | static int put_ushort(unsigned long arg, unsigned short val) | 131 | static int put_ushort(unsigned long arg, unsigned short val) |