aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/delayed-ref.c8
-rw-r--r--fs/btrfs/delayed-ref.h7
-rw-r--r--fs/btrfs/extent-tree.c59
-rw-r--r--fs/btrfs/transaction.c1
4 files changed, 74 insertions, 1 deletions
diff --git a/fs/btrfs/delayed-ref.c b/fs/btrfs/delayed-ref.c
index ee181989d444..66e4f29505a3 100644
--- a/fs/btrfs/delayed-ref.c
+++ b/fs/btrfs/delayed-ref.c
@@ -664,6 +664,9 @@ int btrfs_add_delayed_tree_ref(struct btrfs_fs_info *fs_info,
664 num_bytes, parent, ref_root, level, action, 664 num_bytes, parent, ref_root, level, action,
665 for_cow); 665 for_cow);
666 BUG_ON(ret); 666 BUG_ON(ret);
667 if (!need_ref_seq(for_cow, ref_root) &&
668 waitqueue_active(&delayed_refs->seq_wait))
669 wake_up(&delayed_refs->seq_wait);
667 spin_unlock(&delayed_refs->lock); 670 spin_unlock(&delayed_refs->lock);
668 return 0; 671 return 0;
669} 672}
@@ -712,6 +715,9 @@ int btrfs_add_delayed_data_ref(struct btrfs_fs_info *fs_info,
712 num_bytes, parent, ref_root, owner, offset, 715 num_bytes, parent, ref_root, owner, offset,
713 action, for_cow); 716 action, for_cow);
714 BUG_ON(ret); 717 BUG_ON(ret);
718 if (!need_ref_seq(for_cow, ref_root) &&
719 waitqueue_active(&delayed_refs->seq_wait))
720 wake_up(&delayed_refs->seq_wait);
715 spin_unlock(&delayed_refs->lock); 721 spin_unlock(&delayed_refs->lock);
716 return 0; 722 return 0;
717} 723}
@@ -739,6 +745,8 @@ int btrfs_add_delayed_extent_op(struct btrfs_fs_info *fs_info,
739 extent_op->is_data); 745 extent_op->is_data);
740 BUG_ON(ret); 746 BUG_ON(ret);
741 747
748 if (waitqueue_active(&delayed_refs->seq_wait))
749 wake_up(&delayed_refs->seq_wait);
742 spin_unlock(&delayed_refs->lock); 750 spin_unlock(&delayed_refs->lock);
743 return 0; 751 return 0;
744} 752}
diff --git a/fs/btrfs/delayed-ref.h b/fs/btrfs/delayed-ref.h
index 174416f7882b..d8f244d94925 100644
--- a/fs/btrfs/delayed-ref.h
+++ b/fs/btrfs/delayed-ref.h
@@ -153,6 +153,12 @@ struct btrfs_delayed_ref_root {
153 * as it might influence the outcome of the walk. 153 * as it might influence the outcome of the walk.
154 */ 154 */
155 struct list_head seq_head; 155 struct list_head seq_head;
156
157 /*
158 * when the only refs we have in the list must not be processed, we want
159 * to wait for more refs to show up or for the end of backref walking.
160 */
161 wait_queue_head_t seq_wait;
156}; 162};
157 163
158static inline void btrfs_put_delayed_ref(struct btrfs_delayed_ref_node *ref) 164static inline void btrfs_put_delayed_ref(struct btrfs_delayed_ref_node *ref)
@@ -216,6 +222,7 @@ btrfs_put_delayed_seq(struct btrfs_delayed_ref_root *delayed_refs,
216{ 222{
217 spin_lock(&delayed_refs->lock); 223 spin_lock(&delayed_refs->lock);
218 list_del(&elem->list); 224 list_del(&elem->list);
225 wake_up(&delayed_refs->seq_wait);
219 spin_unlock(&delayed_refs->lock); 226 spin_unlock(&delayed_refs->lock);
220} 227}
221 228
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index bbcca12fbbba..0a435e2e143e 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -2300,7 +2300,12 @@ static noinline int run_clustered_refs(struct btrfs_trans_handle *trans,
2300 ref->in_tree = 0; 2300 ref->in_tree = 0;
2301 rb_erase(&ref->rb_node, &delayed_refs->root); 2301 rb_erase(&ref->rb_node, &delayed_refs->root);
2302 delayed_refs->num_entries--; 2302 delayed_refs->num_entries--;
2303 2303 /*
2304 * we modified num_entries, but as we're currently running
2305 * delayed refs, skip
2306 * wake_up(&delayed_refs->seq_wait);
2307 * here.
2308 */
2304 spin_unlock(&delayed_refs->lock); 2309 spin_unlock(&delayed_refs->lock);
2305 2310
2306 ret = run_one_delayed_ref(trans, root, ref, extent_op, 2311 ret = run_one_delayed_ref(trans, root, ref, extent_op,
@@ -2317,6 +2322,23 @@ static noinline int run_clustered_refs(struct btrfs_trans_handle *trans,
2317 return count; 2322 return count;
2318} 2323}
2319 2324
2325
2326static void wait_for_more_refs(struct btrfs_delayed_ref_root *delayed_refs,
2327 unsigned long num_refs)
2328{
2329 struct list_head *first_seq = delayed_refs->seq_head.next;
2330
2331 spin_unlock(&delayed_refs->lock);
2332 pr_debug("waiting for more refs (num %ld, first %p)\n",
2333 num_refs, first_seq);
2334 wait_event(delayed_refs->seq_wait,
2335 num_refs != delayed_refs->num_entries ||
2336 delayed_refs->seq_head.next != first_seq);
2337 pr_debug("done waiting for more refs (num %ld, first %p)\n",
2338 delayed_refs->num_entries, delayed_refs->seq_head.next);
2339 spin_lock(&delayed_refs->lock);
2340}
2341
2320/* 2342/*
2321 * this starts processing the delayed reference count updates and 2343 * this starts processing the delayed reference count updates and
2322 * extent insertions we have queued up so far. count can be 2344 * extent insertions we have queued up so far. count can be
@@ -2332,8 +2354,11 @@ int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
2332 struct btrfs_delayed_ref_node *ref; 2354 struct btrfs_delayed_ref_node *ref;
2333 struct list_head cluster; 2355 struct list_head cluster;
2334 int ret; 2356 int ret;
2357 u64 delayed_start;
2335 int run_all = count == (unsigned long)-1; 2358 int run_all = count == (unsigned long)-1;
2336 int run_most = 0; 2359 int run_most = 0;
2360 unsigned long num_refs = 0;
2361 int consider_waiting;
2337 2362
2338 if (root == root->fs_info->extent_root) 2363 if (root == root->fs_info->extent_root)
2339 root = root->fs_info->tree_root; 2364 root = root->fs_info->tree_root;
@@ -2341,6 +2366,7 @@ int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
2341 delayed_refs = &trans->transaction->delayed_refs; 2366 delayed_refs = &trans->transaction->delayed_refs;
2342 INIT_LIST_HEAD(&cluster); 2367 INIT_LIST_HEAD(&cluster);
2343again: 2368again:
2369 consider_waiting = 0;
2344 spin_lock(&delayed_refs->lock); 2370 spin_lock(&delayed_refs->lock);
2345 if (count == 0) { 2371 if (count == 0) {
2346 count = delayed_refs->num_entries * 2; 2372 count = delayed_refs->num_entries * 2;
@@ -2357,11 +2383,35 @@ again:
2357 * of refs to process starting at the first one we are able to 2383 * of refs to process starting at the first one we are able to
2358 * lock 2384 * lock
2359 */ 2385 */
2386 delayed_start = delayed_refs->run_delayed_start;
2360 ret = btrfs_find_ref_cluster(trans, &cluster, 2387 ret = btrfs_find_ref_cluster(trans, &cluster,
2361 delayed_refs->run_delayed_start); 2388 delayed_refs->run_delayed_start);
2362 if (ret) 2389 if (ret)
2363 break; 2390 break;
2364 2391
2392 if (delayed_start >= delayed_refs->run_delayed_start) {
2393 if (consider_waiting == 0) {
2394 /*
2395 * btrfs_find_ref_cluster looped. let's do one
2396 * more cycle. if we don't run any delayed ref
2397 * during that cycle (because we can't because
2398 * all of them are blocked) and if the number of
2399 * refs doesn't change, we avoid busy waiting.
2400 */
2401 consider_waiting = 1;
2402 num_refs = delayed_refs->num_entries;
2403 } else {
2404 wait_for_more_refs(delayed_refs, num_refs);
2405 /*
2406 * after waiting, things have changed. we
2407 * dropped the lock and someone else might have
2408 * run some refs, built new clusters and so on.
2409 * therefore, we restart staleness detection.
2410 */
2411 consider_waiting = 0;
2412 }
2413 }
2414
2365 ret = run_clustered_refs(trans, root, &cluster); 2415 ret = run_clustered_refs(trans, root, &cluster);
2366 BUG_ON(ret < 0); 2416 BUG_ON(ret < 0);
2367 2417
@@ -2369,6 +2419,11 @@ again:
2369 2419
2370 if (count == 0) 2420 if (count == 0)
2371 break; 2421 break;
2422
2423 if (ret || delayed_refs->run_delayed_start == 0) {
2424 /* refs were run, let's reset staleness detection */
2425 consider_waiting = 0;
2426 }
2372 } 2427 }
2373 2428
2374 if (run_all) { 2429 if (run_all) {
@@ -4933,6 +4988,8 @@ static noinline int check_ref_cleanup(struct btrfs_trans_handle *trans,
4933 rb_erase(&head->node.rb_node, &delayed_refs->root); 4988 rb_erase(&head->node.rb_node, &delayed_refs->root);
4934 4989
4935 delayed_refs->num_entries--; 4990 delayed_refs->num_entries--;
4991 if (waitqueue_active(&delayed_refs->seq_wait))
4992 wake_up(&delayed_refs->seq_wait);
4936 4993
4937 /* 4994 /*
4938 * we don't take a ref on the node because we're removing it from the 4995 * we don't take a ref on the node because we're removing it from the
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 31a7393af64e..04c5c7c2c32f 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -111,6 +111,7 @@ loop:
111 cur_trans->delayed_refs.flushing = 0; 111 cur_trans->delayed_refs.flushing = 0;
112 cur_trans->delayed_refs.run_delayed_start = 0; 112 cur_trans->delayed_refs.run_delayed_start = 0;
113 cur_trans->delayed_refs.seq = 1; 113 cur_trans->delayed_refs.seq = 1;
114 init_waitqueue_head(&cur_trans->delayed_refs.seq_wait);
114 spin_lock_init(&cur_trans->commit_lock); 115 spin_lock_init(&cur_trans->commit_lock);
115 spin_lock_init(&cur_trans->delayed_refs.lock); 116 spin_lock_init(&cur_trans->delayed_refs.lock);
116 INIT_LIST_HEAD(&cur_trans->delayed_refs.seq_head); 117 INIT_LIST_HEAD(&cur_trans->delayed_refs.seq_head);