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:03 -0400 |
| commit | e7a84565bcdb239caad29ccbe559ef978090ac7e (patch) | |
| tree | aaeba005e713cde2030c27451d98847accff116d | |
| parent | a74a4b97b61beede185b4b3ad359d7d378b0d312 (diff) | |
Btrfs: Add btree locking to the tree defragmentation code
The online btree defragger is simplified and rewritten to use
standard btree searches instead of a walk up / down mechanism.
Signed-off-by: Chris Mason <chris.mason@oracle.com>
| -rw-r--r-- | fs/btrfs/ctree.c | 46 | ||||
| -rw-r--r-- | fs/btrfs/ctree.h | 2 | ||||
| -rw-r--r-- | fs/btrfs/extent-tree.c | 7 | ||||
| -rw-r--r-- | fs/btrfs/tree-defrag.c | 239 |
4 files changed, 93 insertions, 201 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 40f0e0cb804b..7f4cc2b88d09 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
| @@ -354,7 +354,6 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, | |||
| 354 | struct btrfs_key *progress) | 354 | struct btrfs_key *progress) |
| 355 | { | 355 | { |
| 356 | struct extent_buffer *cur; | 356 | struct extent_buffer *cur; |
| 357 | struct extent_buffer *tmp; | ||
| 358 | u64 blocknr; | 357 | u64 blocknr; |
| 359 | u64 gen; | 358 | u64 gen; |
| 360 | u64 search_start = *last_ret; | 359 | u64 search_start = *last_ret; |
| @@ -370,9 +369,6 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, | |||
| 370 | int progress_passed = 0; | 369 | int progress_passed = 0; |
| 371 | struct btrfs_disk_key disk_key; | 370 | struct btrfs_disk_key disk_key; |
| 372 | 371 | ||
| 373 | /* FIXME this code needs locking */ | ||
| 374 | return 0; | ||
| 375 | |||
| 376 | parent_level = btrfs_header_level(parent); | 372 | parent_level = btrfs_header_level(parent); |
| 377 | if (cache_only && parent_level != 1) | 373 | if (cache_only && parent_level != 1) |
| 378 | return 0; | 374 | return 0; |
| @@ -454,20 +450,23 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, | |||
| 454 | if (search_start == 0) | 450 | if (search_start == 0) |
| 455 | search_start = last_block; | 451 | search_start = last_block; |
| 456 | 452 | ||
| 453 | btrfs_tree_lock(cur); | ||
| 457 | err = __btrfs_cow_block(trans, root, cur, parent, i, | 454 | err = __btrfs_cow_block(trans, root, cur, parent, i, |
| 458 | &tmp, search_start, | 455 | &cur, search_start, |
| 459 | min(16 * blocksize, | 456 | min(16 * blocksize, |
| 460 | (end_slot - i) * blocksize)); | 457 | (end_slot - i) * blocksize)); |
| 461 | if (err) { | 458 | if (err) { |
| 459 | btrfs_tree_unlock(cur); | ||
| 462 | free_extent_buffer(cur); | 460 | free_extent_buffer(cur); |
| 463 | break; | 461 | break; |
| 464 | } | 462 | } |
| 465 | search_start = tmp->start; | 463 | search_start = cur->start; |
| 466 | last_block = tmp->start; | 464 | last_block = cur->start; |
| 467 | *last_ret = search_start; | 465 | *last_ret = search_start; |
| 468 | if (parent_level == 1) | 466 | if (parent_level == 1) |
| 469 | btrfs_clear_buffer_defrag(tmp); | 467 | btrfs_clear_buffer_defrag(cur); |
| 470 | free_extent_buffer(tmp); | 468 | btrfs_tree_unlock(cur); |
| 469 | free_extent_buffer(cur); | ||
| 471 | } | 470 | } |
| 472 | if (parent->map_token) { | 471 | if (parent->map_token) { |
| 473 | unmap_extent_buffer(parent, parent->map_token, | 472 | unmap_extent_buffer(parent, parent->map_token, |
| @@ -2970,6 +2969,35 @@ int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path) | |||
| 2970 | return 1; | 2969 | return 1; |
| 2971 | } | 2970 | } |
| 2972 | 2971 | ||
| 2972 | int btrfs_find_next_key(struct btrfs_root *root, struct btrfs_path *path, | ||
| 2973 | struct btrfs_key *key, int lowest_level) | ||
| 2974 | { | ||
| 2975 | int level = lowest_level; | ||
| 2976 | int slot; | ||
| 2977 | struct extent_buffer *c; | ||
| 2978 | |||
| 2979 | while(level < BTRFS_MAX_LEVEL) { | ||
| 2980 | if (!path->nodes[level]) | ||
| 2981 | return 1; | ||
| 2982 | |||
| 2983 | slot = path->slots[level] + 1; | ||
| 2984 | c = path->nodes[level]; | ||
| 2985 | if (slot >= btrfs_header_nritems(c)) { | ||
| 2986 | level++; | ||
| 2987 | if (level == BTRFS_MAX_LEVEL) { | ||
| 2988 | return 1; | ||
| 2989 | } | ||
| 2990 | continue; | ||
| 2991 | } | ||
| 2992 | if (level == 0) | ||
| 2993 | btrfs_item_key_to_cpu(c, key, slot); | ||
| 2994 | else | ||
| 2995 | btrfs_node_key_to_cpu(c, key, slot); | ||
| 2996 | return 0; | ||
| 2997 | } | ||
| 2998 | return 1; | ||
| 2999 | } | ||
| 3000 | |||
| 2973 | /* | 3001 | /* |
| 2974 | * search the tree again to find a leaf with greater keys | 3002 | * search the tree again to find a leaf with greater keys |
| 2975 | * returns 0 if it found something or 1 if there are no greater leaves. | 3003 | * returns 0 if it found something or 1 if there are no greater leaves. |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 244fe86bcc55..ca8e6f15859e 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
| @@ -1411,6 +1411,8 @@ int btrfs_previous_item(struct btrfs_root *root, | |||
| 1411 | 1411 | ||
| 1412 | struct extent_buffer *btrfs_root_node(struct btrfs_root *root); | 1412 | struct extent_buffer *btrfs_root_node(struct btrfs_root *root); |
| 1413 | struct extent_buffer *btrfs_lock_root_node(struct btrfs_root *root); | 1413 | struct extent_buffer *btrfs_lock_root_node(struct btrfs_root *root); |
| 1414 | int btrfs_find_next_key(struct btrfs_root *root, struct btrfs_path *path, | ||
| 1415 | struct btrfs_key *key, int lowest_level); | ||
| 1414 | 1416 | ||
| 1415 | int btrfs_cow_block(struct btrfs_trans_handle *trans, | 1417 | int btrfs_cow_block(struct btrfs_trans_handle *trans, |
| 1416 | struct btrfs_root *root, struct extent_buffer *buf, | 1418 | struct btrfs_root *root, struct extent_buffer *buf, |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 89cc4f611869..a9b3a25a45b7 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
| @@ -2201,6 +2201,7 @@ int drop_snap_lookup_refcount(struct btrfs_root *root, u64 start, u64 len, | |||
| 2201 | { | 2201 | { |
| 2202 | mutex_unlock(&root->fs_info->alloc_mutex); | 2202 | mutex_unlock(&root->fs_info->alloc_mutex); |
| 2203 | lookup_extent_ref(NULL, root, start, len, refs); | 2203 | lookup_extent_ref(NULL, root, start, len, refs); |
| 2204 | cond_resched(); | ||
| 2204 | mutex_lock(&root->fs_info->alloc_mutex); | 2205 | mutex_lock(&root->fs_info->alloc_mutex); |
| 2205 | return lookup_extent_ref(NULL, root, start, len, refs); | 2206 | return lookup_extent_ref(NULL, root, start, len, refs); |
| 2206 | } | 2207 | } |
| @@ -2280,6 +2281,7 @@ static int noinline walk_down_tree(struct btrfs_trans_handle *trans, | |||
| 2280 | 2281 | ||
| 2281 | next = read_tree_block(root, bytenr, blocksize, | 2282 | next = read_tree_block(root, bytenr, blocksize, |
| 2282 | ptr_gen); | 2283 | ptr_gen); |
| 2284 | cond_resched(); | ||
| 2283 | mutex_lock(&root->fs_info->alloc_mutex); | 2285 | mutex_lock(&root->fs_info->alloc_mutex); |
| 2284 | 2286 | ||
| 2285 | /* we've dropped the lock, double check */ | 2287 | /* we've dropped the lock, double check */ |
| @@ -2329,6 +2331,7 @@ out: | |||
| 2329 | *level += 1; | 2331 | *level += 1; |
| 2330 | BUG_ON(ret); | 2332 | BUG_ON(ret); |
| 2331 | mutex_unlock(&root->fs_info->alloc_mutex); | 2333 | mutex_unlock(&root->fs_info->alloc_mutex); |
| 2334 | cond_resched(); | ||
| 2332 | return 0; | 2335 | return 0; |
| 2333 | } | 2336 | } |
| 2334 | 2337 | ||
| @@ -2448,6 +2451,10 @@ int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 2448 | break; | 2451 | break; |
| 2449 | if (wret < 0) | 2452 | if (wret < 0) |
| 2450 | ret = wret; | 2453 | ret = wret; |
| 2454 | if (trans->transaction->in_commit) { | ||
| 2455 | ret = -EAGAIN; | ||
| 2456 | break; | ||
| 2457 | } | ||
| 2451 | } | 2458 | } |
| 2452 | for (i = 0; i <= orig_level; i++) { | 2459 | for (i = 0; i <= orig_level; i++) { |
| 2453 | if (path->nodes[i]) { | 2460 | if (path->nodes[i]) { |
diff --git a/fs/btrfs/tree-defrag.c b/fs/btrfs/tree-defrag.c index fab851d85383..1677e4edaf6f 100644 --- a/fs/btrfs/tree-defrag.c +++ b/fs/btrfs/tree-defrag.c | |||
| @@ -21,167 +21,26 @@ | |||
| 21 | #include "disk-io.h" | 21 | #include "disk-io.h" |
| 22 | #include "print-tree.h" | 22 | #include "print-tree.h" |
| 23 | #include "transaction.h" | 23 | #include "transaction.h" |
| 24 | 24 | #include "locking.h" | |
| 25 | static void reada_defrag(struct btrfs_root *root, | ||
| 26 | struct extent_buffer *node) | ||
| 27 | { | ||
| 28 | int i; | ||
| 29 | u32 nritems; | ||
| 30 | u64 bytenr; | ||
| 31 | u64 gen; | ||
| 32 | u32 blocksize; | ||
| 33 | int ret; | ||
| 34 | |||
| 35 | blocksize = btrfs_level_size(root, btrfs_header_level(node) - 1); | ||
| 36 | nritems = btrfs_header_nritems(node); | ||
| 37 | for (i = 0; i < nritems; i++) { | ||
| 38 | bytenr = btrfs_node_blockptr(node, i); | ||
| 39 | gen = btrfs_node_ptr_generation(node, i); | ||
| 40 | ret = readahead_tree_block(root, bytenr, blocksize, gen); | ||
| 41 | if (ret) | ||
| 42 | break; | ||
| 43 | } | ||
| 44 | } | ||
| 45 | |||
| 46 | static int defrag_walk_down(struct btrfs_trans_handle *trans, | ||
| 47 | struct btrfs_root *root, | ||
| 48 | struct btrfs_path *path, int *level, | ||
| 49 | int cache_only, u64 *last_ret) | ||
| 50 | { | ||
| 51 | struct extent_buffer *next; | ||
| 52 | struct extent_buffer *cur; | ||
| 53 | u64 bytenr; | ||
| 54 | u64 ptr_gen; | ||
| 55 | int ret = 0; | ||
| 56 | int is_extent = 0; | ||
| 57 | |||
| 58 | WARN_ON(*level < 0); | ||
| 59 | WARN_ON(*level >= BTRFS_MAX_LEVEL); | ||
| 60 | |||
| 61 | if (root->fs_info->extent_root == root) | ||
| 62 | is_extent = 1; | ||
| 63 | |||
| 64 | if (*level == 1 && cache_only && path->nodes[1] && | ||
| 65 | !btrfs_buffer_defrag(path->nodes[1])) { | ||
| 66 | goto out; | ||
| 67 | } | ||
| 68 | while(*level > 0) { | ||
| 69 | WARN_ON(*level < 0); | ||
| 70 | WARN_ON(*level >= BTRFS_MAX_LEVEL); | ||
| 71 | cur = path->nodes[*level]; | ||
| 72 | |||
| 73 | if (!cache_only && *level > 1 && path->slots[*level] == 0) | ||
| 74 | reada_defrag(root, cur); | ||
| 75 | |||
| 76 | if (btrfs_header_level(cur) != *level) | ||
| 77 | WARN_ON(1); | ||
| 78 | |||
| 79 | if (path->slots[*level] >= | ||
| 80 | btrfs_header_nritems(cur)) | ||
| 81 | break; | ||
| 82 | |||
| 83 | if (*level == 1) { | ||
| 84 | WARN_ON(btrfs_header_generation(path->nodes[*level]) != | ||
| 85 | trans->transid); | ||
| 86 | ret = btrfs_realloc_node(trans, root, | ||
| 87 | path->nodes[*level], | ||
| 88 | path->slots[*level], | ||
| 89 | cache_only, last_ret, | ||
| 90 | &root->defrag_progress); | ||
| 91 | if (is_extent) | ||
| 92 | btrfs_extent_post_op(trans, root); | ||
| 93 | |||
| 94 | break; | ||
| 95 | } | ||
| 96 | bytenr = btrfs_node_blockptr(cur, path->slots[*level]); | ||
| 97 | ptr_gen = btrfs_node_ptr_generation(cur, path->slots[*level]); | ||
| 98 | |||
| 99 | if (cache_only) { | ||
| 100 | next = btrfs_find_tree_block(root, bytenr, | ||
| 101 | btrfs_level_size(root, *level - 1)); | ||
| 102 | if (!next || !btrfs_buffer_uptodate(next, ptr_gen) || | ||
| 103 | !btrfs_buffer_defrag(next)) { | ||
| 104 | free_extent_buffer(next); | ||
| 105 | path->slots[*level]++; | ||
| 106 | continue; | ||
| 107 | } | ||
| 108 | } else { | ||
| 109 | next = read_tree_block(root, bytenr, | ||
| 110 | btrfs_level_size(root, *level - 1), | ||
| 111 | ptr_gen); | ||
| 112 | } | ||
| 113 | ret = btrfs_cow_block(trans, root, next, path->nodes[*level], | ||
| 114 | path->slots[*level], &next); | ||
| 115 | BUG_ON(ret); | ||
| 116 | if (is_extent) | ||
| 117 | btrfs_extent_post_op(trans, root); | ||
| 118 | |||
| 119 | WARN_ON(*level <= 0); | ||
| 120 | if (path->nodes[*level-1]) | ||
| 121 | free_extent_buffer(path->nodes[*level-1]); | ||
| 122 | path->nodes[*level-1] = next; | ||
| 123 | *level = btrfs_header_level(next); | ||
| 124 | path->slots[*level] = 0; | ||
| 125 | } | ||
| 126 | WARN_ON(*level < 0); | ||
| 127 | WARN_ON(*level >= BTRFS_MAX_LEVEL); | ||
| 128 | |||
| 129 | btrfs_clear_buffer_defrag(path->nodes[*level]); | ||
| 130 | out: | ||
| 131 | free_extent_buffer(path->nodes[*level]); | ||
| 132 | path->nodes[*level] = NULL; | ||
| 133 | *level += 1; | ||
| 134 | WARN_ON(ret && ret != -EAGAIN); | ||
| 135 | return ret; | ||
| 136 | } | ||
| 137 | |||
| 138 | static int defrag_walk_up(struct btrfs_trans_handle *trans, | ||
| 139 | struct btrfs_root *root, | ||
| 140 | struct btrfs_path *path, int *level, | ||
| 141 | int cache_only) | ||
| 142 | { | ||
| 143 | int i; | ||
| 144 | int slot; | ||
| 145 | struct extent_buffer *node; | ||
| 146 | |||
| 147 | for(i = *level; i < BTRFS_MAX_LEVEL - 1 && path->nodes[i]; i++) { | ||
| 148 | slot = path->slots[i]; | ||
| 149 | if (slot < btrfs_header_nritems(path->nodes[i]) - 1) { | ||
| 150 | path->slots[i]++; | ||
| 151 | *level = i; | ||
| 152 | node = path->nodes[i]; | ||
| 153 | WARN_ON(i == 0); | ||
| 154 | btrfs_node_key_to_cpu(node, &root->defrag_progress, | ||
| 155 | path->slots[i]); | ||
| 156 | root->defrag_level = i; | ||
| 157 | return 0; | ||
| 158 | } else { | ||
| 159 | btrfs_clear_buffer_defrag(path->nodes[*level]); | ||
| 160 | free_extent_buffer(path->nodes[*level]); | ||
| 161 | path->nodes[*level] = NULL; | ||
| 162 | *level = i + 1; | ||
| 163 | } | ||
| 164 | } | ||
| 165 | return 1; | ||
| 166 | } | ||
| 167 | 25 | ||
| 168 | int btrfs_defrag_leaves(struct btrfs_trans_handle *trans, | 26 | int btrfs_defrag_leaves(struct btrfs_trans_handle *trans, |
| 169 | struct btrfs_root *root, int cache_only) | 27 | struct btrfs_root *root, int cache_only) |
| 170 | { | 28 | { |
| 171 | struct btrfs_path *path = NULL; | 29 | struct btrfs_path *path = NULL; |
| 172 | struct extent_buffer *tmp; | 30 | struct btrfs_key key; |
| 173 | int ret = 0; | 31 | int ret = 0; |
| 174 | int wret; | 32 | int wret; |
| 175 | int level; | 33 | int level; |
| 176 | int orig_level; | 34 | int orig_level; |
| 177 | int i; | 35 | int i; |
| 178 | int is_extent = 0; | 36 | int is_extent = 0; |
| 37 | int next_key_ret = 0; | ||
| 179 | u64 last_ret = 0; | 38 | u64 last_ret = 0; |
| 180 | 39 | ||
| 181 | if (root->fs_info->extent_root == root) | 40 | if (root->fs_info->extent_root == root) { |
| 41 | mutex_lock(&root->fs_info->alloc_mutex); | ||
| 182 | is_extent = 1; | 42 | is_extent = 1; |
| 183 | 43 | } | |
| 184 | goto out; | ||
| 185 | 44 | ||
| 186 | if (root->ref_cows == 0 && !is_extent) | 45 | if (root->ref_cows == 0 && !is_extent) |
| 187 | goto out; | 46 | goto out; |
| @@ -200,67 +59,63 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans, | |||
| 200 | goto out; | 59 | goto out; |
| 201 | } | 60 | } |
| 202 | if (root->defrag_progress.objectid == 0) { | 61 | if (root->defrag_progress.objectid == 0) { |
| 62 | struct extent_buffer *root_node; | ||
| 203 | u32 nritems; | 63 | u32 nritems; |
| 204 | 64 | ||
| 205 | nritems = btrfs_header_nritems(root->node); | 65 | root_node = btrfs_lock_root_node(root); |
| 66 | nritems = btrfs_header_nritems(root_node); | ||
| 206 | root->defrag_max.objectid = 0; | 67 | root->defrag_max.objectid = 0; |
| 207 | /* from above we know this is not a leaf */ | 68 | /* from above we know this is not a leaf */ |
| 208 | btrfs_node_key_to_cpu(root->node, &root->defrag_max, | 69 | btrfs_node_key_to_cpu(root_node, &root->defrag_max, |
| 209 | nritems - 1); | 70 | nritems - 1); |
| 210 | extent_buffer_get(root->node); | 71 | btrfs_tree_unlock(root_node); |
| 211 | ret = btrfs_cow_block(trans, root, root->node, NULL, 0, &tmp); | 72 | free_extent_buffer(root_node); |
| 212 | BUG_ON(ret); | 73 | memset(&key, 0, sizeof(key)); |
| 213 | path->nodes[level] = root->node; | ||
| 214 | path->slots[level] = 0; | ||
| 215 | if (is_extent) | ||
| 216 | btrfs_extent_post_op(trans, root); | ||
| 217 | } else { | 74 | } else { |
| 218 | level = root->defrag_level; | 75 | memcpy(&key, &root->defrag_progress, sizeof(key)); |
| 219 | path->lowest_level = level; | ||
| 220 | wret = btrfs_search_slot(trans, root, &root->defrag_progress, | ||
| 221 | path, 0, 1); | ||
| 222 | |||
| 223 | if (is_extent) | ||
| 224 | btrfs_extent_post_op(trans, root); | ||
| 225 | |||
| 226 | if (wret < 0) { | ||
| 227 | ret = wret; | ||
| 228 | goto out; | ||
| 229 | } | ||
| 230 | |||
| 231 | while(level > 0 && !path->nodes[level]) | ||
| 232 | level--; | ||
| 233 | |||
| 234 | if (!path->nodes[level]) { | ||
| 235 | ret = 0; | ||
| 236 | goto out; | ||
| 237 | } | ||
| 238 | } | 76 | } |
| 239 | 77 | ||
| 240 | while(1) { | 78 | path->lowest_level = 1; |
| 241 | wret = defrag_walk_down(trans, root, path, &level, cache_only, | 79 | path->keep_locks = 1; |
| 242 | &last_ret); | 80 | wret = btrfs_search_slot(trans, root, &key, path, 0, 1); |
| 243 | if (wret > 0) | ||
| 244 | break; | ||
| 245 | if (wret < 0) | ||
| 246 | ret = wret; | ||
| 247 | 81 | ||
| 248 | wret = defrag_walk_up(trans, root, path, &level, cache_only); | 82 | if (wret < 0) { |
| 249 | if (wret > 0) | 83 | ret = wret; |
| 250 | break; | 84 | goto out; |
| 251 | if (wret < 0) | 85 | } |
| 252 | ret = wret; | 86 | if (!path->nodes[1]) { |
| 253 | else | 87 | ret = 0; |
| 254 | ret = -EAGAIN; | 88 | goto out; |
| 255 | break; | 89 | } |
| 90 | path->slots[1] = btrfs_header_nritems(path->nodes[1]); | ||
| 91 | next_key_ret = btrfs_find_next_key(root, path, &key, 1); | ||
| 92 | ret = btrfs_realloc_node(trans, root, | ||
| 93 | path->nodes[1], 0, | ||
| 94 | cache_only, &last_ret, | ||
| 95 | &root->defrag_progress); | ||
| 96 | WARN_ON(ret && ret != -EAGAIN); | ||
| 97 | if (next_key_ret == 0) { | ||
| 98 | memcpy(&root->defrag_progress, &key, sizeof(key)); | ||
| 99 | ret = -EAGAIN; | ||
| 256 | } | 100 | } |
| 257 | for (i = 0; i <= orig_level; i++) { | 101 | |
| 102 | for (i = 1; i < BTRFS_MAX_LEVEL; i++) { | ||
| 103 | if (path->locks[i]) { | ||
| 104 | btrfs_tree_unlock(path->nodes[i]); | ||
| 105 | path->locks[i] = 0; | ||
| 106 | } | ||
| 258 | if (path->nodes[i]) { | 107 | if (path->nodes[i]) { |
| 259 | free_extent_buffer(path->nodes[i]); | 108 | free_extent_buffer(path->nodes[i]); |
| 260 | path->nodes[i] = NULL; | 109 | path->nodes[i] = NULL; |
| 261 | } | 110 | } |
| 262 | } | 111 | } |
| 112 | if (is_extent) | ||
| 113 | btrfs_extent_post_op(trans, root); | ||
| 114 | |||
| 263 | out: | 115 | out: |
| 116 | if (is_extent) | ||
| 117 | mutex_unlock(&root->fs_info->alloc_mutex); | ||
| 118 | |||
| 264 | if (path) | 119 | if (path) |
| 265 | btrfs_free_path(path); | 120 | btrfs_free_path(path); |
| 266 | if (ret == -EAGAIN) { | 121 | if (ret == -EAGAIN) { |
