From a68370515356a3eddbfaf7f56418b3cf85d76c2c Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Wed, 4 Feb 2009 09:19:41 -0500 Subject: [PATCH] Btrfs: Catch missed bios in the async bio submission thread The async bio submission thread was missing some bios that were added after it had decided there was no work left to do. Signed-off-by: Chris Mason --- fs/btrfs/async-thread.c | 10 +++++++++- fs/btrfs/volumes.c | 11 +++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/fs/btrfs/async-thread.c b/fs/btrfs/async-thread.c index d5f4e94f2ca2..f2e80f3768ec 100644 --- a/fs/btrfs/async-thread.c +++ b/fs/btrfs/async-thread.c @@ -349,6 +349,7 @@ int btrfs_requeue_work(struct btrfs_work *work) { struct btrfs_worker_thread *worker = work->worker; unsigned long flags; + int wake = 0; if (test_and_set_bit(WORK_QUEUED_BIT, &work->flags)) goto out; @@ -367,10 +368,16 @@ int btrfs_requeue_work(struct btrfs_work *work) &worker->workers->worker_list); spin_unlock_irqrestore(&worker->workers->lock, flags); } + if (!worker->working) { + wake = 1; + worker->working = 1; + } spin_unlock_irqrestore(&worker->lock, flags); - + if (wake) + wake_up_process(worker->task); out: + return 0; } @@ -397,6 +404,7 @@ int btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work) } spin_lock_irqsave(&worker->lock, flags); + atomic_inc(&worker->num_pending); check_busy_worker(worker); list_add_tail(&work->list, &worker->pending); diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index fd0bedb07a64..bcd14ebccae1 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -154,6 +154,7 @@ static noinline int run_scheduled_bios(struct btrfs_device *device) loop: spin_lock(&device->io_lock); +loop_lock: /* take all the bios off the list at once and process them * later on (without the lock held). But, remember the * tail and other pointers so the bios can be properly reinserted @@ -203,7 +204,7 @@ loop: * is now congested. Back off and let other work structs * run instead */ - if (pending && bdi_write_congested(bdi) && + if (pending && bdi_write_congested(bdi) && num_run > 16 && fs_info->fs_devices->open_devices > 1) { struct bio *old_head; @@ -215,7 +216,8 @@ loop: tail->bi_next = old_head; else device->pending_bio_tail = tail; - device->running_pending = 0; + + device->running_pending = 1; spin_unlock(&device->io_lock); btrfs_requeue_work(&device->work); @@ -224,6 +226,11 @@ loop: } if (again) goto loop; + + spin_lock(&device->io_lock); + if (device->pending_bios) + goto loop_lock; + spin_unlock(&device->io_lock); done: return 0; } -- 2.30.2