[Btrfs-devel][PATCH]Add delay allocation accounting

Yan Zheng yanzheng at 21cn.com
Sun Nov 11 19:04:09 PST 2007


Hello,

This patch adds two hooks to 'extent_map_ops'. 'set_extent_bit' and
'set_extent_bit' call the hook functions before they modify
'extent_state->state'. The last parameter of the hook functions
indicates bits that will be inverted.  By using these hooks, do delay
allocation accounting is easy.

Regards
YZ
---
diff -r dc03d8df4762 ctree.h
--- a/ctree.h	Wed Nov 07 21:08:16 2007 -0500
+++ b/ctree.h	Mon Nov 12 11:03:16 2007 +0800
@@ -323,6 +323,9 @@ struct btrfs_fs_info {
 	struct completion kobj_unregister;
 	int do_barriers;
 	int closing;
+
+	u64 total_delalloc;
+	spinlock_t stat_lock;
 };

 /*
diff -r dc03d8df4762 disk-io.c
--- a/disk-io.c	Wed Nov 07 21:08:16 2007 -0500
+++ b/disk-io.c	Mon Nov 12 11:03:16 2007 +0800
@@ -570,6 +570,9 @@ struct btrfs_root *open_ctree(struct sup
 	fs_info->do_barriers = 1;
 	fs_info->closing = 0;

+	fs_info->total_delalloc = 0;
+	spin_lock_init(&fs_info->stat_lock);
+
 	INIT_DELAYED_WORK(&fs_info->trans_work, btrfs_transaction_cleaner);
 	BTRFS_I(fs_info->btree_inode)->root = tree_root;
 	memset(&BTRFS_I(fs_info->btree_inode)->location, 0,
diff -r dc03d8df4762 extent_map.c
--- a/extent_map.c	Wed Nov 07 21:08:16 2007 -0500
+++ b/extent_map.c	Mon Nov 12 11:03:16 2007 +0800
@@ -502,7 +502,15 @@ int clear_extent_bit(struct extent_map_t
 	unsigned long flags;
 	int err;
 	int set = 0;
-
+	int clear = bits;
+	void (*hook)(struct extent_map_tree *, struct extent_state *, int);
+
+	if (delete)
+		clear = -1;
+	if (tree->ops)
+		hook = tree->ops->clear_extent_bits_hook;
+	else
+		hook = NULL;
 again:
 	if (!prealloc && (mask & __GFP_WAIT)) {
 		prealloc = alloc_extent_state(mask);
@@ -546,6 +554,8 @@ again:
 		if (err)
 			goto out;
 		if (state->end <= end) {
+			if (hook)
+				hook(tree, state, clear & state->state);
 			start = state->end + 1;
 			set |= clear_state_bit(tree, state, bits,
 					wake, delete);
@@ -566,12 +576,16 @@ again:

 		if (wake)
 			wake_up(&state->wq);
+		if (hook)
+			hook(tree, prealloc, clear & prealloc->state);
 		set |= clear_state_bit(tree, prealloc, bits,
 				       wake, delete);
 		prealloc = NULL;
 		goto out;
 	}

+	if (hook)
+		hook(tree, state, clear & state->state);
 	start = state->end + 1;
 	set |= clear_state_bit(tree, state, bits, wake, delete);
 	goto search_again;
@@ -677,6 +691,12 @@ int set_extent_bit(struct extent_map_tre
 	int set;
 	u64 last_start;
 	u64 last_end;
+	void (*hook)(struct extent_map_tree *, struct extent_state *, int);
+
+	if (tree->ops)
+		hook = tree->ops->set_extent_bits_hook;
+	else
+		hook = NULL;
 again:
 	if (!prealloc && (mask & __GFP_WAIT)) {
 		prealloc = alloc_extent_state(mask);
@@ -691,6 +711,11 @@ again:
 	 */
 	node = tree_search(&tree->state, start);
 	if (!node) {
+		if (hook) {
+			prealloc->start = start;
+			prealloc->end = end;
+			hook(tree, prealloc, bits);
+		}
 		err = insert_state(tree, prealloc, start, end, bits);
 		prealloc = NULL;
 		BUG_ON(err == -EEXIST);
@@ -714,6 +739,8 @@ again:
 			err = -EEXIST;
 			goto out;
 		}
+		if (hook)
+			hook(tree, state, bits ^ set);
 		state->state |= bits;
 		start = state->end + 1;
 		merge_state(tree, state);
