aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-08-10 14:06:19 -0400
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-08-10 14:06:19 -0400
commite9d0b13b5bbb58c9b840e407a8d181442f799966 (patch)
treed51a7e111a824e883c347c83745109400231de1c
parent409eb95d7f6632d5af32b795244ce68a29e49319 (diff)
Btrfs: Btree defrag on the extent-mapping tree as well
Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r--fs/btrfs/ctree.c18
-rw-r--r--fs/btrfs/ctree.h4
-rw-r--r--fs/btrfs/extent-tree.c28
-rw-r--r--fs/btrfs/inode.c23
-rw-r--r--fs/btrfs/super.c2
-rw-r--r--fs/btrfs/transaction.c91
-rw-r--r--fs/btrfs/transaction.h2
-rw-r--r--fs/btrfs/tree-defrag.c36
8 files changed, 125 insertions, 79 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index c7e47e77723..ee1ae00d282 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -99,7 +99,6 @@ static int __btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root
99 if (ret) 99 if (ret)
100 return ret; 100 return ret;
101 } else { 101 } else {
102 WARN_ON(!root->ref_cows);
103 clean_tree_block(trans, root, buf); 102 clean_tree_block(trans, root, buf);
104 } 103 }
105 104
@@ -162,13 +161,14 @@ static int close_blocks(u64 blocknr, u64 other)
162 161
163int btrfs_realloc_node(struct btrfs_trans_handle *trans, 162int btrfs_realloc_node(struct btrfs_trans_handle *trans,
164 struct btrfs_root *root, struct buffer_head *parent, 163 struct btrfs_root *root, struct buffer_head *parent,
165 int cache_only) 164 int cache_only, u64 *last_ret)
166{ 165{
167 struct btrfs_node *parent_node; 166 struct btrfs_node *parent_node;
168 struct buffer_head *cur_bh; 167 struct buffer_head *cur_bh;
169 struct buffer_head *tmp_bh; 168 struct buffer_head *tmp_bh;
170 u64 blocknr; 169 u64 blocknr;
171 u64 search_start = 0; 170 u64 search_start = *last_ret;
171 u64 last_block = 0;
172 u64 other; 172 u64 other;
173 u32 parent_nritems; 173 u32 parent_nritems;
174 int start_slot; 174 int start_slot;
@@ -198,6 +198,8 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
198 for (i = start_slot; i < end_slot; i++) { 198 for (i = start_slot; i < end_slot; i++) {
199 int close = 1; 199 int close = 1;
200 blocknr = btrfs_node_blockptr(parent_node, i); 200 blocknr = btrfs_node_blockptr(parent_node, i);
201 if (last_block == 0)
202 last_block = blocknr;
201 if (i > 0) { 203 if (i > 0) {
202 other = btrfs_node_blockptr(parent_node, i - 1); 204 other = btrfs_node_blockptr(parent_node, i - 1);
203 close = close_blocks(blocknr, other); 205 close = close_blocks(blocknr, other);
@@ -206,8 +208,10 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
206 other = btrfs_node_blockptr(parent_node, i + 1); 208 other = btrfs_node_blockptr(parent_node, i + 1);
207 close = close_blocks(blocknr, other); 209 close = close_blocks(blocknr, other);
208 } 210 }
209 if (close) 211 if (close) {
212 last_block = blocknr;
210 continue; 213 continue;
214 }
211 215
212 cur_bh = btrfs_find_tree_block(root, blocknr); 216 cur_bh = btrfs_find_tree_block(root, blocknr);
213 if (!cur_bh || !buffer_uptodate(cur_bh) || 217 if (!cur_bh || !buffer_uptodate(cur_bh) ||
@@ -219,9 +223,9 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
219 brelse(cur_bh); 223 brelse(cur_bh);
220 cur_bh = read_tree_block(root, blocknr); 224 cur_bh = read_tree_block(root, blocknr);
221 } 225 }
222 if (search_start == 0) { 226 if (search_start == 0)
223 search_start = bh_blocknr(cur_bh) & ~((u64)65535); 227 search_start = last_block & ~((u64)65535);
224 } 228
225 err = __btrfs_cow_block(trans, root, cur_bh, parent, i, 229 err = __btrfs_cow_block(trans, root, cur_bh, parent, i,
226 &tmp_bh, search_start, 230 &tmp_bh, search_start,
227 min(8, end_slot - i)); 231 min(8, end_slot - i));
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 59e09e37ab9..d3cd564b3b3 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -1019,6 +1019,8 @@ static inline void btrfs_memmove(struct btrfs_root *root,
1019 btrfs_item_offset((leaf)->items + (slot)))) 1019 btrfs_item_offset((leaf)->items + (slot))))
1020 1020
1021/* extent-tree.c */ 1021/* extent-tree.c */
1022int btrfs_extent_post_op(struct btrfs_trans_handle *trans,
1023 struct btrfs_root *root);
1022int btrfs_copy_pinned(struct btrfs_root *root, struct radix_tree_root *copy); 1024int btrfs_copy_pinned(struct btrfs_root *root, struct radix_tree_root *copy);
1023struct btrfs_block_group_cache *btrfs_lookup_block_group(struct 1025struct btrfs_block_group_cache *btrfs_lookup_block_group(struct
1024 btrfs_fs_info *info, 1026 btrfs_fs_info *info,
@@ -1066,7 +1068,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
1066 ins_len, int cow); 1068 ins_len, int cow);
1067int btrfs_realloc_node(struct btrfs_trans_handle *trans, 1069int btrfs_realloc_node(struct btrfs_trans_handle *trans,
1068 struct btrfs_root *root, struct buffer_head *parent, 1070 struct btrfs_root *root, struct buffer_head *parent,
1069 int cache_only); 1071 int cache_only, u64 *last_ret);
1070void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p); 1072void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p);
1071struct btrfs_path *btrfs_alloc_path(void); 1073struct btrfs_path *btrfs_alloc_path(void);
1072void btrfs_free_path(struct btrfs_path *p); 1074void btrfs_free_path(struct btrfs_path *p);
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 120c448f58f..3418bb62b99 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -396,6 +396,14 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
396 return 0; 396 return 0;
397} 397}
398 398
399int btrfs_extent_post_op(struct btrfs_trans_handle *trans,
400 struct btrfs_root *root)
401{
402 finish_current_insert(trans, root->fs_info->extent_root);
403 del_pending_extents(trans, root->fs_info->extent_root);
404 return 0;
405}
406
399static int lookup_extent_ref(struct btrfs_trans_handle *trans, 407static int lookup_extent_ref(struct btrfs_trans_handle *trans,
400 struct btrfs_root *root, u64 blocknr, 408 struct btrfs_root *root, u64 blocknr,
401 u64 num_blocks, u32 *refs) 409 u64 num_blocks, u32 *refs)
@@ -1374,7 +1382,25 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root
1374 BUG_ON(ret); 1382 BUG_ON(ret);
1375 continue; 1383 continue;
1376 } 1384 }
1377 next = read_tree_block(root, blocknr); 1385 next = btrfs_find_tree_block(root, blocknr);
1386 if (!next || !buffer_uptodate(next)) {
1387 brelse(next);
1388 mutex_unlock(&root->fs_info->fs_mutex);
1389 next = read_tree_block(root, blocknr);
1390 mutex_lock(&root->fs_info->fs_mutex);
1391
1392 /* we dropped the lock, check one more time */
1393 ret = lookup_extent_ref(trans, root, blocknr, 1, &refs);
1394 BUG_ON(ret);
1395 if (refs != 1) {
1396 path->slots[*level]++;
1397 brelse(next);
1398 ret = btrfs_free_extent(trans, root,
1399 blocknr, 1, 1);
1400 BUG_ON(ret);
1401 continue;
1402 }
1403 }
1378 WARN_ON(*level <= 0); 1404 WARN_ON(*level <= 0);
1379 if (path->nodes[*level-1]) 1405 if (path->nodes[*level-1])
1380 btrfs_block_release(root, path->nodes[*level-1]); 1406 btrfs_block_release(root, path->nodes[*level-1]);
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 12aa043b9f6..5c05ecbc572 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -2159,9 +2159,7 @@ int btrfs_ioctl(struct inode *inode, struct file *filp, unsigned int
2159{ 2159{
2160 struct btrfs_root *root = BTRFS_I(inode)->root; 2160 struct btrfs_root *root = BTRFS_I(inode)->root;
2161 struct btrfs_ioctl_vol_args vol_args; 2161 struct btrfs_ioctl_vol_args vol_args;
2162 struct btrfs_trans_handle *trans;
2163 int ret = 0; 2162 int ret = 0;
2164 int err;
2165 struct btrfs_dir_item *di; 2163 struct btrfs_dir_item *di;
2166 int namelen; 2164 int namelen;
2167 struct btrfs_path *path; 2165 struct btrfs_path *path;
@@ -2201,25 +2199,8 @@ int btrfs_ioctl(struct inode *inode, struct file *filp, unsigned int
2201 2199
2202 case BTRFS_IOC_DEFRAG: 2200 case BTRFS_IOC_DEFRAG:
2203 mutex_lock(&root->fs_info->fs_mutex); 2201 mutex_lock(&root->fs_info->fs_mutex);
2204 trans = btrfs_start_transaction(root, 1); 2202 btrfs_defrag_root(root, 0);
2205 memset(&root->defrag_progress, 0, 2203 btrfs_defrag_root(root->fs_info->extent_root, 0);
2206 sizeof(root->defrag_progress));
2207 while (1) {
2208 root->defrag_running = 1;
2209 err = btrfs_defrag_leaves(trans, root, 0);
2210
2211 btrfs_end_transaction(trans, root);
2212 mutex_unlock(&root->fs_info->fs_mutex);
2213
2214 btrfs_btree_balance_dirty(root);
2215
2216 mutex_lock(&root->fs_info->fs_mutex);
2217 trans = btrfs_start_transaction(root, 1);
2218 if (err != -EAGAIN)
2219 break;
2220 }
2221 root->defrag_running = 0;
2222 btrfs_end_transaction(trans, root);
2223 mutex_unlock(&root->fs_info->fs_mutex); 2204 mutex_unlock(&root->fs_info->fs_mutex);
2224 ret = 0; 2205 ret = 0;
2225 break; 2206 break;
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 2e797d5fb28..74f3de47423 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -121,7 +121,9 @@ static int btrfs_sync_fs(struct super_block *sb, int wait)
121 filemap_flush(root->fs_info->btree_inode->i_mapping); 121 filemap_flush(root->fs_info->btree_inode->i_mapping);
122 return 0; 122 return 0;
123 } 123 }
124 btrfs_clean_old_snapshots(root);
124 mutex_lock(&root->fs_info->fs_mutex); 125 mutex_lock(&root->fs_info->fs_mutex);
126 btrfs_defrag_dirty_roots(root->fs_info);
125 trans = btrfs_start_transaction(root, 1); 127 trans = btrfs_start_transaction(root, 1);
126 ret = btrfs_commit_transaction(trans, root); 128 ret = btrfs_commit_transaction(trans, root);
127 sb->s_dirt = 0; 129 sb->s_dirt = 0;
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 204337c5ca0..c9d52dc83e4 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -317,18 +317,47 @@ static int add_dirty_roots(struct btrfs_trans_handle *trans,
317 return err; 317 return err;
318} 318}
319 319
320int btrfs_defrag_root(struct btrfs_root *root, int cacheonly)
321{
322 struct btrfs_fs_info *info = root->fs_info;
323 int ret;
324 struct btrfs_trans_handle *trans;
325
326 if (root->defrag_running)
327 return 0;
328
329 trans = btrfs_start_transaction(root, 1);
330 while (1) {
331 root->defrag_running = 1;
332 ret = btrfs_defrag_leaves(trans, root, cacheonly);
333 btrfs_end_transaction(trans, root);
334 mutex_unlock(&info->fs_mutex);
335
336 btrfs_btree_balance_dirty(root);
337 cond_resched();
338
339 mutex_lock(&info->fs_mutex);
340 trans = btrfs_start_transaction(root, 1);
341 if (ret != -EAGAIN)
342 break;
343 }
344 root->defrag_running = 0;
345 radix_tree_tag_clear(&info->fs_roots_radix,
346 (unsigned long)root->root_key.objectid,
347 BTRFS_ROOT_DEFRAG_TAG);
348 btrfs_end_transaction(trans, root);
349 return 0;
350}
351
320int btrfs_defrag_dirty_roots(struct btrfs_fs_info *info) 352int btrfs_defrag_dirty_roots(struct btrfs_fs_info *info)
321{ 353{
322 struct btrfs_root *gang[1]; 354 struct btrfs_root *gang[1];
323 struct btrfs_root *root; 355 struct btrfs_root *root;
324 struct btrfs_root *tree_root = info->tree_root;
325 struct btrfs_trans_handle *trans;
326 int i; 356 int i;
327 int ret; 357 int ret;
328 int err = 0; 358 int err = 0;
329 u64 last = 0; 359 u64 last = 0;
330 360
331 trans = btrfs_start_transaction(tree_root, 1);
332 while(1) { 361 while(1) {
333 ret = radix_tree_gang_lookup_tag(&info->fs_roots_radix, 362 ret = radix_tree_gang_lookup_tag(&info->fs_roots_radix,
334 (void **)gang, last, 363 (void **)gang, last,
@@ -339,37 +368,10 @@ int btrfs_defrag_dirty_roots(struct btrfs_fs_info *info)
339 for (i = 0; i < ret; i++) { 368 for (i = 0; i < ret; i++) {
340 root = gang[i]; 369 root = gang[i];
341 last = root->root_key.objectid + 1; 370 last = root->root_key.objectid + 1;
342 radix_tree_tag_clear(&info->fs_roots_radix, 371 btrfs_defrag_root(root, 1);
343 (unsigned long)root->root_key.objectid,
344 BTRFS_ROOT_DEFRAG_TAG);
345 if (root->defrag_running)
346 continue;
347
348 while (1) {
349 mutex_lock(&root->fs_info->trans_mutex);
350 record_root_in_trans(root);
351 mutex_unlock(&root->fs_info->trans_mutex);
352
353 root->defrag_running = 1;
354 err = btrfs_defrag_leaves(trans, root, 1);
355 btrfs_end_transaction(trans, tree_root);
356 mutex_unlock(&info->fs_mutex);
357
358 btrfs_btree_balance_dirty(root);
359 cond_resched();
360
361 mutex_lock(&info->fs_mutex);
362 trans = btrfs_start_transaction(tree_root, 1);
363 if (err != -EAGAIN)
364 break;
365 }
366 root->defrag_running = 0;
367 radix_tree_tag_clear(&info->fs_roots_radix,
368 (unsigned long)root->root_key.objectid,
369 BTRFS_ROOT_DEFRAG_TAG);
370 } 372 }
371 } 373 }
372 btrfs_end_transaction(trans, tree_root); 374 btrfs_defrag_root(info->extent_root, 1);
373 return err; 375 return err;
374} 376}
375 377
@@ -527,6 +529,20 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
527 return ret; 529 return ret;
528} 530}
529 531
532int btrfs_clean_old_snapshots(struct btrfs_root *root)
533{
534 struct list_head dirty_roots;
535 INIT_LIST_HEAD(&dirty_roots);
536
537 mutex_lock(&root->fs_info->trans_mutex);
538 list_splice_init(&root->fs_info->dead_roots, &dirty_roots);
539 mutex_unlock(&root->fs_info->trans_mutex);
540
541 if (!list_empty(&dirty_roots)) {
542 drop_dirty_roots(root, &dirty_roots);
543 }
544 return 0;
545}
530void btrfs_transaction_cleaner(struct work_struct *work) 546void btrfs_transaction_cleaner(struct work_struct *work)
531{ 547{
532 struct btrfs_fs_info *fs_info = container_of(work, 548 struct btrfs_fs_info *fs_info = container_of(work,
@@ -536,12 +552,10 @@ void btrfs_transaction_cleaner(struct work_struct *work)
536 struct btrfs_root *root = fs_info->tree_root; 552 struct btrfs_root *root = fs_info->tree_root;
537 struct btrfs_transaction *cur; 553 struct btrfs_transaction *cur;
538 struct btrfs_trans_handle *trans; 554 struct btrfs_trans_handle *trans;
539 struct list_head dirty_roots;
540 unsigned long now; 555 unsigned long now;
541 unsigned long delay = HZ * 30; 556 unsigned long delay = HZ * 30;
542 int ret; 557 int ret;
543 558
544 INIT_LIST_HEAD(&dirty_roots);
545 mutex_lock(&root->fs_info->fs_mutex); 559 mutex_lock(&root->fs_info->fs_mutex);
546 mutex_lock(&root->fs_info->trans_mutex); 560 mutex_lock(&root->fs_info->trans_mutex);
547 cur = root->fs_info->running_transaction; 561 cur = root->fs_info->running_transaction;
@@ -561,14 +575,7 @@ void btrfs_transaction_cleaner(struct work_struct *work)
561 ret = btrfs_commit_transaction(trans, root); 575 ret = btrfs_commit_transaction(trans, root);
562out: 576out:
563 mutex_unlock(&root->fs_info->fs_mutex); 577 mutex_unlock(&root->fs_info->fs_mutex);
564 578 btrfs_clean_old_snapshots(root);
565 mutex_lock(&root->fs_info->trans_mutex);
566 list_splice_init(&root->fs_info->dead_roots, &dirty_roots);
567 mutex_unlock(&root->fs_info->trans_mutex);
568
569 if (!list_empty(&dirty_roots)) {
570 drop_dirty_roots(root, &dirty_roots);
571 }
572 btrfs_transaction_queue_work(root, delay); 579 btrfs_transaction_queue_work(root, delay);
573} 580}
574 581
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h
index 65a395eeca9..d5f491d3757 100644
--- a/fs/btrfs/transaction.h
+++ b/fs/btrfs/transaction.h
@@ -73,5 +73,7 @@ void btrfs_init_transaction_sys(void);
73void btrfs_exit_transaction_sys(void); 73void btrfs_exit_transaction_sys(void);
74int btrfs_add_dead_root(struct btrfs_root *root, struct list_head *dead_list); 74int btrfs_add_dead_root(struct btrfs_root *root, struct list_head *dead_list);
75int btrfs_defrag_dirty_roots(struct btrfs_fs_info *info); 75int btrfs_defrag_dirty_roots(struct btrfs_fs_info *info);
76int btrfs_defrag_root(struct btrfs_root *root, int cacheonly);
77int btrfs_clean_old_snapshots(struct btrfs_root *root);
76 78
77#endif 79#endif
diff --git a/fs/btrfs/tree-defrag.c b/fs/btrfs/tree-defrag.c
index 7ea66b4aa5c..a09064a9a41 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)