diff options
author | Chris Mason <chris.mason@oracle.com> | 2008-06-25 16:01:31 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:04:04 -0400 |
commit | 3f157a2fd2ad731e1ed9964fecdc5f459f04a4a4 (patch) | |
tree | df9421e7b1d0c06d5efb8659f4317438d3d511d7 /fs/btrfs/tree-defrag.c | |
parent | 1b1e2135dc1e4efbcf25ac9ac9979316d4e1193e (diff) |
Btrfs: Online btree defragmentation fixes
The btree defragger wasn't making forward progress because the new key wasn't
being saved by the btrfs_search_forward function.
This also disables the automatic btree defrag, it wasn't scaling well to
huge filesystems. The auto-defrag needs to be done differently.
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/tree-defrag.c')
-rw-r--r-- | fs/btrfs/tree-defrag.c | 36 |
1 files changed, 19 insertions, 17 deletions
diff --git a/fs/btrfs/tree-defrag.c b/fs/btrfs/tree-defrag.c index b17693f61fbc..cc2650b06952 100644 --- a/fs/btrfs/tree-defrag.c +++ b/fs/btrfs/tree-defrag.c | |||
@@ -32,10 +32,13 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans, | |||
32 | int wret; | 32 | int wret; |
33 | int level; | 33 | int level; |
34 | int orig_level; | 34 | int orig_level; |
35 | int i; | ||
36 | int is_extent = 0; | 35 | int is_extent = 0; |
37 | int next_key_ret = 0; | 36 | int next_key_ret = 0; |
38 | u64 last_ret = 0; | 37 | u64 last_ret = 0; |
38 | u64 min_trans = 0; | ||
39 | |||
40 | if (cache_only) | ||
41 | goto out; | ||
39 | 42 | ||
40 | if (root->fs_info->extent_root == root) { | 43 | if (root->fs_info->extent_root == root) { |
41 | /* | 44 | /* |
@@ -43,10 +46,6 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans, | |||
43 | * we can't defrag the extent root without deadlock | 46 | * we can't defrag the extent root without deadlock |
44 | */ | 47 | */ |
45 | goto out; | 48 | goto out; |
46 | #if 0 | ||
47 | mutex_lock(&root->fs_info->alloc_mutex); | ||
48 | is_extent = 1; | ||
49 | #endif | ||
50 | } | 49 | } |
51 | 50 | ||
52 | if (root->ref_cows == 0 && !is_extent) | 51 | if (root->ref_cows == 0 && !is_extent) |
@@ -84,6 +83,17 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans, | |||
84 | 83 | ||
85 | path->lowest_level = 1; | 84 | path->lowest_level = 1; |
86 | path->keep_locks = 1; | 85 | path->keep_locks = 1; |
86 | if (cache_only) | ||
87 | min_trans = root->defrag_trans_start; | ||
88 | |||
89 | ret = btrfs_search_forward(root, &key, path, cache_only, min_trans); | ||
90 | if (ret < 0) | ||
91 | goto out; | ||
92 | if (ret > 0) { | ||
93 | ret = 0; | ||
94 | goto out; | ||
95 | } | ||
96 | btrfs_release_path(root, path); | ||
87 | wret = btrfs_search_slot(trans, root, &key, path, 0, 1); | 97 | wret = btrfs_search_slot(trans, root, &key, path, 0, 1); |
88 | 98 | ||
89 | if (wret < 0) { | 99 | if (wret < 0) { |
@@ -95,7 +105,8 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans, | |||
95 | goto out; | 105 | goto out; |
96 | } | 106 | } |
97 | path->slots[1] = btrfs_header_nritems(path->nodes[1]); | 107 | path->slots[1] = btrfs_header_nritems(path->nodes[1]); |
98 | next_key_ret = btrfs_find_next_key(root, path, &key, 1); | 108 | next_key_ret = btrfs_find_next_key(root, path, &key, 1, cache_only, |
109 | min_trans); | ||
99 | ret = btrfs_realloc_node(trans, root, | 110 | ret = btrfs_realloc_node(trans, root, |
100 | path->nodes[1], 0, | 111 | path->nodes[1], 0, |
101 | cache_only, &last_ret, | 112 | cache_only, &last_ret, |
@@ -106,19 +117,9 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans, | |||
106 | ret = -EAGAIN; | 117 | ret = -EAGAIN; |
107 | } | 118 | } |
108 | 119 | ||
109 | for (i = 1; i < BTRFS_MAX_LEVEL; i++) { | 120 | btrfs_release_path(root, path); |
110 | if (path->locks[i]) { | ||
111 | btrfs_tree_unlock(path->nodes[i]); | ||
112 | path->locks[i] = 0; | ||
113 | } | ||
114 | if (path->nodes[i]) { | ||
115 | free_extent_buffer(path->nodes[i]); | ||
116 | path->nodes[i] = NULL; | ||
117 | } | ||
118 | } | ||
119 | if (is_extent) | 121 | if (is_extent) |
120 | btrfs_extent_post_op(trans, root); | 122 | btrfs_extent_post_op(trans, root); |
121 | |||
122 | out: | 123 | out: |
123 | if (is_extent) | 124 | if (is_extent) |
124 | mutex_unlock(&root->fs_info->alloc_mutex); | 125 | mutex_unlock(&root->fs_info->alloc_mutex); |
@@ -138,6 +139,7 @@ done: | |||
138 | if (ret != -EAGAIN) { | 139 | if (ret != -EAGAIN) { |
139 | memset(&root->defrag_progress, 0, | 140 | memset(&root->defrag_progress, 0, |
140 | sizeof(root->defrag_progress)); | 141 | sizeof(root->defrag_progress)); |
142 | root->defrag_trans_start = trans->transid; | ||
141 | } | 143 | } |
142 | return ret; | 144 | return ret; |
143 | } | 145 | } |