aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2009-03-25 09:55:11 -0400
committerChris Mason <chris.mason@oracle.com>2009-03-25 09:55:11 -0400
commit1a81af4d1d9c60d4313309f937a1fc5567205a87 (patch)
tree535b65b3948d34f0948613afc6ebdfe693683f33 /fs/btrfs
parentaf4176b49c5ee15a9c9b10720c92456b28e7aac7 (diff)
Btrfs: make sure btrfs_update_delayed_ref doesn't increase ref_mod
btrfs_update_delayed_ref is optimized to add and remove different references in one pass through the delayed ref tree. It is a zero sum on the total number of refs on a given extent. But, the code was recording an extra ref in the head node. This never made it down to the disk but was used when deciding if it was safe to free the extent while dropping snapshots. The fix used here is to make sure the ref_mod count is unchanged on the head ref when btrfs_update_delayed_ref is called. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/delayed-ref.c10
-rw-r--r--fs/btrfs/delayed-ref.h1
2 files changed, 8 insertions, 3 deletions
diff --git a/fs/btrfs/delayed-ref.c b/fs/btrfs/delayed-ref.c
index 759fa247ced8..cbf7dc8ae3ec 100644
--- a/fs/btrfs/delayed-ref.c
+++ b/fs/btrfs/delayed-ref.c
@@ -450,8 +450,12 @@ static noinline int __btrfs_add_delayed_ref(struct btrfs_trans_handle *trans,
450 * the head node stores the sum of all the mods, so dropping a ref 450 * the head node stores the sum of all the mods, so dropping a ref
451 * should drop the sum in the head node by one. 451 * should drop the sum in the head node by one.
452 */ 452 */
453 if (parent == (u64)-1 && action == BTRFS_DROP_DELAYED_REF) 453 if (parent == (u64)-1) {
454 count_mod = -1; 454 if (action == BTRFS_DROP_DELAYED_REF)
455 count_mod = -1;
456 else if (action == BTRFS_UPDATE_DELAYED_HEAD)
457 count_mod = 0;
458 }
455 459
456 /* 460 /*
457 * BTRFS_ADD_DELAYED_EXTENT means that we need to update 461 * BTRFS_ADD_DELAYED_EXTENT means that we need to update
@@ -647,7 +651,7 @@ int btrfs_update_delayed_ref(struct btrfs_trans_handle *trans,
647 */ 651 */
648 ret = __btrfs_add_delayed_ref(trans, &head_ref->node, bytenr, num_bytes, 652 ret = __btrfs_add_delayed_ref(trans, &head_ref->node, bytenr, num_bytes,
649 (u64)-1, 0, 0, 0, 653 (u64)-1, 0, 0, 0,
650 BTRFS_ADD_DELAYED_REF, 0); 654 BTRFS_UPDATE_DELAYED_HEAD, 0);
651 BUG_ON(ret); 655 BUG_ON(ret);
652 656
653 ret = __btrfs_add_delayed_ref(trans, &ref->node, bytenr, num_bytes, 657 ret = __btrfs_add_delayed_ref(trans, &ref->node, bytenr, num_bytes,
diff --git a/fs/btrfs/delayed-ref.h b/fs/btrfs/delayed-ref.h
index 57153fcc347b..3bec2ff0b15c 100644
--- a/fs/btrfs/delayed-ref.h
+++ b/fs/btrfs/delayed-ref.h
@@ -22,6 +22,7 @@
22#define BTRFS_ADD_DELAYED_REF 1 /* add one backref to the tree */ 22#define BTRFS_ADD_DELAYED_REF 1 /* add one backref to the tree */
23#define BTRFS_DROP_DELAYED_REF 2 /* delete one backref from the tree */ 23#define BTRFS_DROP_DELAYED_REF 2 /* delete one backref from the tree */
24#define BTRFS_ADD_DELAYED_EXTENT 3 /* record a full extent allocation */ 24#define BTRFS_ADD_DELAYED_EXTENT 3 /* record a full extent allocation */
25#define BTRFS_UPDATE_DELAYED_HEAD 4 /* not changing ref count on head ref */
25 26
26struct btrfs_delayed_ref_node { 27struct btrfs_delayed_ref_node {
27 struct rb_node rb_node; 28 struct rb_node rb_node;