aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/tree-defrag.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/tree-defrag.c')
-rw-r--r--fs/btrfs/tree-defrag.c36
1 files changed, 29 insertions, 7 deletions
diff --git a/fs/btrfs/tree-defrag.c b/fs/btrfs/tree-defrag.c
index 7ea66b4aa5c2..a09064a9a41c 100644
--- a/fs/btrfs/tree-defrag.c
+++ b/fs/btrfs/tree-defrag.c
@@ -42,16 +42,20 @@ static void reada_defrag(struct btrfs_root *root,
42static int defrag_walk_down(struct btrfs_trans_handle *trans, 42static int defrag_walk_down(struct btrfs_trans_handle *trans,
43 struct btrfs_root *root, 43 struct btrfs_root *root,
44 struct btrfs_path *path, int *level, 44 struct btrfs_path *path, int *level,
45 int cache_only) 45 int cache_only, u64 *last_ret)
46{ 46{
47 struct buffer_head *next; 47 struct buffer_head *next;
48 struct buffer_head *cur; 48 struct buffer_head *cur;
49 u64 blocknr; 49 u64 blocknr;
50 int ret = 0; 50 int ret = 0;
51 int is_extent = 0;
51 52
52 WARN_ON(*level < 0); 53 WARN_ON(*level < 0);
53 WARN_ON(*level >= BTRFS_MAX_LEVEL); 54 WARN_ON(*level >= BTRFS_MAX_LEVEL);
54 55
56 if (root->fs_info->extent_root == root)
57 is_extent = 1;
58
55 while(*level > 0) { 59 while(*level > 0) {
56 WARN_ON(*level < 0); 60 WARN_ON(*level < 0);
57 WARN_ON(*level >= BTRFS_MAX_LEVEL); 61 WARN_ON(*level >= BTRFS_MAX_LEVEL);
@@ -70,7 +74,10 @@ static int defrag_walk_down(struct btrfs_trans_handle *trans,
70 if (*level == 1) { 74 if (*level == 1) {
71 ret = btrfs_realloc_node(trans, root, 75 ret = btrfs_realloc_node(trans, root,
72 path->nodes[*level], 76 path->nodes[*level],
73 cache_only); 77 cache_only, last_ret);
78 if (is_extent)
79 btrfs_extent_post_op(trans, root);
80
74 break; 81 break;
75 } 82 }
76 blocknr = btrfs_node_blockptr(btrfs_buffer_node(cur), 83 blocknr = btrfs_node_blockptr(btrfs_buffer_node(cur),
@@ -90,8 +97,13 @@ static int defrag_walk_down(struct btrfs_trans_handle *trans,
90 ret = btrfs_cow_block(trans, root, next, path->nodes[*level], 97 ret = btrfs_cow_block(trans, root, next, path->nodes[*level],
91 path->slots[*level], &next); 98 path->slots[*level], &next);
92 BUG_ON(ret); 99 BUG_ON(ret);
93 ret = btrfs_realloc_node(trans, root, next, cache_only); 100 ret = btrfs_realloc_node(trans, root, next, cache_only,
101 last_ret);
94 BUG_ON(ret); 102 BUG_ON(ret);
103
104 if (is_extent)
105 btrfs_extent_post_op(trans, root);
106
95 WARN_ON(*level <= 0); 107 WARN_ON(*level <= 0);
96 if (path->nodes[*level-1]) 108 if (path->nodes[*level-1])
97 btrfs_block_release(root, path->nodes[*level-1]); 109 btrfs_block_release(root, path->nodes[*level-1]);
@@ -148,10 +160,14 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
148 int level; 160 int level;
149 int orig_level; 161 int orig_level;
150 int i; 162 int i;
163 int is_extent = 0;
164 u64 last_ret = 0;
165
166 if (root->fs_info->extent_root == root)
167 is_extent = 1;
151 168
152 if (root->ref_cows == 0) { 169 if (root->ref_cows == 0 && !is_extent)
153 goto out; 170 goto out;
154 }
155 path = btrfs_alloc_path(); 171 path = btrfs_alloc_path();
156 if (!path) 172 if (!path)
157 return -ENOMEM; 173 return -ENOMEM;
@@ -165,16 +181,21 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
165 get_bh(root->node); 181 get_bh(root->node);
166 ret = btrfs_cow_block(trans, root, root->node, NULL, 0, &tmp); 182 ret = btrfs_cow_block(trans, root, root->node, NULL, 0, &tmp);
167 BUG_ON(ret); 183 BUG_ON(ret);
168 ret = btrfs_realloc_node(trans, root, root->node, cache_only); 184 ret = btrfs_realloc_node(trans, root, root->node, cache_only,
185 &last_ret);
169 BUG_ON(ret); 186 BUG_ON(ret);
170 path->nodes[level] = root->node; 187 path->nodes[level] = root->node;
171 path->slots[level] = 0; 188 path->slots[level] = 0;
189 if (is_extent)
190 btrfs_extent_post_op(trans, root);
172 } else { 191 } else {
173 level = root->defrag_level; 192 level = root->defrag_level;
174 path->lowest_level = level; 193 path->lowest_level = level;
175 wret = btrfs_search_slot(trans, root, &root->defrag_progress, 194 wret = btrfs_search_slot(trans, root, &root->defrag_progress,
176 path, 0, 1); 195 path, 0, 1);
177 196
197 if (is_extent)
198 btrfs_extent_post_op(trans, root);
178 if (wret < 0) { 199 if (wret < 0) {
179 ret = wret; 200 ret = wret;
180 goto out; 201 goto out;
@@ -188,7 +209,8 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
188 } 209 }
189 210
190 while(1) { 211 while(1) {
191 wret = defrag_walk_down(trans, root, path, &level, cache_only); 212 wret = defrag_walk_down(trans, root, path, &level, cache_only,
213 &last_ret);
192 if (wret > 0) 214 if (wret > 0)
193 break; 215 break;
194 if (wret < 0) 216 if (wret < 0)