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>
diff --git a/fs/btrfs/tree-defrag.c b/fs/btrfs/tree-defrag.c
index c02e2bf..155961c 100644
--- a/fs/btrfs/tree-defrag.c
+++ b/fs/btrfs/tree-defrag.c
@@ -198,6 +198,13 @@
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 @@
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));