diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index dd06e18e5aac7518191e02791073345e6a0f51cd..cc01abff03d963af529027941bb2bb4f16f53f3c 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include "compat.h" #include "ctree.h" @@ -145,6 +146,7 @@ static noinline int run_scheduled_bios(struct btrfs_device *device) int again = 0; unsigned long num_run = 0; unsigned long limit; + unsigned long last_waited = 0; bdi = device->bdev->bd_inode->i_mapping->backing_dev_info; fs_info = device->dev_root->fs_info; @@ -207,7 +209,32 @@ static noinline int run_scheduled_bios(struct btrfs_device *device) if (pending && bdi_write_congested(bdi) && num_run > 16 && fs_info->fs_devices->open_devices > 1) { struct bio *old_head; + struct io_context *ioc; + ioc = current->io_context; + + /* + * the main goal here is that we don't want to + * block if we're going to be able to submit + * more requests without blocking. + * + * This code does two great things, it pokes into + * the elevator code from a filesystem _and_ + * it makes assumptions about how batching works. + */ + if (ioc && ioc->nr_batch_requests > 0 && + time_before(jiffies, ioc->last_waited + HZ/50UL) && + (last_waited == 0 || + ioc->last_waited == last_waited)) { + /* + * we want to go through our batch of + * requests and stop. So, we copy out + * the ioc->last_waited time and test + * against it before looping + */ + last_waited = ioc->last_waited; + continue; + } spin_lock(&device->io_lock); old_head = device->pending_bios;