@@ -749,6 +776,8 @@ again:
 		if (err)
 			goto out;
 		if (state->end <= end) {
+			if (hook)
+				hook(tree, state, bits ^ set);
 			state->state |= bits;
 			start = state->end + 1;
 			merge_state(tree, state);
@@ -770,6 +799,11 @@ again:
 			this_end = end;
 		else
 			this_end = last_start -1;
+		if (hook) {
+			prealloc->start = start;
+			prealloc->end = this_end;
+			hook(tree, prealloc, bits);
+		}
 		err = insert_state(tree, prealloc, start, this_end,
 				   bits);
 		prealloc = NULL;
@@ -794,7 +828,8 @@ again:
 		}
 		err = split_state(tree, state, prealloc, end + 1);
 		BUG_ON(err == -EEXIST);
-
+		if (hook)
+			hook(tree, prealloc, bits ^ set);
 		prealloc->state |= bits;
 		merge_state(tree, prealloc);
 		prealloc = NULL;
diff -r dc03d8df4762 extent_map.h
--- a/extent_map.h	Wed Nov 07 21:08:16 2007 -0500
+++ b/extent_map.h	Mon Nov 12 11:03:16 2007 +0800
@@ -27,6 +27,9 @@
 #define EXTENT_PAGE_PRIVATE 1
 #define EXTENT_PAGE_PRIVATE_FIRST_PAGE 3

+struct extent_map;
+struct extent_state;
+struct extent_map_tree;

 struct extent_map_ops {
 	int (*fill_delalloc)(struct inode *inode, u64 start, u64 end);
@@ -34,6 +37,10 @@ struct extent_map_ops {
 	int (*readpage_io_hook)(struct page *page, u64 start, u64 end);
 	int (*readpage_end_io_hook)(struct page *page, u64 start, u64 end);
 	void (*writepage_end_io_hook)(struct page *page, u64 start, u64 end);
+	void (*set_extent_bits_hook)(struct extent_map_tree *tree,
+				struct extent_state *state, int diff);
+	void (*clear_extent_bits_hook)(struct extent_map_tree *tree,
+				struct extent_state *state, int diff);
 };

 struct extent_map_tree {
diff -r dc03d8df4762 inode.c
--- a/inode.c	Wed Nov 07 21:08:16 2007 -0500
+++ b/inode.c	Mon Nov 12 11:03:16 2007 +0800
@@ -196,6 +196,36 @@ zeroit:
 	kunmap_atomic(kaddr, KM_IRQ0);
 	local_irq_restore(flags);
 	return 0;
+}
+
+void btrfs_set_extent_bits_hook(struct extent_map_tree *tree,
+				struct extent_state *state, int diff)
+{
+	struct inode *inode = tree->mapping->host;
+	struct btrfs_fs_info *info = BTRFS_I(inode)->root->fs_info;
+
+	/* local irq has already been disabled */
+	if (diff & EXTENT_DELALLOC) {
+		spin_lock(&info->stat_lock);
+		info->total_delalloc += state->end + 1 - state->start;
+		spin_unlock(&info->stat_lock);
+	}
+	return;
+}
+
+void btrfs_clear_extent_bits_hook(struct extent_map_tree *tree,
+				  struct extent_state *state, int diff)
+{
+	struct inode *inode = tree->mapping->host;
+	struct btrfs_fs_info *info = BTRFS_I(inode)->root->fs_info;
+	
+	/* local irq has already been disabled */
+	if (diff & EXTENT_DELALLOC) {
+		spin_lock(&info->stat_lock);
+		info->total_delalloc -= state->end + 1 - state->start;
+		spin_unlock(&info->stat_lock);
+	}
+	return;
 }

 void btrfs_read_locked_inode(struct inode *inode)
@@ -2531,6 +2561,8 @@ static struct extent_map_ops btrfs_exten
 	.writepage_io_hook = btrfs_writepage_io_hook,
 	.readpage_io_hook = btrfs_readpage_io_hook,
 	.readpage_end_io_hook = btrfs_readpage_end_io_hook,
+	.set_extent_bits_hook = btrfs_set_extent_bits_hook,
+	.clear_extent_bits_hook = btrfs_clear_extent_bits_hook,
 };

 static struct address_space_operations btrfs_aops = {



More information about the Btrfs-devel mailing list