aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-11-06 10:26:24 -0500
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:03:57 -0400
commit081e95736d9118a96e9f6dcc5cec02dc75c9e1cb (patch)
tree41c1b692a0ba44223cadae5d78bc3446f963dca1 /fs
parentBtrfs: Properly update free space cache in __free_extent (diff)
downloadlinux-dev-081e95736d9118a96e9f6dcc5cec02dc75c9e1cb.tar.xz
linux-dev-081e95736d9118a96e9f6dcc5cec02dc75c9e1cb.zip
Btrfs: Make defrag check nodes against the progress key to prevent repeating work
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/ctree.c56
-rw-r--r--fs/btrfs/tree-defrag.c3
2 files changed, 34 insertions, 25 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index eef9c92f86d5..ea9b46699349 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -161,6 +161,31 @@ static int close_blocks(u64 blocknr, u64 other, u32 blocksize)
return 0;
}
+/*
+ * compare two keys in a memcmp fashion
+ */
+static int comp_keys(struct btrfs_disk_key *disk, struct btrfs_key *k2)
+{
+ struct btrfs_key k1;
+
+ btrfs_disk_key_to_cpu(&k1, disk);
+
+ if (k1.objectid > k2->objectid)
+ return 1;
+ if (k1.objectid < k2->objectid)
+ return -1;
+ if (k1.type > k2->type)
+ return 1;
+ if (k1.type < k2->type)
+ return -1;
+ if (k1.offset > k2->offset)
+ return 1;
+ if (k1.offset < k2->offset)
+ return -1;
+ return 0;
+}
+
+
int btrfs_realloc_node(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct extent_buffer *parent,
int start_slot, int cache_only, u64 *last_ret,
@@ -179,6 +204,8 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
int parent_level;
int uptodate;
u32 blocksize;
+ int progress_passed = 0;
+ struct btrfs_disk_key disk_key;
parent_level = btrfs_header_level(parent);
if (cache_only && parent_level != 1)
@@ -213,6 +240,11 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
&parent->map_start, &parent->map_len,
KM_USER1);
}
+ btrfs_node_key(parent, &disk_key, i);
+ if (!progress_passed && comp_keys(&disk_key, progress) < 0)
+ continue;
+
+ progress_passed = 1;
blocknr = btrfs_node_blockptr(parent, i);
if (last_block == 0)
last_block = blocknr;
@@ -292,30 +324,6 @@ static inline unsigned int leaf_data_end(struct btrfs_root *root,
return btrfs_item_offset_nr(leaf, nr - 1);
}
-/*
- * compare two keys in a memcmp fashion
- */
-static int comp_keys(struct btrfs_disk_key *disk, struct btrfs_key *k2)
-{
- struct btrfs_key k1;
-
- btrfs_disk_key_to_cpu(&k1, disk);
-
- if (k1.objectid > k2->objectid)
- return 1;
- if (k1.objectid < k2->objectid)
- return -1;
- if (k1.type > k2->type)
- return 1;
- if (k1.type < k2->type)
- return -1;
- if (k1.offset > k2->offset)
- return 1;
- if (k1.offset < k2->offset)
- return -1;
- return 0;
-}
-
static int check_node(struct btrfs_root *root, struct btrfs_path *path,
int level)
{
diff --git a/fs/btrfs/tree-defrag.c b/fs/btrfs/tree-defrag.c
index 65ef12351566..6ef1ba5f9c2f 100644
--- a/fs/btrfs/tree-defrag.c
+++ b/fs/btrfs/tree-defrag.c
@@ -227,7 +227,8 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
break;
if (wret < 0)
ret = wret;
- ret = -EAGAIN;
+ else
+ ret = -EAGAIN;
break;
}
for (i = 0; i <= orig_level; i++) {