All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Process delayed back reference insertion before deletion
@ 2009-02-23 14:11 Yan Zheng
  0 siblings, 0 replies; only message in thread
From: Yan Zheng @ 2009-02-23 14:11 UTC (permalink / raw)
  To: linux-btrfs, chris Mason

hello,

This patch makes btrfs_run_delayed_refs processes delayed back
reference insertion before deletion. This prevents the reference
count in BTRFS_EXTENT_ITEM going down to zero when there still
are pending delayed back references. This patch fixes the issue
that BTRFS_EXTENT_ITEM with zero reference count left in the
extent tree. Thank you,

Signed-off-by: Yan Zheng <zheng.yan@oracle.com>

---
diff -urp 1/fs/btrfs/extent-tree.c 2/fs/btrfs/extent-tree.c
--- 1/fs/btrfs/extent-tree.c	2009-02-23 09:02:35.763717851 +0800
+++ 2/fs/btrfs/extent-tree.c	2009-02-23 21:20:08.000000000 +0800
@@ -1533,6 +1533,37 @@ static noinline int run_one_delayed_ref(
 	return 0;
 }
 
+static noinline struct btrfs_delayed_ref_node *
+select_delayed_ref(struct btrfs_delayed_ref_head *head)
+{
+	struct rb_node *node;
+	struct btrfs_delayed_ref_node *ref;
+	int action = BTRFS_ADD_DELAYED_REF;
+again:
+	/*
+	 * select delayed ref of type BTRFS_ADD_DELAYED_REF first.
+	 * this prevents ref count from going down to zero when
+	 * there still are pending delayed ref.
+	 */
+	node = rb_prev(&head->node.rb_node);
+	while (1) {
+		if (!node)
+			break;
+		ref = rb_entry(node, struct btrfs_delayed_ref_node,
+				rb_node);
+		if (ref->bytenr != head->node.bytenr)
+			break;
+		if (btrfs_delayed_node_to_ref(ref)->action == action)
+			return ref;
+		node = rb_prev(node);
+	}
+	if (action == BTRFS_ADD_DELAYED_REF) {
+		action = BTRFS_DROP_DELAYED_REF;
+		goto again;
+	}
+	return NULL;
+}
+
 /*
  * this starts processing the delayed reference count updates and
  * extent insertions we have queued up so far.  count can be
@@ -1592,23 +1623,13 @@ again:
 		 * locked_ref is the head node, so we have to go one
 		 * node back for any delayed ref updates
 		 */
-		node = rb_prev(&locked_ref->node.rb_node);
-		if (node) {
-			ref = rb_entry(node, struct btrfs_delayed_ref_node,
-				       rb_node);
-			/* if the byte numbers don't match, there are
-			 * no updates for this head node.  Go ahead
-			 * and send the head node to run_one_delayed_ref
+
+		ref = select_delayed_ref(locked_ref);
+		if (!ref) {
+			/* All delayed refs have been processed, Go ahead
+			 * and send the head node to run_one_delayed_ref,
 			 * so that any accounting fixes can happen
 			 */
-			if (ref->bytenr != locked_ref->node.bytenr) {
-				ref = &locked_ref->node;
-				locked_ref = NULL;
-			}
-		} else {
-			/* there is no previous node at  all, just
-			 * process the head ref
-			 */
 			ref = &locked_ref->node;
 			locked_ref = NULL;
 		}
@@ -2996,7 +3017,6 @@ static int __free_extent(struct btrfs_tr
 	int extent_slot = 0;
 	int found_extent = 0;
 	int num_to_del = 1;
-	int cache_pending;
 	struct btrfs_extent_item *ei;
 	u32 refs;
 
@@ -3065,14 +3085,13 @@ static int __free_extent(struct btrfs_tr
 	 * we're not allowed to delete the extent item if there
 	 * are other delayed ref updates pending
 	 */
-	cache_pending = btrfs_delayed_ref_pending(trans, bytenr);
 
 	BUG_ON(refs < refs_to_drop);
 	refs -= refs_to_drop;
 	btrfs_set_extent_refs(leaf, ei, refs);
 	btrfs_mark_buffer_dirty(leaf);
 
-	if (!cache_pending && refs == 0 && found_extent &&
+	if (refs == 0 && found_extent &&
 	    path->slots[0] == extent_slot + 1) {
 		struct btrfs_extent_ref *ref;
 		ref = btrfs_item_ptr(leaf, path->slots[0],
@@ -3089,7 +3108,7 @@ static int __free_extent(struct btrfs_tr
 					    refs_to_drop);
 		BUG_ON(ret);
 		/* if refs are 0, we need to setup the path for deletion */
-		if (refs == 0 && !cache_pending) {
+		if (refs == 0) {
 			btrfs_release_path(extent_root, path);
 			ret = btrfs_search_slot(trans, extent_root, &key, path,
 						-1, 1);
@@ -3097,7 +3116,7 @@ static int __free_extent(struct btrfs_tr
 		}
 	}
 
-	if (!cache_pending && refs == 0) {
+	if (refs == 0) {
 		u64 super_used;
 		u64 root_used;
 

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2009-02-23 14:11 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-02-23 14:11 [PATCH] Process delayed back reference insertion before deletion Yan Zheng

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.