linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] Btrfs: fix the same inode id problem when doing auto defragment
@ 2012-05-24  2:42 Miao Xie
  2012-05-24 10:26 ` David Sterba
  0 siblings, 1 reply; 3+ messages in thread
From: Miao Xie @ 2012-05-24  2:42 UTC (permalink / raw)
  To: Linux Btrfs

Two files in the different subvolumes may have the same inode id, so
The rb-tree which is used to manage the defragment object must take it
into account. This patch fix this problem.

Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
---
 fs/btrfs/file.c |   45 +++++++++++++++++++++++++++++++++++----------
 1 files changed, 35 insertions(+), 10 deletions(-)

diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 23364c1..3d22fd0 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -65,6 +65,21 @@ struct inode_defrag {
 	int cycled;
 };
 
+static int __compare_inode_defrag(struct inode_defrag *defrag1,
+				  struct inode_defrag *defrag2)
+{
+	if (defrag1->root > defrag2->root)
+		return 1;
+	else if (defrag1->root < defrag2->root)
+		return -1;
+	else if (defrag1->ino > defrag2->ino)
+		return 1;
+	else if (defrag1->ino < defrag2->ino)
+		return -1;
+	else
+		return 0;
+}
+
 /* pop a record for an inode into the defrag tree.  The lock
  * must be held already
  *
@@ -87,9 +102,9 @@ static void __btrfs_add_inode_defrag(struct inode *inode,
 		parent = *p;
 		entry = rb_entry(parent, struct inode_defrag, rb_node);
 
-		if (defrag->ino < entry->ino)
+		if (__compare_inode_defrag(defrag, entry) < 0)
 			p = &parent->rb_left;
-		else if (defrag->ino > entry->ino)
+		else if (__compare_inode_defrag(defrag, entry) > 0)
 			p = &parent->rb_right;
 		else {
 			/* if we're reinserting an entry for
@@ -159,28 +174,33 @@ int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans,
 /*
  * must be called with the defrag_inodes lock held
  */
-struct inode_defrag *btrfs_find_defrag_inode(struct btrfs_fs_info *info, u64 ino,
+struct inode_defrag *btrfs_find_defrag_inode(struct btrfs_fs_info *info,
+					     u64 root, u64 ino,
 					     struct rb_node **next)
 {
 	struct inode_defrag *entry = NULL;
+	struct inode_defrag tmp;
 	struct rb_node *p;
 	struct rb_node *parent = NULL;
 
+	tmp.ino = ino;
+	tmp.root = root;
+
 	p = info->defrag_inodes.rb_node;
 	while (p) {
 		parent = p;
 		entry = rb_entry(parent, struct inode_defrag, rb_node);
 
-		if (ino < entry->ino)
+		if (__compare_inode_defrag(&tmp, entry) < 0)
 			p = parent->rb_left;
-		else if (ino > entry->ino)
+		else if (__compare_inode_defrag(&tmp, entry) > 0)
 			p = parent->rb_right;
 		else
 			return entry;
 	}
 
 	if (next) {
-		while (parent && ino > entry->ino) {
+		while (parent && __compare_inode_defrag(&tmp, entry) > 0) {
 			parent = rb_next(parent);
 			entry = rb_entry(parent, struct inode_defrag, rb_node);
 		}
@@ -202,6 +222,7 @@ int btrfs_run_defrag_inodes(struct btrfs_fs_info *fs_info)
 	struct btrfs_key key;
 	struct btrfs_ioctl_defrag_range_args range;
 	u64 first_ino = 0;
+	u64 root_objectid = 0;
 	int num_defrag;
 	int defrag_batch = 1024;
 
@@ -214,11 +235,14 @@ int btrfs_run_defrag_inodes(struct btrfs_fs_info *fs_info)
 		n = NULL;
 
 		/* find an inode to defrag */
-		defrag = btrfs_find_defrag_inode(fs_info, first_ino, &n);
+		defrag = btrfs_find_defrag_inode(fs_info, root_objectid,
+						 first_ino, &n);
 		if (!defrag) {
-			if (n)
-				defrag = rb_entry(n, struct inode_defrag, rb_node);
-			else if (first_ino) {
+			if (n) {
+				defrag = rb_entry(n, struct inode_defrag,
+						  rb_node);
+			} else if (root_objectid || first_ino) {
+				root_objectid = 0;
 				first_ino = 0;
 				continue;
 			} else {
@@ -228,6 +252,7 @@ int btrfs_run_defrag_inodes(struct btrfs_fs_info *fs_info)
 
 		/* remove it from the rbtree */
 		first_ino = defrag->ino + 1;
+		root_objectid = defrag->root;
 		rb_erase(&defrag->rb_node, &fs_info->defrag_inodes);
 
 		if (btrfs_fs_closing(fs_info) ||
-- 
1.7.6.5

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] Btrfs: fix the same inode id problem when doing auto defragment
  2012-05-24  2:42 [PATCH] Btrfs: fix the same inode id problem when doing auto defragment Miao Xie
@ 2012-05-24 10:26 ` David Sterba
  2012-05-24 10:58   ` [PATCH V2] " Miao Xie
  0 siblings, 1 reply; 3+ messages in thread
From: David Sterba @ 2012-05-24 10:26 UTC (permalink / raw)
  To: Miao Xie; +Cc: Linux Btrfs

On Thu, May 24, 2012 at 10:42:19AM +0800, Miao Xie wrote:
> @@ -87,9 +102,9 @@ static void __btrfs_add_inode_defrag(struct inode *inode,
>  		parent = *p;
>  		entry = rb_entry(parent, struct inode_defrag, rb_node);
>  
> -		if (defrag->ino < entry->ino)
> +		if (__compare_inode_defrag(defrag, entry) < 0)
>  			p = &parent->rb_left;
> -		else if (defrag->ino > entry->ino)
> +		else if (__compare_inode_defrag(defrag, entry) > 0)
>  			p = &parent->rb_right;

you don't need to call the __compare_inode_defrag twice, the comparison
result will not change under hands between the two calls.

>  		else {
>  			/* if we're reinserting an entry for
> @@ -159,28 +174,33 @@ int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans,
>  /*
>   * must be called with the defrag_inodes lock held
>   */
> -struct inode_defrag *btrfs_find_defrag_inode(struct btrfs_fs_info *info, u64 ino,
> +struct inode_defrag *btrfs_find_defrag_inode(struct btrfs_fs_info *info,
> +					     u64 root, u64 ino,
>  					     struct rb_node **next)
>  {
>  	struct inode_defrag *entry = NULL;
> +	struct inode_defrag tmp;
>  	struct rb_node *p;
>  	struct rb_node *parent = NULL;
>  
> +	tmp.ino = ino;
> +	tmp.root = root;
> +
>  	p = info->defrag_inodes.rb_node;
>  	while (p) {
>  		parent = p;
>  		entry = rb_entry(parent, struct inode_defrag, rb_node);
>  
> -		if (ino < entry->ino)
> +		if (__compare_inode_defrag(&tmp, entry) < 0)
>  			p = parent->rb_left;
> -		else if (ino > entry->ino)
> +		else if (__compare_inode_defrag(&tmp, entry) > 0)

(same here)

>  			p = parent->rb_right;
>  		else
>  			return entry;
>  	}
>  
>  	if (next) {
> -		while (parent && ino > entry->ino) {
> +		while (parent && __compare_inode_defrag(&tmp, entry) > 0) {
>  			parent = rb_next(parent);
>  			entry = rb_entry(parent, struct inode_defrag, rb_node);
>  		}


david

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH V2] Btrfs: fix the same inode id problem when doing auto defragment
  2012-05-24 10:26 ` David Sterba
@ 2012-05-24 10:58   ` Miao Xie
  0 siblings, 0 replies; 3+ messages in thread
From: Miao Xie @ 2012-05-24 10:58 UTC (permalink / raw)
  To: Linux Btrfs; +Cc: David Sterba

Two files in the different subvolumes may have the same inode id, so
The rb-tree which is used to manage the defragment object must take it
into account. This patch fix this problem.

Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
---
Changelog v1 -> v2
- cleanup unnecessary comparison.
---
 fs/btrfs/file.c |   49 +++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 39 insertions(+), 10 deletions(-)

diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 53bf2d7..0c04a62 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -65,6 +65,21 @@ struct inode_defrag {
 	int cycled;
 };
 
+static int __compare_inode_defrag(struct inode_defrag *defrag1,
+				  struct inode_defrag *defrag2)
+{
+	if (defrag1->root > defrag2->root)
+		return 1;
+	else if (defrag1->root < defrag2->root)
+		return -1;
+	else if (defrag1->ino > defrag2->ino)
+		return 1;
+	else if (defrag1->ino < defrag2->ino)
+		return -1;
+	else
+		return 0;
+}
+
 /* pop a record for an inode into the defrag tree.  The lock
  * must be held already
  *
@@ -81,15 +96,17 @@ static void __btrfs_add_inode_defrag(struct inode *inode,
 	struct inode_defrag *entry;
 	struct rb_node **p;
 	struct rb_node *parent = NULL;
+	int ret;
 
 	p = &root->fs_info->defrag_inodes.rb_node;
 	while (*p) {
 		parent = *p;
 		entry = rb_entry(parent, struct inode_defrag, rb_node);
 
-		if (defrag->ino < entry->ino)
+		ret = __compare_inode_defrag(defrag, entry);
+		if (ret < 0)
 			p = &parent->rb_left;
-		else if (defrag->ino > entry->ino)
+		else if (ret > 0)
 			p = &parent->rb_right;
 		else {
 			/* if we're reinserting an entry for
@@ -159,28 +176,35 @@ int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans,
 /*
  * must be called with the defrag_inodes lock held
  */
-struct inode_defrag *btrfs_find_defrag_inode(struct btrfs_fs_info *info, u64 ino,
+struct inode_defrag *btrfs_find_defrag_inode(struct btrfs_fs_info *info,
+					     u64 root, u64 ino,
 					     struct rb_node **next)
 {
 	struct inode_defrag *entry = NULL;
+	struct inode_defrag tmp;
 	struct rb_node *p;
 	struct rb_node *parent = NULL;
+	int ret;
+
+	tmp.ino = ino;
+	tmp.root = root;
 
 	p = info->defrag_inodes.rb_node;
 	while (p) {
 		parent = p;
 		entry = rb_entry(parent, struct inode_defrag, rb_node);
 
-		if (ino < entry->ino)
+		ret = __compare_inode_defrag(&tmp, entry);
+		if (ret < 0)
 			p = parent->rb_left;
-		else if (ino > entry->ino)
+		else if (ret > 0)
 			p = parent->rb_right;
 		else
 			return entry;
 	}
 
 	if (next) {
-		while (parent && ino > entry->ino) {
+		while (parent && __compare_inode_defrag(&tmp, entry) > 0) {
 			parent = rb_next(parent);
 			entry = rb_entry(parent, struct inode_defrag, rb_node);
 		}
@@ -202,6 +226,7 @@ int btrfs_run_defrag_inodes(struct btrfs_fs_info *fs_info)
 	struct btrfs_key key;
 	struct btrfs_ioctl_defrag_range_args range;
 	u64 first_ino = 0;
+	u64 root_objectid = 0;
 	int num_defrag;
 	int defrag_batch = 1024;
 
@@ -214,11 +239,14 @@ int btrfs_run_defrag_inodes(struct btrfs_fs_info *fs_info)
 		n = NULL;
 
 		/* find an inode to defrag */
-		defrag = btrfs_find_defrag_inode(fs_info, first_ino, &n);
+		defrag = btrfs_find_defrag_inode(fs_info, root_objectid,
+						 first_ino, &n);
 		if (!defrag) {
-			if (n)
-				defrag = rb_entry(n, struct inode_defrag, rb_node);
-			else if (first_ino) {
+			if (n) {
+				defrag = rb_entry(n, struct inode_defrag,
+						  rb_node);
+			} else if (root_objectid || first_ino) {
+				root_objectid = 0;
 				first_ino = 0;
 				continue;
 			} else {
@@ -228,6 +256,7 @@ int btrfs_run_defrag_inodes(struct btrfs_fs_info *fs_info)
 
 		/* remove it from the rbtree */
 		first_ino = defrag->ino + 1;
+		root_objectid = defrag->root;
 		rb_erase(&defrag->rb_node, &fs_info->defrag_inodes);
 
 		if (btrfs_fs_closing(fs_info))
-- 
1.7.6.5

^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2012-05-24 10:59 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-05-24  2:42 [PATCH] Btrfs: fix the same inode id problem when doing auto defragment Miao Xie
2012-05-24 10:26 ` David Sterba
2012-05-24 10:58   ` [PATCH V2] " Miao Xie

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).