diff options
-rw-r--r-- | fs/btrfs/delayed-ref.c | 8 | ||||
-rw-r--r-- | fs/btrfs/delayed-ref.h | 7 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 59 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 1 |
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 | ||
158 | static inline void btrfs_put_delayed_ref(struct btrfs_delayed_ref_node *ref) | 164 | static 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 | |||
2326 | static 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); |
2343 | again: | 2368 | again: |
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); |