Skip to content

Commit

Permalink
Btrfs: Catch missed bios in the async bio submission thread
Browse files Browse the repository at this point in the history
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 <chris.mason@oracle.com>
  • Loading branch information
Chris Mason committed Feb 4, 2009
1 parent 89f135d commit a683705
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 3 deletions.
10 changes: 9 additions & 1 deletion fs/btrfs/async-thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}

Expand All @@ -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);
Expand Down
11 changes: 9 additions & 2 deletions fs/btrfs/volumes.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -203,7 +204,7 @@ static noinline int run_scheduled_bios(struct btrfs_device *device)
* 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;

Expand All @@ -215,7 +216,8 @@ static noinline int run_scheduled_bios(struct btrfs_device *device)
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);
Expand All @@ -224,6 +226,11 @@ static noinline int run_scheduled_bios(struct btrfs_device *device)
}
if (again)
goto loop;

spin_lock(&device->io_lock);
if (device->pending_bios)
goto loop_lock;
spin_unlock(&device->io_lock);
done:
return 0;
}
Expand Down

0 comments on commit a683705

Please sign in to comment.