aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
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
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')
-rw-r--r--fs/btrfs/delayed-ref.c18
-rw-r--r--fs/btrfs/delayed-ref.h5
-rw-r--r--fs/btrfs/extent-tree.c67
3 files changed, 87 insertions, 3 deletions
diff --git a/fs/btrfs/delayed-ref.c b/fs/btrfs/delayed-ref.c
index 874565a1f634..3e7eeaf86408 100644
--- a/fs/btrfs/delayed-ref.c
+++ b/fs/btrfs/delayed-ref.c
@@ -511,6 +511,24 @@ int btrfs_add_delayed_ref(struct btrfs_trans_handle *trans,
511} 511}
512 512
513/* 513/*
514 * this does a simple search for the head node for a given extent.
515 * It must be called with the delayed ref spinlock held, and it returns
516 * the head node if any where found, or NULL if not.
517 */
518struct btrfs_delayed_ref_head *
519btrfs_find_delayed_ref_head(struct btrfs_trans_handle *trans, u64 bytenr)
520{
521 struct btrfs_delayed_ref_node *ref;
522 struct btrfs_delayed_ref_root *delayed_refs;
523
524 delayed_refs = &trans->transaction->delayed_refs;
525 ref = tree_search(&delayed_refs->root, bytenr, (u64)-1);
526 if (ref)
527 return btrfs_delayed_node_to_head(ref);
528 return NULL;
529}
530
531/*
514 * add a delayed ref to the tree. This does all of the accounting required 532 * add a delayed ref to the tree. This does all of the accounting required
515 * to make sure the delayed ref is eventually processed before this 533 * to make sure the delayed ref is eventually processed before this
516 * transaction commits. 534 * transaction commits.
diff --git a/fs/btrfs/delayed-ref.h b/fs/btrfs/delayed-ref.h
index 37919e5c007f..c345fee9f96b 100644
--- a/fs/btrfs/delayed-ref.h
+++ b/fs/btrfs/delayed-ref.h
@@ -137,9 +137,8 @@ int btrfs_add_delayed_ref(struct btrfs_trans_handle *trans,
137 u64 ref_generation, u64 owner_objectid, int action, 137 u64 ref_generation, u64 owner_objectid, int action,
138 int pin); 138 int pin);
139 139
140struct btrfs_delayed_ref * 140struct btrfs_delayed_ref_head *
141btrfs_find_delayed_ref(struct btrfs_trans_handle *trans, u64 bytenr, 141btrfs_find_delayed_ref_head(struct btrfs_trans_handle *trans, u64 bytenr);
142 u64 parent);
143int btrfs_delayed_ref_pending(struct btrfs_trans_handle *trans, u64 bytenr); 142int btrfs_delayed_ref_pending(struct btrfs_trans_handle *trans, u64 bytenr);
144int btrfs_lock_delayed_ref(struct btrfs_trans_handle *trans, 143int btrfs_lock_delayed_ref(struct btrfs_trans_handle *trans,
145 struct btrfs_delayed_ref_node *ref, 144 struct btrfs_delayed_ref_node *ref,
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}