diff options
| author | Chris Mason <chris.mason@oracle.com> | 2007-06-28 15:57:36 -0400 |
|---|---|---|
| committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-06-28 15:57:36 -0400 |
| commit | ccd467d60e81b48cdbecae93532b66bcdedca91d (patch) | |
| tree | 7c8c74ca8c6c058fc2e3c90c0082e796b7c1e92e /fs/btrfs/extent-tree.c | |
| parent | f2654de42a759127cb1f1e8a626ec94178732e20 (diff) | |
Btrfs: crash recovery fixes
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 | 37 |
1 files changed, 33 insertions, 4 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 01dc30579287..14b93268920e 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
| @@ -523,6 +523,7 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
| 523 | } | 523 | } |
| 524 | return 0; | 524 | return 0; |
| 525 | fail: | 525 | fail: |
| 526 | WARN_ON(1); | ||
| 526 | for (i =0; i < faili; i++) { | 527 | for (i =0; i < faili; i++) { |
| 527 | if (leaf) { | 528 | if (leaf) { |
| 528 | u64 disk_blocknr; | 529 | u64 disk_blocknr; |
| @@ -572,7 +573,7 @@ static int write_one_cache_group(struct btrfs_trans_handle *trans, | |||
| 572 | bi = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0], | 573 | bi = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0], |
| 573 | struct btrfs_block_group_item); | 574 | struct btrfs_block_group_item); |
| 574 | memcpy(bi, &cache->item, sizeof(*bi)); | 575 | memcpy(bi, &cache->item, sizeof(*bi)); |
| 575 | mark_buffer_dirty(path->nodes[0]); | 576 | btrfs_mark_buffer_dirty(path->nodes[0]); |
| 576 | btrfs_release_path(extent_root, path); | 577 | btrfs_release_path(extent_root, path); |
| 577 | fail: | 578 | fail: |
| 578 | finish_current_insert(trans, extent_root); | 579 | finish_current_insert(trans, extent_root); |
| @@ -739,8 +740,30 @@ static int try_remove_page(struct address_space *mapping, unsigned long index) | |||
| 739 | return ret; | 740 | return ret; |
| 740 | } | 741 | } |
| 741 | 742 | ||
| 742 | int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct | 743 | int btrfs_copy_pinned(struct btrfs_root *root, struct radix_tree_root *copy) |
| 743 | btrfs_root *root) | 744 | { |
| 745 | unsigned long gang[8]; | ||
| 746 | u64 last = 0; | ||
| 747 | struct radix_tree_root *pinned_radix = &root->fs_info->pinned_radix; | ||
| 748 | int ret; | ||
| 749 | int i; | ||
| 750 | |||
| 751 | while(1) { | ||
| 752 | ret = find_first_radix_bit(pinned_radix, gang, last, | ||
| 753 | ARRAY_SIZE(gang)); | ||
| 754 | if (!ret) | ||
| 755 | break; | ||
| 756 | for (i = 0 ; i < ret; i++) { | ||
| 757 | set_radix_bit(copy, gang[i]); | ||
| 758 | last = gang[i] + 1; | ||
| 759 | } | ||
| 760 | } | ||
| 761 | return 0; | ||
| 762 | } | ||
| 763 | |||
| 764 | int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, | ||
| 765 | struct btrfs_root *root, | ||
| 766 | struct radix_tree_root *unpin_radix) | ||
| 744 | { | 767 | { |
| 745 | unsigned long gang[8]; | 768 | unsigned long gang[8]; |
| 746 | struct inode *btree_inode = root->fs_info->btree_inode; | 769 | struct inode *btree_inode = root->fs_info->btree_inode; |
| @@ -752,7 +775,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct | |||
| 752 | struct radix_tree_root *extent_radix = &root->fs_info->extent_map_radix; | 775 | struct radix_tree_root *extent_radix = &root->fs_info->extent_map_radix; |
| 753 | 776 | ||
| 754 | while(1) { | 777 | while(1) { |
| 755 | ret = find_first_radix_bit(pinned_radix, gang, 0, | 778 | ret = find_first_radix_bit(unpin_radix, gang, 0, |
| 756 | ARRAY_SIZE(gang)); | 779 | ARRAY_SIZE(gang)); |
| 757 | if (!ret) | 780 | if (!ret) |
| 758 | break; | 781 | break; |
| @@ -760,6 +783,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct | |||
| 760 | first = gang[0]; | 783 | first = gang[0]; |
| 761 | for (i = 0; i < ret; i++) { | 784 | for (i = 0; i < ret; i++) { |
| 762 | clear_radix_bit(pinned_radix, gang[i]); | 785 | clear_radix_bit(pinned_radix, gang[i]); |
| 786 | clear_radix_bit(unpin_radix, gang[i]); | ||
| 763 | block_group = btrfs_lookup_block_group(root->fs_info, | 787 | block_group = btrfs_lookup_block_group(root->fs_info, |
| 764 | gang[i]); | 788 | gang[i]); |
| 765 | if (block_group) { | 789 | if (block_group) { |
| @@ -1309,6 +1333,7 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, | |||
| 1309 | if (data) { | 1333 | if (data) { |
| 1310 | ret = find_free_extent(trans, root, 0, 0, | 1334 | ret = find_free_extent(trans, root, 0, 0, |
| 1311 | search_end, 0, &prealloc_key, 0, 0, 0); | 1335 | search_end, 0, &prealloc_key, 0, 0, 0); |
| 1336 | BUG_ON(ret); | ||
| 1312 | if (ret) | 1337 | if (ret) |
| 1313 | return ret; | 1338 | return ret; |
| 1314 | exclude_nr = info->extent_tree_prealloc_nr; | 1339 | exclude_nr = info->extent_tree_prealloc_nr; |
| @@ -1319,6 +1344,7 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, | |||
| 1319 | ret = find_free_extent(trans, root, num_blocks, search_start, | 1344 | ret = find_free_extent(trans, root, num_blocks, search_start, |
| 1320 | search_end, hint_block, ins, | 1345 | search_end, hint_block, ins, |
| 1321 | exclude_start, exclude_nr, data); | 1346 | exclude_start, exclude_nr, data); |
| 1347 | BUG_ON(ret); | ||
| 1322 | if (ret) | 1348 | if (ret) |
| 1323 | return ret; | 1349 | return ret; |
| 1324 | 1350 | ||
| @@ -1334,10 +1360,12 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, | |||
| 1334 | if (!data) { | 1360 | if (!data) { |
| 1335 | exclude_start = ins->objectid; | 1361 | exclude_start = ins->objectid; |
| 1336 | exclude_nr = ins->offset; | 1362 | exclude_nr = ins->offset; |
| 1363 | hint_block = exclude_start + exclude_nr; | ||
| 1337 | ret = find_free_extent(trans, root, 0, search_start, | 1364 | ret = find_free_extent(trans, root, 0, search_start, |
| 1338 | search_end, hint_block, | 1365 | search_end, hint_block, |
| 1339 | &prealloc_key, exclude_start, | 1366 | &prealloc_key, exclude_start, |
| 1340 | exclude_nr, 0); | 1367 | exclude_nr, 0); |
| 1368 | BUG_ON(ret); | ||
| 1341 | if (ret) | 1369 | if (ret) |
| 1342 | return ret; | 1370 | return ret; |
| 1343 | } | 1371 | } |
| @@ -1348,6 +1376,7 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, | |||
| 1348 | ret = btrfs_insert_item(trans, extent_root, ins, &extent_item, | 1376 | ret = btrfs_insert_item(trans, extent_root, ins, &extent_item, |
| 1349 | sizeof(extent_item)); | 1377 | sizeof(extent_item)); |
| 1350 | 1378 | ||
| 1379 | BUG_ON(ret); | ||
| 1351 | finish_current_insert(trans, extent_root); | 1380 | finish_current_insert(trans, extent_root); |
| 1352 | pending_ret = del_pending_extents(trans, extent_root); | 1381 | pending_ret = del_pending_extents(trans, extent_root); |
| 1353 | if (ret) { | 1382 | if (ret) { |
