aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2009-03-13 10:11:24 -0400
committerChris Mason <chris.mason@oracle.com>2009-03-24 16:14:26 -0400
commit1887be66dcc3140a81d1299958a41fc0eedfa64f (patch)
tree3f0666948a83c48c77e0c37dca1c71a6aff9eb1d /fs/btrfs/extent-tree.c
parent44871b1b24b593996db43495cf4484cc580bdc10 (diff)
Btrfs: try to cleanup delayed refs while freeing extents
When extents are freed, it is likely that we've removed the last delayed reference update for the extent. This checks the delayed ref tree when things are freed, and if no ref updates area left it immediately processes the delayed ref. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c67
1 files changed, 67 insertions, 0 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 9b5da2b013e4..8471c79b0877 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -1021,6 +1021,7 @@ again:
1021 if (!locked_ref && count == 0) 1021 if (!locked_ref && count == 0)
1022 break; 1022 break;
1023 1023
1024 cond_resched();
1024 spin_lock(&delayed_refs->lock); 1025 spin_lock(&delayed_refs->lock);
1025 } 1026 }
1026 if (run_all) { 1027 if (run_all) {
@@ -1045,6 +1046,7 @@ again:
1045 mutex_unlock(&head->mutex); 1046 mutex_unlock(&head->mutex);
1046 1047
1047 btrfs_put_delayed_ref(ref); 1048 btrfs_put_delayed_ref(ref);
1049 cond_resched();
1048 goto again; 1050 goto again;
1049 } 1051 }
1050 node = rb_next(node); 1052 node = rb_next(node);
@@ -2361,6 +2363,68 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
2361 owner_objectid, pin, pin == 0, refs_to_drop); 2363 owner_objectid, pin, pin == 0, refs_to_drop);
2362} 2364}
2363 2365
2366/*
2367 * when we free an extent, it is possible (and likely) that we free the last
2368 * delayed ref for that extent as well. This searches the delayed ref tree for
2369 * a given extent, and if there are no other delayed refs to be processed, it
2370 * removes it from the tree.
2371 */
2372static noinline int check_ref_cleanup(struct btrfs_trans_handle *trans,
2373 struct btrfs_root *root, u64 bytenr)
2374{
2375 struct btrfs_delayed_ref_head *head;
2376 struct btrfs_delayed_ref_root *delayed_refs;
2377 struct btrfs_delayed_ref_node *ref;
2378 struct rb_node *node;
2379 int ret;
2380
2381 delayed_refs = &trans->transaction->delayed_refs;
2382 spin_lock(&delayed_refs->lock);
2383 head = btrfs_find_delayed_ref_head(trans, bytenr);
2384 if (!head)
2385 goto out;
2386
2387 node = rb_prev(&head->node.rb_node);
2388 if (!node)
2389 goto out;
2390
2391 ref = rb_entry(node, struct btrfs_delayed_ref_node, rb_node);
2392
2393 /* there are still entries for this ref, we can't drop it */
2394 if (ref->bytenr == bytenr)
2395 goto out;
2396
2397 /*
2398 * waiting for the lock here would deadlock. If someone else has it
2399 * locked they are already in the process of dropping it anyway
2400 */
2401 if (!mutex_trylock(&head->mutex))
2402 goto out;
2403
2404 /*
2405 * at this point we have a head with no other entries. Go
2406 * ahead and process it.
2407 */
2408 head->node.in_tree = 0;
2409 rb_erase(&head->node.rb_node, &delayed_refs->root);
2410 delayed_refs->num_entries--;
2411
2412 /*
2413 * we don't take a ref on the node because we're removing it from the
2414 * tree, so we just steal the ref the tree was holding.
2415 */
2416 spin_unlock(&delayed_refs->lock);
2417
2418 ret = run_one_delayed_ref(trans, root->fs_info->tree_root,
2419 &head->node, head->must_insert_reserved);
2420 BUG_ON(ret);
2421 btrfs_put_delayed_ref(&head->node);
2422 return 0;
2423out:
2424 spin_unlock(&delayed_refs->lock);
2425 return 0;
2426}
2427
2364int btrfs_free_extent(struct btrfs_trans_handle *trans, 2428int btrfs_free_extent(struct btrfs_trans_handle *trans,
2365 struct btrfs_root *root, 2429 struct btrfs_root *root,
2366 u64 bytenr, u64 num_bytes, u64 parent, 2430 u64 bytenr, u64 num_bytes, u64 parent,
@@ -2388,6 +2452,9 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans,
2388 root_objectid, ref_generation, 2452 root_objectid, ref_generation,
2389 owner_objectid, 2453 owner_objectid,
2390 BTRFS_DROP_DELAYED_REF, 1); 2454 BTRFS_DROP_DELAYED_REF, 1);
2455 BUG_ON(ret);
2456 ret = check_ref_cleanup(trans, root, bytenr);
2457 BUG_ON(ret);
2391 } 2458 }
2392 return ret; 2459 return ret;
2393} 2460}