Commit d644d8a1 authored by Chris Mason's avatar Chris Mason

Btrfs: avoid IO stalls behind congested devices in a multi-device FS

The btrfs IO submission threads try to service a bunch of devices with a small
number of threads.  They do a congestion check to try and avoid waiting
on requests for a busy device.

The checks make sure we've sent a few requests down to a given device just so
that we aren't bouncing between busy devices without actually sending down
any IO.  The counter used to decide if we can switch to the next device
is somewhat overloaded.  It is also being used to decide if we've done
a good batch of requests between the WRITE_SYNC or regular priority lists.
It may get reset to zero often, leaving us hammering on a busy device
instead of moving on to another disk.

This commit adds a new counter for the number of bios sent while
servicing a device.  It doesn't get reset or fiddled with.  On
multi-device filesystems, this fixes IO stalls in streaming
write workloads.
Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent d84275c9
...@@ -161,6 +161,7 @@ static noinline int run_scheduled_bios(struct btrfs_device *device) ...@@ -161,6 +161,7 @@ static noinline int run_scheduled_bios(struct btrfs_device *device)
int again = 0; int again = 0;
unsigned long num_run; unsigned long num_run;
unsigned long num_sync_run; unsigned long num_sync_run;
unsigned long batch_run = 0;
unsigned long limit; unsigned long limit;
unsigned long last_waited = 0; unsigned long last_waited = 0;
int force_reg = 0; int force_reg = 0;
...@@ -257,6 +258,8 @@ static noinline int run_scheduled_bios(struct btrfs_device *device) ...@@ -257,6 +258,8 @@ static noinline int run_scheduled_bios(struct btrfs_device *device)
BUG_ON(atomic_read(&cur->bi_cnt) == 0); BUG_ON(atomic_read(&cur->bi_cnt) == 0);
submit_bio(cur->bi_rw, cur); submit_bio(cur->bi_rw, cur);
num_run++; num_run++;
batch_run++;
if (bio_sync(cur)) if (bio_sync(cur))
num_sync_run++; num_sync_run++;
...@@ -273,7 +276,7 @@ static noinline int run_scheduled_bios(struct btrfs_device *device) ...@@ -273,7 +276,7 @@ static noinline int run_scheduled_bios(struct btrfs_device *device)
* is now congested. Back off and let other work structs * is now congested. Back off and let other work structs
* run instead * run instead
*/ */
if (pending && bdi_write_congested(bdi) && num_run > 16 && if (pending && bdi_write_congested(bdi) && batch_run > 32 &&
fs_info->fs_devices->open_devices > 1) { fs_info->fs_devices->open_devices > 1) {
struct io_context *ioc; struct io_context *ioc;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment