* [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).