浏览代码

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 <chris.mason@oracle.com>
Chris Mason 16 年之前
父节点
当前提交
a683705153
共有 2 个文件被更改,包括 18 次插入3 次删除
  1. 9 1
      fs/btrfs/async-thread.c
  2. 9 2
      fs/btrfs/volumes.c

+ 9 - 1
fs/btrfs/async-thread.c

@@ -349,6 +349,7 @@ int btrfs_requeue_work(struct btrfs_work *work)
 {
 {
 	struct btrfs_worker_thread *worker = work->worker;
 	struct btrfs_worker_thread *worker = work->worker;
 	unsigned long flags;
 	unsigned long flags;
+	int wake = 0;
 
 
 	if (test_and_set_bit(WORK_QUEUED_BIT, &work->flags))
 	if (test_and_set_bit(WORK_QUEUED_BIT, &work->flags))
 		goto out;
 		goto out;
@@ -367,10 +368,16 @@ int btrfs_requeue_work(struct btrfs_work *work)
 			       &worker->workers->worker_list);
 			       &worker->workers->worker_list);
 		spin_unlock_irqrestore(&worker->workers->lock, flags);
 		spin_unlock_irqrestore(&worker->workers->lock, flags);
 	}
 	}
+	if (!worker->working) {
+		wake = 1;
+		worker->working = 1;
+	}
 
 
 	spin_unlock_irqrestore(&worker->lock, flags);
 	spin_unlock_irqrestore(&worker->lock, flags);
-
+	if (wake)
+		wake_up_process(worker->task);
 out:
 out:
+
 	return 0;
 	return 0;
 }
 }
 
 
@@ -397,6 +404,7 @@ int btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work)
 	}
 	}
 
 
 	spin_lock_irqsave(&worker->lock, flags);
 	spin_lock_irqsave(&worker->lock, flags);
+
 	atomic_inc(&worker->num_pending);
 	atomic_inc(&worker->num_pending);
 	check_busy_worker(worker);
 	check_busy_worker(worker);
 	list_add_tail(&work->list, &worker->pending);
 	list_add_tail(&work->list, &worker->pending);

+ 9 - 2
fs/btrfs/volumes.c

@@ -154,6 +154,7 @@ static noinline int run_scheduled_bios(struct btrfs_device *device)
 loop:
 loop:
 	spin_lock(&device->io_lock);
 	spin_lock(&device->io_lock);
 
 
+loop_lock:
 	/* take all the bios off the list at once and process them
 	/* take all the bios off the list at once and process them
 	 * later on (without the lock held).  But, remember the
 	 * later on (without the lock held).  But, remember the
 	 * tail and other pointers so the bios can be properly reinserted
 	 * 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
 		 * is now congested.  Back off and let other work structs
 		 * run instead
 		 * run instead
 		 */
 		 */
-		if (pending && bdi_write_congested(bdi) &&
+		if (pending && bdi_write_congested(bdi) && num_run > 16 &&
 		    fs_info->fs_devices->open_devices > 1) {
 		    fs_info->fs_devices->open_devices > 1) {
 			struct bio *old_head;
 			struct bio *old_head;
 
 
@@ -215,7 +216,8 @@ loop:
 				tail->bi_next = old_head;
 				tail->bi_next = old_head;
 			else
 			else
 				device->pending_bio_tail = tail;
 				device->pending_bio_tail = tail;
-			device->running_pending = 0;
+
+			device->running_pending = 1;
 
 
 			spin_unlock(&device->io_lock);
 			spin_unlock(&device->io_lock);
 			btrfs_requeue_work(&device->work);
 			btrfs_requeue_work(&device->work);
@@ -224,6 +226,11 @@ loop:
 	}
 	}
 	if (again)
 	if (again)
 		goto loop;
 		goto loop;
+
+	spin_lock(&device->io_lock);
+	if (device->pending_bios)
+		goto loop_lock;
+	spin_unlock(&device->io_lock);
 done:
 done:
 	return 0;
 	return 0;
 }
 }