summaryrefslogtreecommitdiffstats
path: root/fs/btrfs/tree-defrag.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-05-24 20:04:53 +0200
committerChris Mason <chris.mason@oracle.com>2008-09-25 17:04:03 +0200
commit0ef3e66b6700eb8f052daa8b89443ff872fbbdfc (patch)
tree26bce57770b4f093199b6f87ab8ed3a54e951337 /fs/btrfs/tree-defrag.c
parentBtrfs: Use kzalloc on the fs_devices allocation (diff)
downloadlinux-0ef3e66b6700eb8f052daa8b89443ff872fbbdfc.tar.xz
linux-0ef3e66b6700eb8f052daa8b89443ff872fbbdfc.zip
Btrfs: Allocator fix variety pack
* Force chunk allocation when find_free_extent has to do a full scan * Record the max key at the start of defrag so it doesn't run forever * Block groups might not be contiguous, make a forward search for the next block group in extent-tree.c * Get rid of extra checks for total fs size * Fix relocate_one_reference to avoid relocating the same file data block twice when referenced by an older transaction * Use the open device count when allocating chunks so that we don't try to allocate from devices that don't exist Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/tree-defrag.c')
-rw-r--r--fs/btrfs/tree-defrag.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/fs/btrfs/tree-defrag.c b/fs/btrfs/tree-defrag.c
index c02e2bf2f028..155961c7b4d5 100644
--- a/fs/btrfs/tree-defrag.c
+++ b/fs/btrfs/tree-defrag.c
@@ -198,6 +198,13 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
goto out;
}
if (root->defrag_progress.objectid == 0) {
+ u32 nritems;
+
+ nritems = btrfs_header_nritems(root->node);
+ root->defrag_max.objectid = 0;
+ /* from above we know this is not a leaf */
+ btrfs_node_key_to_cpu(root->node, &root->defrag_max,
+ nritems - 1);
extent_buffer_get(root->node);
ret = btrfs_cow_block(trans, root, root->node, NULL, 0, &tmp);
BUG_ON(ret);
@@ -254,6 +261,16 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
out:
if (path)
btrfs_free_path(path);
+ if (ret == -EAGAIN) {
+ if (root->defrag_max.objectid > root->defrag_progress.objectid)
+ goto done;
+ if (root->defrag_max.type > root->defrag_progress.type)
+ goto done;
+ if (root->defrag_max.offset > root->defrag_progress.offset)
+ goto done;
+ ret = 0;
+ }
+done:
if (ret != -EAGAIN) {
memset(&root->defrag_progress, 0,
sizeof(root->defrag_progress));