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) { |