aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fusionio.com>2013-10-07 15:11:00 -0400
committerChris Mason <chris.mason@fusionio.com>2013-11-11 21:56:11 -0500
commit681ae50917df9fd1fae2571fb36a579d1e872b12 (patch)
treee111fd622d2eef00c211b9adb9b68d1a8cd07e57
parenteb58bb371a04d3bbab44ec0c5672ce69487bac1e (diff)
Btrfs: cleanup reserved space when freeing tree log on error
On error we will wait and free the tree log at unmount without a transaction. This means that the actual freeing of the blocks doesn't happen which means we complain about space leaks on unmount. So to fix this just skip the transaction specific cleanup part of the tree log free'ing if we don't have a transaction and that way we can free up our reserved space and our counters stay happy. Thanks, Signed-off-by: Josef Bacik <jbacik@fusionio.com> Signed-off-by: Chris Mason <chris.mason@fusionio.com>
-rw-r--r--fs/btrfs/tree-log.c47
1 files changed, 25 insertions, 22 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 964c583ea900..849b72985c74 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -2151,11 +2151,13 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans,
2151 return ret; 2151 return ret;
2152 } 2152 }
2153 2153
2154 btrfs_tree_lock(next); 2154 if (trans) {
2155 btrfs_set_lock_blocking(next); 2155 btrfs_tree_lock(next);
2156 clean_tree_block(trans, root, next); 2156 btrfs_set_lock_blocking(next);
2157 btrfs_wait_tree_block_writeback(next); 2157 clean_tree_block(trans, root, next);
2158 btrfs_tree_unlock(next); 2158 btrfs_wait_tree_block_writeback(next);
2159 btrfs_tree_unlock(next);
2160 }
2159 2161
2160 WARN_ON(root_owner != 2162 WARN_ON(root_owner !=
2161 BTRFS_TREE_LOG_OBJECTID); 2163 BTRFS_TREE_LOG_OBJECTID);
@@ -2227,11 +2229,13 @@ static noinline int walk_up_log_tree(struct btrfs_trans_handle *trans,
2227 2229
2228 next = path->nodes[*level]; 2230 next = path->nodes[*level];
2229 2231
2230 btrfs_tree_lock(next); 2232 if (trans) {
2231 btrfs_set_lock_blocking(next); 2233 btrfs_tree_lock(next);
2232 clean_tree_block(trans, root, next); 2234 btrfs_set_lock_blocking(next);
2233 btrfs_wait_tree_block_writeback(next); 2235 clean_tree_block(trans, root, next);
2234 btrfs_tree_unlock(next); 2236 btrfs_wait_tree_block_writeback(next);
2237 btrfs_tree_unlock(next);
2238 }
2235 2239
2236 WARN_ON(root_owner != BTRFS_TREE_LOG_OBJECTID); 2240 WARN_ON(root_owner != BTRFS_TREE_LOG_OBJECTID);
2237 ret = btrfs_free_and_pin_reserved_extent(root, 2241 ret = btrfs_free_and_pin_reserved_extent(root,
@@ -2301,11 +2305,13 @@ static int walk_log_tree(struct btrfs_trans_handle *trans,
2301 2305
2302 next = path->nodes[orig_level]; 2306 next = path->nodes[orig_level];
2303 2307
2304 btrfs_tree_lock(next); 2308 if (trans) {
2305 btrfs_set_lock_blocking(next); 2309 btrfs_tree_lock(next);
2306 clean_tree_block(trans, log, next); 2310 btrfs_set_lock_blocking(next);
2307 btrfs_wait_tree_block_writeback(next); 2311 clean_tree_block(trans, log, next);
2308 btrfs_tree_unlock(next); 2312 btrfs_wait_tree_block_writeback(next);
2313 btrfs_tree_unlock(next);
2314 }
2309 2315
2310 WARN_ON(log->root_key.objectid != 2316 WARN_ON(log->root_key.objectid !=
2311 BTRFS_TREE_LOG_OBJECTID); 2317 BTRFS_TREE_LOG_OBJECTID);
@@ -2608,13 +2614,10 @@ static void free_log_tree(struct btrfs_trans_handle *trans,
2608 .process_func = process_one_buffer 2614 .process_func = process_one_buffer
2609 }; 2615 };
2610 2616
2611 if (trans) { 2617 ret = walk_log_tree(trans, log, &wc);
2612 ret = walk_log_tree(trans, log, &wc); 2618 /* I don't think this can happen but just in case */
2613 2619 if (ret)
2614 /* I don't think this can happen but just in case */ 2620 btrfs_abort_transaction(trans, log, ret);
2615 if (ret)
2616 btrfs_abort_transaction(trans, log, ret);
2617 }
2618 2621
2619 while (1) { 2622 while (1) {
2620 ret = find_first_extent_bit(&log->dirty_log_pages, 2623 ret = find_first_extent_bit(&log->dirty_log_pages,