diff options
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r-- | fs/btrfs/volumes.c | 41 |
1 files changed, 40 insertions, 1 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index dd06e18e5aac..e0913e469728 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/buffer_head.h> | 20 | #include <linux/buffer_head.h> |
21 | #include <linux/blkdev.h> | 21 | #include <linux/blkdev.h> |
22 | #include <linux/random.h> | 22 | #include <linux/random.h> |
23 | #include <linux/iocontext.h> | ||
23 | #include <asm/div64.h> | 24 | #include <asm/div64.h> |
24 | #include "compat.h" | 25 | #include "compat.h" |
25 | #include "ctree.h" | 26 | #include "ctree.h" |
@@ -145,8 +146,9 @@ static noinline int run_scheduled_bios(struct btrfs_device *device) | |||
145 | int again = 0; | 146 | int again = 0; |
146 | unsigned long num_run = 0; | 147 | unsigned long num_run = 0; |
147 | unsigned long limit; | 148 | unsigned long limit; |
149 | unsigned long last_waited = 0; | ||
148 | 150 | ||
149 | bdi = device->bdev->bd_inode->i_mapping->backing_dev_info; | 151 | bdi = blk_get_backing_dev_info(device->bdev); |
150 | fs_info = device->dev_root->fs_info; | 152 | fs_info = device->dev_root->fs_info; |
151 | limit = btrfs_async_submit_limit(fs_info); | 153 | limit = btrfs_async_submit_limit(fs_info); |
152 | limit = limit * 2 / 3; | 154 | limit = limit * 2 / 3; |
@@ -207,7 +209,32 @@ loop_lock: | |||
207 | if (pending && bdi_write_congested(bdi) && num_run > 16 && | 209 | if (pending && bdi_write_congested(bdi) && num_run > 16 && |
208 | fs_info->fs_devices->open_devices > 1) { | 210 | fs_info->fs_devices->open_devices > 1) { |
209 | struct bio *old_head; | 211 | struct bio *old_head; |
212 | struct io_context *ioc; | ||
210 | 213 | ||
214 | ioc = current->io_context; | ||
215 | |||
216 | /* | ||
217 | * the main goal here is that we don't want to | ||
218 | * block if we're going to be able to submit | ||
219 | * more requests without blocking. | ||
220 | * | ||
221 | * This code does two great things, it pokes into | ||
222 | * the elevator code from a filesystem _and_ | ||
223 | * it makes assumptions about how batching works. | ||
224 | */ | ||
225 | if (ioc && ioc->nr_batch_requests > 0 && | ||
226 | time_before(jiffies, ioc->last_waited + HZ/50UL) && | ||
227 | (last_waited == 0 || | ||
228 | ioc->last_waited == last_waited)) { | ||
229 | /* | ||
230 | * we want to go through our batch of | ||
231 | * requests and stop. So, we copy out | ||
232 | * the ioc->last_waited time and test | ||
233 | * against it before looping | ||
234 | */ | ||
235 | last_waited = ioc->last_waited; | ||
236 | continue; | ||
237 | } | ||
211 | spin_lock(&device->io_lock); | 238 | spin_lock(&device->io_lock); |
212 | 239 | ||
213 | old_head = device->pending_bios; | 240 | old_head = device->pending_bios; |
@@ -231,6 +258,18 @@ loop_lock: | |||
231 | if (device->pending_bios) | 258 | if (device->pending_bios) |
232 | goto loop_lock; | 259 | goto loop_lock; |
233 | spin_unlock(&device->io_lock); | 260 | spin_unlock(&device->io_lock); |
261 | |||
262 | /* | ||
263 | * IO has already been through a long path to get here. Checksumming, | ||
264 | * async helper threads, perhaps compression. We've done a pretty | ||
265 | * good job of collecting a batch of IO and should just unplug | ||
266 | * the device right away. | ||
267 | * | ||
268 | * This will help anyone who is waiting on the IO, they might have | ||
269 | * already unplugged, but managed to do so before the bio they | ||
270 | * cared about found its way down here. | ||
271 | */ | ||
272 | blk_run_backing_dev(bdi, NULL); | ||
234 | done: | 273 | done: |
235 | return 0; | 274 | return 0; |
236 | } | 275 | } |