[PATCH 2/4] Add shared reference cache

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello,

This patch adds shared reference cache support. The new space
balancing code plays with multiple subvols at the same time, So
the old per-subvol reference cache isn't fit for it.

Regards
Yan Zheng

---
diff -r 47aa0c51998a ctree.h
--- a/ctree.h	Thu Sep 25 16:00:36 2008 +0800
+++ b/ctree.h	Thu Sep 25 16:02:11 2008 +0800
@@ -80,6 +80,10 @@
 /* does write ahead logging to speed up fsyncs */
 #define BTRFS_TREE_LOG_OBJECTID -6ULL
 #define BTRFS_TREE_LOG_FIXUP_OBJECTID -7ULL
+
+/* for space balancing */
+#define BTRFS_TREE_RELOC_OBJECTID -8ULL
+#define BTRFS_DATA_RELOC_TREE_OBJECTID -9ULL
 
 /* dummy objectid represents multiple objectids */
 #define BTRFS_MULTIPLE_OBJECTIDS -255ULL
@@ -539,6 +543,12 @@
 	struct list_head list;
 };
 
+struct btrfs_leaf_ref_tree {
+	struct rb_root root;
+	struct list_head list;
+	spinlock_t lock;
+};
+
 struct btrfs_device;
 struct btrfs_fs_devices;
 struct btrfs_fs_info {
@@ -637,6 +647,8 @@
 	struct task_struct *cleaner_kthread;
 	int thread_pool_size;
 
+	struct btrfs_leaf_ref_tree shared_ref_tree;
+
 	struct kobject super_kobj;
 	struct completion kobj_unregister;
 	int do_barriers;
@@ -668,13 +680,6 @@
 	u64 system_alloc_profile;
 
 	void *bdev_holder;
-};
-
-struct btrfs_leaf_ref_tree {
-	struct rb_root root;
-	struct btrfs_leaf_ref *last;
-	struct list_head list;
-	spinlock_t lock;
 };
 
 /*
diff -r 47aa0c51998a disk-io.c
--- a/disk-io.c	Thu Sep 25 16:00:36 2008 +0800
+++ b/disk-io.c	Thu Sep 25 16:02:11 2008 +0800
@@ -1430,6 +1430,8 @@
 			     fs_info->btree_inode->i_mapping, GFP_NOFS);
 	fs_info->do_barriers = 1;
 
+	btrfs_leaf_ref_tree_init(&fs_info->shared_ref_tree);
+
 	BTRFS_I(fs_info->btree_inode)->root = tree_root;
 	memset(&BTRFS_I(fs_info->btree_inode)->location, 0,
 	       sizeof(struct btrfs_key));
diff -r 47aa0c51998a extent-tree.c
--- a/extent-tree.c	Thu Sep 25 16:00:36 2008 +0800
+++ b/extent-tree.c	Thu Sep 25 16:02:11 2008 +0800
@@ -1091,15 +1091,25 @@
 int btrfs_cache_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 		    struct extent_buffer *buf, u32 nr_extents)
 {
-	u32 nritems;
 	struct btrfs_key key;
 	struct btrfs_file_extent_item *fi;
-	int i;
-	int level;
-	int ret = 0;
+	u64 root_gen;
+	u32 nritems;
+	int i;
+	int level;
+	int ret = 0;
+	int shared = 0;
 
 	if (!root->ref_cows)
 		return 0;
+
+	if (root->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID) {
+		shared = 0;
+		root_gen = root->root_key.offset;
+	} else {
+		shared = 1;
+		root_gen = trans->transid - 1;
+	}
 
 	level = btrfs_header_level(buf);
 	nritems = btrfs_header_nritems(buf);
@@ -1114,7 +1124,7 @@
 			goto out;
 		}
 
-		ref->root_gen = root->root_key.offset;
+		ref->root_gen = root_gen;
 		ref->bytenr = buf->start;
 		ref->owner = btrfs_header_owner(buf);
 		ref->generation = btrfs_header_generation(buf);
@@ -1143,8 +1153,7 @@
 			info++;
 		}
 
-		BUG_ON(!root->ref_tree);
-		ret = btrfs_add_leaf_ref(root, ref);
+		ret = btrfs_add_leaf_ref(root, ref, shared);
 		WARN_ON(ret);
 		btrfs_free_leaf_ref(root, ref);
 	}
diff -r 47aa0c51998a ref-cache.c
--- a/ref-cache.c	Thu Sep 25 16:00:36 2008 +0800
+++ b/ref-cache.c	Thu Sep 25 16:02:11 2008 +0800
@@ -78,7 +78,6 @@
 	}
 
 	entry = rb_entry(node, struct btrfs_leaf_ref, rb_node);
-	entry->in_tree = 1;
 	rb_link_node(node, parent, p);
 	rb_insert_color(node, root);
 	return NULL;
@@ -103,23 +102,29 @@
 	return NULL;
 }
 
-int btrfs_remove_leaf_refs(struct btrfs_root *root, u64 max_root_gen)
+int btrfs_remove_leaf_refs(struct btrfs_root *root, u64 max_root_gen,
+			   int shared)
 {
 	struct btrfs_leaf_ref *ref = NULL;
 	struct btrfs_leaf_ref_tree *tree = root->ref_tree;
 
+	if (shared)
+		tree = &root->fs_info->shared_ref_tree;
 	if (!tree)
 		return 0;
 
 	spin_lock(&tree->lock);
 	while(!list_empty(&tree->list)) {
 		ref = list_entry(tree->list.next, struct btrfs_leaf_ref, list);
-		BUG_ON(!ref->in_tree);
+		BUG_ON(ref->tree != tree);
 		if (ref->root_gen > max_root_gen)
 			break;
+		if (!xchg(&ref->in_tree, 0)) {
+			cond_resched_lock(&tree->lock);
+			continue;
+		}
 
 		rb_erase(&ref->rb_node, &tree->root);
-		ref->in_tree = 0;
 		list_del_init(&ref->list);
 
 		spin_unlock(&tree->lock);
@@ -137,25 +142,34 @@
 	struct rb_node *rb;
 	struct btrfs_leaf_ref *ref = NULL;
 	struct btrfs_leaf_ref_tree *tree = root->ref_tree;
-
-	if (!tree)
-		return NULL;
-
-	spin_lock(&tree->lock);
-	rb = tree_search(&tree->root, bytenr);
-	if (rb)
-		ref = rb_entry(rb, struct btrfs_leaf_ref, rb_node);
-	if (ref)
-		atomic_inc(&ref->usage);
-	spin_unlock(&tree->lock);
-	return ref;
+again:
+	if (tree) {
+		spin_lock(&tree->lock);
+		rb = tree_search(&tree->root, bytenr);
+		if (rb)
+			ref = rb_entry(rb, struct btrfs_leaf_ref, rb_node);
+		if (ref)
+			atomic_inc(&ref->usage);
+		spin_unlock(&tree->lock);
+		if (ref)
+			return ref;
+	}
+	if (tree != &root->fs_info->shared_ref_tree) {
+		tree = &root->fs_info->shared_ref_tree;
+		goto again;
+	}
+	return NULL;
 }
 
-int btrfs_add_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref)
+int btrfs_add_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref,
+		       int shared)
 {
 	int ret = 0;
 	struct rb_node *rb;
 	struct btrfs_leaf_ref_tree *tree = root->ref_tree;
+
+	if (shared)
+		tree = &root->fs_info->shared_ref_tree;
 
 	spin_lock(&tree->lock);
 	rb = tree_insert(&tree->root, ref->bytenr, &ref->rb_node);
@@ -163,6 +177,8 @@
 		ret = -EEXIST;
 	} else {
 		atomic_inc(&ref->usage);
+		ref->tree = tree;
+		ref->in_tree = 1;
 		list_add_tail(&ref->list, &tree->list);
 	}
 	spin_unlock(&tree->lock);
@@ -171,13 +187,15 @@
 
 int btrfs_remove_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref)
 {
-	struct btrfs_leaf_ref_tree *tree = root->ref_tree;
+	struct btrfs_leaf_ref_tree *tree;
 
-	BUG_ON(!ref->in_tree);
+	if (!xchg(&ref->in_tree, 0))
+		return 0;
+
+	tree = ref->tree;
 	spin_lock(&tree->lock);
 
 	rb_erase(&ref->rb_node, &tree->root);
-	ref->in_tree = 0;
 	list_del_init(&ref->list);
 
 	spin_unlock(&tree->lock);
diff -r 47aa0c51998a ref-cache.h
--- a/ref-cache.h	Thu Sep 25 16:00:36 2008 +0800
+++ b/ref-cache.h	Thu Sep 25 16:02:11 2008 +0800
@@ -27,6 +27,7 @@
 
 struct btrfs_leaf_ref {
 	struct rb_node rb_node;
+	struct btrfs_leaf_ref_tree *tree;
 	int in_tree;
 	atomic_t usage;
 
@@ -64,8 +65,10 @@
 void btrfs_free_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref);
 struct btrfs_leaf_ref *btrfs_lookup_leaf_ref(struct btrfs_root *root,
 					     u64 bytenr);
-int btrfs_add_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref);
-int btrfs_remove_leaf_refs(struct btrfs_root *root, u64 max_root_gen);
+int btrfs_add_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref,
+		       int shared);
+int btrfs_remove_leaf_refs(struct btrfs_root *root, u64 max_root_gen,
+			   int shared);
 int btrfs_remove_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref);
 
 #endif
diff -r 47aa0c51998a transaction.c
--- a/transaction.c	Thu Sep 25 16:00:36 2008 +0800
+++ b/transaction.c	Thu Sep 25 16:02:11 2008 +0800
@@ -650,7 +650,7 @@
 		ret = btrfs_end_transaction(trans, tree_root);
 		BUG_ON(ret);
 
-		ret = btrfs_remove_leaf_refs(root, max_useless);
+		ret = btrfs_remove_leaf_refs(root, max_useless, 0);
 		BUG_ON(ret);
 
 		free_extent_buffer(dirty->root->node);
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Filesystem Development]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux