Btrfs: Catch missed bios in the async bio submission thread
authorChris Mason <chris.mason@oracle.com>
Wed, 4 Feb 2009 14:19:41 +0000 (09:19 -0500)
committerChris Mason <chris.mason@oracle.com>
Wed, 4 Feb 2009 14:19:41 +0000 (09:19 -0500)
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>
fs/btrfs/async-thread.c
fs/btrfs/volumes.c

index d5f4e94f2ca238b2afe5ea925363dda47ca5b585..f2e80f3768ec76266d3c4424946d7e4e000da427 100644 (file)
@@ -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);
index fd0bedb07a6405d78f66ef7de63965b17d5617d3..bcd14ebccae16e751e67a73cf79c2dfbbf0db465 100644 (file)
@@ -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;
 }