diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-04-02 11:20:42 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-04-02 11:20:42 -0400 |
commit | 5caf2a002901f0fde475371c4bf1c553b51884af (patch) | |
tree | 1c262f723307fe924ea4e960761354f194f3843e /fs/btrfs/extent-tree.c | |
parent | 2c90e5d658424bc71b111eb5a972240d5d06fe86 (diff) |
Btrfs: dynamic allocation of path struct
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r-- | fs/btrfs/extent-tree.c | 100 |
1 files changed, 61 insertions, 39 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 37b87e28a2f3..d785b721b461 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -15,7 +15,7 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct | |||
15 | static int inc_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root | 15 | static int inc_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root |
16 | *root, u64 blocknr, u64 num_blocks) | 16 | *root, u64 blocknr, u64 num_blocks) |
17 | { | 17 | { |
18 | struct btrfs_path path; | 18 | struct btrfs_path *path; |
19 | int ret; | 19 | int ret; |
20 | struct btrfs_key key; | 20 | struct btrfs_key key; |
21 | struct btrfs_leaf *l; | 21 | struct btrfs_leaf *l; |
@@ -25,23 +25,26 @@ static int inc_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root | |||
25 | 25 | ||
26 | find_free_extent(trans, root->fs_info->extent_root, 0, 0, (u64)-1, | 26 | find_free_extent(trans, root->fs_info->extent_root, 0, 0, (u64)-1, |
27 | &ins); | 27 | &ins); |
28 | btrfs_init_path(&path); | 28 | path = btrfs_alloc_path(); |
29 | BUG_ON(!path); | ||
30 | btrfs_init_path(path); | ||
29 | key.objectid = blocknr; | 31 | key.objectid = blocknr; |
30 | key.flags = 0; | 32 | key.flags = 0; |
31 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); | 33 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); |
32 | key.offset = num_blocks; | 34 | key.offset = num_blocks; |
33 | ret = btrfs_search_slot(trans, root->fs_info->extent_root, &key, &path, | 35 | ret = btrfs_search_slot(trans, root->fs_info->extent_root, &key, path, |
34 | 0, 1); | 36 | 0, 1); |
35 | if (ret != 0) | 37 | if (ret != 0) |
36 | BUG(); | 38 | BUG(); |
37 | BUG_ON(ret != 0); | 39 | BUG_ON(ret != 0); |
38 | l = btrfs_buffer_leaf(path.nodes[0]); | 40 | l = btrfs_buffer_leaf(path->nodes[0]); |
39 | item = btrfs_item_ptr(l, path.slots[0], struct btrfs_extent_item); | 41 | item = btrfs_item_ptr(l, path->slots[0], struct btrfs_extent_item); |
40 | refs = btrfs_extent_refs(item); | 42 | refs = btrfs_extent_refs(item); |
41 | btrfs_set_extent_refs(item, refs + 1); | 43 | btrfs_set_extent_refs(item, refs + 1); |
42 | btrfs_mark_buffer_dirty(path.nodes[0]); | 44 | btrfs_mark_buffer_dirty(path->nodes[0]); |
43 | 45 | ||
44 | btrfs_release_path(root->fs_info->extent_root, &path); | 46 | btrfs_release_path(root->fs_info->extent_root, path); |
47 | btrfs_free_path(path); | ||
45 | finish_current_insert(trans, root->fs_info->extent_root); | 48 | finish_current_insert(trans, root->fs_info->extent_root); |
46 | del_pending_extents(trans, root->fs_info->extent_root); | 49 | del_pending_extents(trans, root->fs_info->extent_root); |
47 | return 0; | 50 | return 0; |
@@ -50,24 +53,27 @@ static int inc_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root | |||
50 | static int lookup_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root | 53 | static int lookup_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root |
51 | *root, u64 blocknr, u64 num_blocks, u32 *refs) | 54 | *root, u64 blocknr, u64 num_blocks, u32 *refs) |
52 | { | 55 | { |
53 | struct btrfs_path path; | 56 | struct btrfs_path *path; |
54 | int ret; | 57 | int ret; |
55 | struct btrfs_key key; | 58 | struct btrfs_key key; |
56 | struct btrfs_leaf *l; | 59 | struct btrfs_leaf *l; |
57 | struct btrfs_extent_item *item; | 60 | struct btrfs_extent_item *item; |
58 | btrfs_init_path(&path); | 61 | |
62 | path = btrfs_alloc_path(); | ||
63 | btrfs_init_path(path); | ||
59 | key.objectid = blocknr; | 64 | key.objectid = blocknr; |
60 | key.offset = num_blocks; | 65 | key.offset = num_blocks; |
61 | key.flags = 0; | 66 | key.flags = 0; |
62 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); | 67 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); |
63 | ret = btrfs_search_slot(trans, root->fs_info->extent_root, &key, &path, | 68 | ret = btrfs_search_slot(trans, root->fs_info->extent_root, &key, path, |
64 | 0, 0); | 69 | 0, 0); |
65 | if (ret != 0) | 70 | if (ret != 0) |
66 | BUG(); | 71 | BUG(); |
67 | l = btrfs_buffer_leaf(path.nodes[0]); | 72 | l = btrfs_buffer_leaf(path->nodes[0]); |
68 | item = btrfs_item_ptr(l, path.slots[0], struct btrfs_extent_item); | 73 | item = btrfs_item_ptr(l, path->slots[0], struct btrfs_extent_item); |
69 | *refs = btrfs_extent_refs(item); | 74 | *refs = btrfs_extent_refs(item); |
70 | btrfs_release_path(root->fs_info->extent_root, &path); | 75 | btrfs_release_path(root->fs_info->extent_root, path); |
76 | btrfs_free_path(path); | ||
71 | return 0; | 77 | return 0; |
72 | } | 78 | } |
73 | 79 | ||
@@ -200,7 +206,7 @@ static int pin_down_block(struct btrfs_root *root, u64 blocknr, int pending) | |||
200 | static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | 206 | static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root |
201 | *root, u64 blocknr, u64 num_blocks, int pin) | 207 | *root, u64 blocknr, u64 num_blocks, int pin) |
202 | { | 208 | { |
203 | struct btrfs_path path; | 209 | struct btrfs_path *path; |
204 | struct btrfs_key key; | 210 | struct btrfs_key key; |
205 | struct btrfs_fs_info *info = root->fs_info; | 211 | struct btrfs_fs_info *info = root->fs_info; |
206 | struct btrfs_root *extent_root = info->extent_root; | 212 | struct btrfs_root *extent_root = info->extent_root; |
@@ -215,20 +221,22 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
215 | key.offset = num_blocks; | 221 | key.offset = num_blocks; |
216 | 222 | ||
217 | find_free_extent(trans, root, 0, 0, (u64)-1, &ins); | 223 | find_free_extent(trans, root, 0, 0, (u64)-1, &ins); |
218 | btrfs_init_path(&path); | 224 | path = btrfs_alloc_path(); |
219 | ret = btrfs_search_slot(trans, extent_root, &key, &path, -1, 1); | 225 | BUG_ON(!path); |
226 | btrfs_init_path(path); | ||
227 | ret = btrfs_search_slot(trans, extent_root, &key, path, -1, 1); | ||
220 | if (ret) { | 228 | if (ret) { |
221 | printk("failed to find %Lu\n", key.objectid); | 229 | printk("failed to find %Lu\n", key.objectid); |
222 | btrfs_print_tree(extent_root, extent_root->node); | 230 | btrfs_print_tree(extent_root, extent_root->node); |
223 | printk("failed to find %Lu\n", key.objectid); | 231 | printk("failed to find %Lu\n", key.objectid); |
224 | BUG(); | 232 | BUG(); |
225 | } | 233 | } |
226 | ei = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), path.slots[0], | 234 | ei = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0], |
227 | struct btrfs_extent_item); | 235 | struct btrfs_extent_item); |
228 | BUG_ON(ei->refs == 0); | 236 | BUG_ON(ei->refs == 0); |
229 | refs = btrfs_extent_refs(ei) - 1; | 237 | refs = btrfs_extent_refs(ei) - 1; |
230 | btrfs_set_extent_refs(ei, refs); | 238 | btrfs_set_extent_refs(ei, refs); |
231 | btrfs_mark_buffer_dirty(path.nodes[0]); | 239 | btrfs_mark_buffer_dirty(path->nodes[0]); |
232 | if (refs == 0) { | 240 | if (refs == 0) { |
233 | u64 super_blocks_used; | 241 | u64 super_blocks_used; |
234 | 242 | ||
@@ -240,13 +248,14 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
240 | super_blocks_used = btrfs_super_blocks_used(info->disk_super); | 248 | super_blocks_used = btrfs_super_blocks_used(info->disk_super); |
241 | btrfs_set_super_blocks_used(info->disk_super, | 249 | btrfs_set_super_blocks_used(info->disk_super, |
242 | super_blocks_used - num_blocks); | 250 | super_blocks_used - num_blocks); |
243 | ret = btrfs_del_item(trans, extent_root, &path); | 251 | ret = btrfs_del_item(trans, extent_root, path); |
244 | if (extent_root->fs_info->last_insert.objectid > blocknr) | 252 | if (extent_root->fs_info->last_insert.objectid > blocknr) |
245 | extent_root->fs_info->last_insert.objectid = blocknr; | 253 | extent_root->fs_info->last_insert.objectid = blocknr; |
246 | if (ret) | 254 | if (ret) |
247 | BUG(); | 255 | BUG(); |
248 | } | 256 | } |
249 | btrfs_release_path(extent_root, &path); | 257 | btrfs_release_path(extent_root, path); |
258 | btrfs_free_path(path); | ||
250 | finish_current_insert(trans, extent_root); | 259 | finish_current_insert(trans, extent_root); |
251 | return ret; | 260 | return ret; |
252 | } | 261 | } |
@@ -319,7 +328,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
319 | *orig_root, u64 num_blocks, u64 search_start, u64 | 328 | *orig_root, u64 num_blocks, u64 search_start, u64 |
320 | search_end, struct btrfs_key *ins) | 329 | search_end, struct btrfs_key *ins) |
321 | { | 330 | { |
322 | struct btrfs_path path; | 331 | struct btrfs_path *path; |
323 | struct btrfs_key key; | 332 | struct btrfs_key key; |
324 | int ret; | 333 | int ret; |
325 | u64 hole_size = 0; | 334 | u64 hole_size = 0; |
@@ -339,24 +348,25 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
339 | 348 | ||
340 | ins->flags = 0; | 349 | ins->flags = 0; |
341 | btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY); | 350 | btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY); |
351 | path = btrfs_alloc_path(); | ||
342 | 352 | ||
343 | check_failed: | 353 | check_failed: |
344 | btrfs_init_path(&path); | 354 | btrfs_init_path(path); |
345 | ins->objectid = search_start; | 355 | ins->objectid = search_start; |
346 | ins->offset = 0; | 356 | ins->offset = 0; |
347 | start_found = 0; | 357 | start_found = 0; |
348 | ret = btrfs_search_slot(trans, root, ins, &path, 0, 0); | 358 | ret = btrfs_search_slot(trans, root, ins, path, 0, 0); |
349 | if (ret < 0) | 359 | if (ret < 0) |
350 | goto error; | 360 | goto error; |
351 | 361 | ||
352 | if (path.slots[0] > 0) | 362 | if (path->slots[0] > 0) |
353 | path.slots[0]--; | 363 | path->slots[0]--; |
354 | 364 | ||
355 | while (1) { | 365 | while (1) { |
356 | l = btrfs_buffer_leaf(path.nodes[0]); | 366 | l = btrfs_buffer_leaf(path->nodes[0]); |
357 | slot = path.slots[0]; | 367 | slot = path->slots[0]; |
358 | if (slot >= btrfs_header_nritems(&l->header)) { | 368 | if (slot >= btrfs_header_nritems(&l->header)) { |
359 | ret = btrfs_next_leaf(root, &path); | 369 | ret = btrfs_next_leaf(root, path); |
360 | if (ret == 0) | 370 | if (ret == 0) |
361 | continue; | 371 | continue; |
362 | if (ret < 0) | 372 | if (ret < 0) |
@@ -387,14 +397,14 @@ check_failed: | |||
387 | } | 397 | } |
388 | start_found = 1; | 398 | start_found = 1; |
389 | last_block = key.objectid + key.offset; | 399 | last_block = key.objectid + key.offset; |
390 | path.slots[0]++; | 400 | path->slots[0]++; |
391 | } | 401 | } |
392 | // FIXME -ENOSPC | 402 | // FIXME -ENOSPC |
393 | check_pending: | 403 | check_pending: |
394 | /* we have to make sure we didn't find an extent that has already | 404 | /* we have to make sure we didn't find an extent that has already |
395 | * been allocated by the map tree or the original allocation | 405 | * been allocated by the map tree or the original allocation |
396 | */ | 406 | */ |
397 | btrfs_release_path(root, &path); | 407 | btrfs_release_path(root, path); |
398 | BUG_ON(ins->objectid < search_start); | 408 | BUG_ON(ins->objectid < search_start); |
399 | for (test_block = ins->objectid; | 409 | for (test_block = ins->objectid; |
400 | test_block < ins->objectid + total_needed; test_block++) { | 410 | test_block < ins->objectid + total_needed; test_block++) { |
@@ -410,9 +420,11 @@ check_pending: | |||
410 | root->fs_info->current_insert.flags = 0; | 420 | root->fs_info->current_insert.flags = 0; |
411 | root->fs_info->last_insert.objectid = ins->objectid; | 421 | root->fs_info->last_insert.objectid = ins->objectid; |
412 | ins->offset = num_blocks; | 422 | ins->offset = num_blocks; |
423 | btrfs_free_path(path); | ||
413 | return 0; | 424 | return 0; |
414 | error: | 425 | error: |
415 | btrfs_release_path(root, &path); | 426 | btrfs_release_path(root, path); |
427 | btrfs_free_path(path); | ||
416 | return ret; | 428 | return ret; |
417 | } | 429 | } |
418 | 430 | ||
@@ -533,6 +545,8 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root | |||
533 | int ret; | 545 | int ret; |
534 | u32 refs; | 546 | u32 refs; |
535 | 547 | ||
548 | WARN_ON(*level < 0); | ||
549 | WARN_ON(*level >= BTRFS_MAX_LEVEL); | ||
536 | ret = lookup_block_ref(trans, root, path->nodes[*level]->b_blocknr, | 550 | ret = lookup_block_ref(trans, root, path->nodes[*level]->b_blocknr, |
537 | 1, &refs); | 551 | 1, &refs); |
538 | BUG_ON(ret); | 552 | BUG_ON(ret); |
@@ -542,6 +556,8 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root | |||
542 | * walk down to the last node level and free all the leaves | 556 | * walk down to the last node level and free all the leaves |
543 | */ | 557 | */ |
544 | while(*level >= 0) { | 558 | while(*level >= 0) { |
559 | WARN_ON(*level < 0); | ||
560 | WARN_ON(*level >= BTRFS_MAX_LEVEL); | ||
545 | cur = path->nodes[*level]; | 561 | cur = path->nodes[*level]; |
546 | if (btrfs_header_level(btrfs_buffer_header(cur)) != *level) | 562 | if (btrfs_header_level(btrfs_buffer_header(cur)) != *level) |
547 | WARN_ON(1); | 563 | WARN_ON(1); |
@@ -564,6 +580,7 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root | |||
564 | continue; | 580 | continue; |
565 | } | 581 | } |
566 | next = read_tree_block(root, blocknr); | 582 | next = read_tree_block(root, blocknr); |
583 | WARN_ON(*level <= 0); | ||
567 | if (path->nodes[*level-1]) | 584 | if (path->nodes[*level-1]) |
568 | btrfs_block_release(root, path->nodes[*level-1]); | 585 | btrfs_block_release(root, path->nodes[*level-1]); |
569 | path->nodes[*level-1] = next; | 586 | path->nodes[*level-1] = next; |
@@ -571,6 +588,8 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root | |||
571 | path->slots[*level] = 0; | 588 | path->slots[*level] = 0; |
572 | } | 589 | } |
573 | out: | 590 | out: |
591 | WARN_ON(*level < 0); | ||
592 | WARN_ON(*level >= BTRFS_MAX_LEVEL); | ||
574 | ret = btrfs_free_extent(trans, root, | 593 | ret = btrfs_free_extent(trans, root, |
575 | path->nodes[*level]->b_blocknr, 1, 1); | 594 | path->nodes[*level]->b_blocknr, 1, 1); |
576 | btrfs_block_release(root, path->nodes[*level]); | 595 | btrfs_block_release(root, path->nodes[*level]); |
@@ -622,33 +641,36 @@ int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root | |||
622 | int ret = 0; | 641 | int ret = 0; |
623 | int wret; | 642 | int wret; |
624 | int level; | 643 | int level; |
625 | struct btrfs_path path; | 644 | struct btrfs_path *path; |
626 | int i; | 645 | int i; |
627 | int orig_level; | 646 | int orig_level; |
628 | 647 | ||
629 | btrfs_init_path(&path); | 648 | path = btrfs_alloc_path(); |
649 | BUG_ON(!path); | ||
650 | btrfs_init_path(path); | ||
630 | 651 | ||
631 | level = btrfs_header_level(btrfs_buffer_header(snap)); | 652 | level = btrfs_header_level(btrfs_buffer_header(snap)); |
632 | orig_level = level; | 653 | orig_level = level; |
633 | path.nodes[level] = snap; | 654 | path->nodes[level] = snap; |
634 | path.slots[level] = 0; | 655 | path->slots[level] = 0; |
635 | while(1) { | 656 | while(1) { |
636 | wret = walk_down_tree(trans, root, &path, &level); | 657 | wret = walk_down_tree(trans, root, path, &level); |
637 | if (wret > 0) | 658 | if (wret > 0) |
638 | break; | 659 | break; |
639 | if (wret < 0) | 660 | if (wret < 0) |
640 | ret = wret; | 661 | ret = wret; |
641 | 662 | ||
642 | wret = walk_up_tree(trans, root, &path, &level); | 663 | wret = walk_up_tree(trans, root, path, &level); |
643 | if (wret > 0) | 664 | if (wret > 0) |
644 | break; | 665 | break; |
645 | if (wret < 0) | 666 | if (wret < 0) |
646 | ret = wret; | 667 | ret = wret; |
647 | } | 668 | } |
648 | for (i = 0; i <= orig_level; i++) { | 669 | for (i = 0; i <= orig_level; i++) { |
649 | if (path.nodes[i]) { | 670 | if (path->nodes[i]) { |
650 | btrfs_block_release(root, path.nodes[i]); | 671 | btrfs_block_release(root, path->nodes[i]); |
651 | } | 672 | } |
652 | } | 673 | } |
674 | btrfs_free_path(path); | ||
653 | return ret; | 675 | return ret; |
654 | } | 676 | } |