diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-11-06 10:26:24 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:03:57 -0400 |
commit | 081e95736d9118a96e9f6dcc5cec02dc75c9e1cb (patch) | |
tree | 41c1b692a0ba44223cadae5d78bc3446f963dca1 /fs | |
parent | c549228ff63498025bf0b065c5a5909a06f21647 (diff) |
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.c | 56 | ||||
-rw-r--r-- | fs/btrfs/tree-defrag.c | 3 |
2 files changed, 34 insertions, 25 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index eef9c92f86d..ea9b4669934 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 65ef1235156..6ef1ba5f9c2 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++) { |