diff options
Diffstat (limited to 'fs/btrfs/disk-io.c')
| -rw-r--r-- | fs/btrfs/disk-io.c | 132 |
1 files changed, 125 insertions, 7 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 830d261d0e6b..d7a7315bd031 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include <linux/crc32c.h> | 29 | #include <linux/crc32c.h> |
| 30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
| 31 | #include <linux/migrate.h> | 31 | #include <linux/migrate.h> |
| 32 | #include <asm/unaligned.h> | ||
| 32 | #include "compat.h" | 33 | #include "compat.h" |
| 33 | #include "ctree.h" | 34 | #include "ctree.h" |
| 34 | #include "disk-io.h" | 35 | #include "disk-io.h" |
| @@ -198,7 +199,7 @@ u32 btrfs_csum_data(struct btrfs_root *root, char *data, u32 seed, size_t len) | |||
| 198 | 199 | ||
| 199 | void btrfs_csum_final(u32 crc, char *result) | 200 | void btrfs_csum_final(u32 crc, char *result) |
| 200 | { | 201 | { |
| 201 | *(__le32 *)result = ~cpu_to_le32(crc); | 202 | put_unaligned_le32(~crc, result); |
| 202 | } | 203 | } |
| 203 | 204 | ||
| 204 | /* | 205 | /* |
| @@ -323,6 +324,7 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root, | |||
| 323 | int num_copies = 0; | 324 | int num_copies = 0; |
| 324 | int mirror_num = 0; | 325 | int mirror_num = 0; |
| 325 | 326 | ||
| 327 | clear_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags); | ||
| 326 | io_tree = &BTRFS_I(root->fs_info->btree_inode)->io_tree; | 328 | io_tree = &BTRFS_I(root->fs_info->btree_inode)->io_tree; |
| 327 | while (1) { | 329 | while (1) { |
| 328 | ret = read_extent_buffer_pages(io_tree, eb, start, 1, | 330 | ret = read_extent_buffer_pages(io_tree, eb, start, 1, |
| @@ -331,6 +333,14 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root, | |||
| 331 | !verify_parent_transid(io_tree, eb, parent_transid)) | 333 | !verify_parent_transid(io_tree, eb, parent_transid)) |
| 332 | return ret; | 334 | return ret; |
| 333 | 335 | ||
| 336 | /* | ||
| 337 | * This buffer's crc is fine, but its contents are corrupted, so | ||
| 338 | * there is no reason to read the other copies, they won't be | ||
| 339 | * any less wrong. | ||
| 340 | */ | ||
| 341 | if (test_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags)) | ||
| 342 | return ret; | ||
| 343 | |||
| 334 | num_copies = btrfs_num_copies(&root->fs_info->mapping_tree, | 344 | num_copies = btrfs_num_copies(&root->fs_info->mapping_tree, |
| 335 | eb->start, eb->len); | 345 | eb->start, eb->len); |
| 336 | if (num_copies == 1) | 346 | if (num_copies == 1) |
| @@ -419,6 +429,73 @@ static int check_tree_block_fsid(struct btrfs_root *root, | |||
| 419 | return ret; | 429 | return ret; |
| 420 | } | 430 | } |
| 421 | 431 | ||
| 432 | #define CORRUPT(reason, eb, root, slot) \ | ||
| 433 | printk(KERN_CRIT "btrfs: corrupt leaf, %s: block=%llu," \ | ||
| 434 | "root=%llu, slot=%d\n", reason, \ | ||
| 435 | (unsigned long long)btrfs_header_bytenr(eb), \ | ||
| 436 | (unsigned long long)root->objectid, slot) | ||
| 437 | |||
| 438 | static noinline int check_leaf(struct btrfs_root *root, | ||
| 439 | struct extent_buffer *leaf) | ||
| 440 | { | ||
| 441 | struct btrfs_key key; | ||
| 442 | struct btrfs_key leaf_key; | ||
| 443 | u32 nritems = btrfs_header_nritems(leaf); | ||
| 444 | int slot; | ||
| 445 | |||
| 446 | if (nritems == 0) | ||
| 447 | return 0; | ||
| 448 | |||
| 449 | /* Check the 0 item */ | ||
| 450 | if (btrfs_item_offset_nr(leaf, 0) + btrfs_item_size_nr(leaf, 0) != | ||
| 451 | BTRFS_LEAF_DATA_SIZE(root)) { | ||
| 452 | CORRUPT("invalid item offset size pair", leaf, root, 0); | ||
| 453 | return -EIO; | ||
| 454 | } | ||
| 455 | |||
| 456 | /* | ||
| 457 | * Check to make sure each items keys are in the correct order and their | ||
| 458 | * offsets make sense. We only have to loop through nritems-1 because | ||
| 459 | * we check the current slot against the next slot, which verifies the | ||
| 460 | * next slot's offset+size makes sense and that the current's slot | ||
| 461 | * offset is correct. | ||
| 462 | */ | ||
| 463 | for (slot = 0; slot < nritems - 1; slot++) { | ||
| 464 | btrfs_item_key_to_cpu(leaf, &leaf_key, slot); | ||
| 465 | btrfs_item_key_to_cpu(leaf, &key, slot + 1); | ||
| 466 | |||
| 467 | /* Make sure the keys are in the right order */ | ||
| 468 | if (btrfs_comp_cpu_keys(&leaf_key, &key) >= 0) { | ||
| 469 | CORRUPT("bad key order", leaf, root, slot); | ||
| 470 | return -EIO; | ||
| 471 | } | ||
| 472 | |||
| 473 | /* | ||
| 474 | * Make sure the offset and ends are right, remember that the | ||
| 475 | * item data starts at the end of the leaf and grows towards the | ||
| 476 | * front. | ||
| 477 | */ | ||
| 478 | if (btrfs_item_offset_nr(leaf, slot) != | ||
| 479 | btrfs_item_end_nr(leaf, slot + 1)) { | ||
| 480 | CORRUPT("slot offset bad", leaf, root, slot); | ||
| 481 | return -EIO; | ||
| 482 | } | ||
| 483 | |||
| 484 | /* | ||
| 485 | * Check to make sure that we don't point outside of the leaf, | ||
| 486 | * just incase all the items are consistent to eachother, but | ||
| 487 | * all point outside of the leaf. | ||
| 488 | */ | ||
| 489 | if (btrfs_item_end_nr(leaf, slot) > | ||
| 490 | BTRFS_LEAF_DATA_SIZE(root)) { | ||
| 491 | CORRUPT("slot end outside of leaf", leaf, root, slot); | ||
| 492 | return -EIO; | ||
| 493 | } | ||
| 494 | } | ||
| 495 | |||
| 496 | return 0; | ||
| 497 | } | ||
| 498 | |||
| 422 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | 499 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
| 423 | void btrfs_set_buffer_lockdep_class(struct extent_buffer *eb, int level) | 500 | void btrfs_set_buffer_lockdep_class(struct extent_buffer *eb, int level) |
| 424 | { | 501 | { |
| @@ -485,8 +562,20 @@ static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end, | |||
| 485 | btrfs_set_buffer_lockdep_class(eb, found_level); | 562 | btrfs_set_buffer_lockdep_class(eb, found_level); |
| 486 | 563 | ||
| 487 | ret = csum_tree_block(root, eb, 1); | 564 | ret = csum_tree_block(root, eb, 1); |
| 488 | if (ret) | 565 | if (ret) { |
| 489 | ret = -EIO; | 566 | ret = -EIO; |
| 567 | goto err; | ||
| 568 | } | ||
| 569 | |||
| 570 | /* | ||
| 571 | * If this is a leaf block and it is corrupt, set the corrupt bit so | ||
| 572 | * that we don't try and read the other copies of this block, just | ||
| 573 | * return -EIO. | ||
| 574 | */ | ||
| 575 | if (found_level == 0 && check_leaf(root, eb)) { | ||
| 576 | set_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags); | ||
| 577 | ret = -EIO; | ||
| 578 | } | ||
| 490 | 579 | ||
| 491 | end = min_t(u64, eb->len, PAGE_CACHE_SIZE); | 580 | end = min_t(u64, eb->len, PAGE_CACHE_SIZE); |
| 492 | end = eb->start + end - 1; | 581 | end = eb->start + end - 1; |
| @@ -1159,7 +1248,10 @@ struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_root *tree_root, | |||
| 1159 | root, fs_info, location->objectid); | 1248 | root, fs_info, location->objectid); |
| 1160 | 1249 | ||
| 1161 | path = btrfs_alloc_path(); | 1250 | path = btrfs_alloc_path(); |
| 1162 | BUG_ON(!path); | 1251 | if (!path) { |
| 1252 | kfree(root); | ||
| 1253 | return ERR_PTR(-ENOMEM); | ||
| 1254 | } | ||
| 1163 | ret = btrfs_search_slot(NULL, tree_root, location, path, 0, 0); | 1255 | ret = btrfs_search_slot(NULL, tree_root, location, path, 0, 0); |
| 1164 | if (ret == 0) { | 1256 | if (ret == 0) { |
| 1165 | l = path->nodes[0]; | 1257 | l = path->nodes[0]; |
| @@ -1553,6 +1645,8 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
| 1553 | goto fail_bdi; | 1645 | goto fail_bdi; |
| 1554 | } | 1646 | } |
| 1555 | 1647 | ||
| 1648 | fs_info->btree_inode->i_mapping->flags &= ~__GFP_FS; | ||
| 1649 | |||
| 1556 | INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_ATOMIC); | 1650 | INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_ATOMIC); |
| 1557 | INIT_LIST_HEAD(&fs_info->trans_list); | 1651 | INIT_LIST_HEAD(&fs_info->trans_list); |
| 1558 | INIT_LIST_HEAD(&fs_info->dead_roots); | 1652 | INIT_LIST_HEAD(&fs_info->dead_roots); |
| @@ -1683,6 +1777,12 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
| 1683 | 1777 | ||
| 1684 | btrfs_check_super_valid(fs_info, sb->s_flags & MS_RDONLY); | 1778 | btrfs_check_super_valid(fs_info, sb->s_flags & MS_RDONLY); |
| 1685 | 1779 | ||
| 1780 | /* | ||
| 1781 | * In the long term, we'll store the compression type in the super | ||
| 1782 | * block, and it'll be used for per file compression control. | ||
| 1783 | */ | ||
| 1784 | fs_info->compress_type = BTRFS_COMPRESS_ZLIB; | ||
| 1785 | |||
| 1686 | ret = btrfs_parse_options(tree_root, options); | 1786 | ret = btrfs_parse_options(tree_root, options); |
| 1687 | if (ret) { | 1787 | if (ret) { |
| 1688 | err = ret; | 1788 | err = ret; |
| @@ -1888,6 +1988,12 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
| 1888 | fs_info->metadata_alloc_profile = (u64)-1; | 1988 | fs_info->metadata_alloc_profile = (u64)-1; |
| 1889 | fs_info->system_alloc_profile = fs_info->metadata_alloc_profile; | 1989 | fs_info->system_alloc_profile = fs_info->metadata_alloc_profile; |
| 1890 | 1990 | ||
| 1991 | ret = btrfs_init_space_info(fs_info); | ||
| 1992 | if (ret) { | ||
| 1993 | printk(KERN_ERR "Failed to initial space info: %d\n", ret); | ||
| 1994 | goto fail_block_groups; | ||
| 1995 | } | ||
| 1996 | |||
| 1891 | ret = btrfs_read_block_groups(extent_root); | 1997 | ret = btrfs_read_block_groups(extent_root); |
| 1892 | if (ret) { | 1998 | if (ret) { |
| 1893 | printk(KERN_ERR "Failed to read block groups: %d\n", ret); | 1999 | printk(KERN_ERR "Failed to read block groups: %d\n", ret); |
| @@ -1979,9 +2085,14 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
| 1979 | 2085 | ||
| 1980 | if (!(sb->s_flags & MS_RDONLY)) { | 2086 | if (!(sb->s_flags & MS_RDONLY)) { |
| 1981 | down_read(&fs_info->cleanup_work_sem); | 2087 | down_read(&fs_info->cleanup_work_sem); |
| 1982 | btrfs_orphan_cleanup(fs_info->fs_root); | 2088 | err = btrfs_orphan_cleanup(fs_info->fs_root); |
| 1983 | btrfs_orphan_cleanup(fs_info->tree_root); | 2089 | if (!err) |
| 2090 | err = btrfs_orphan_cleanup(fs_info->tree_root); | ||
| 1984 | up_read(&fs_info->cleanup_work_sem); | 2091 | up_read(&fs_info->cleanup_work_sem); |
| 2092 | if (err) { | ||
| 2093 | close_ctree(tree_root); | ||
| 2094 | return ERR_PTR(err); | ||
| 2095 | } | ||
| 1985 | } | 2096 | } |
| 1986 | 2097 | ||
| 1987 | return tree_root; | 2098 | return tree_root; |
| @@ -2356,8 +2467,12 @@ int btrfs_cleanup_fs_roots(struct btrfs_fs_info *fs_info) | |||
| 2356 | 2467 | ||
| 2357 | root_objectid = gang[ret - 1]->root_key.objectid + 1; | 2468 | root_objectid = gang[ret - 1]->root_key.objectid + 1; |
| 2358 | for (i = 0; i < ret; i++) { | 2469 | for (i = 0; i < ret; i++) { |
| 2470 | int err; | ||
| 2471 | |||
| 2359 | root_objectid = gang[i]->root_key.objectid; | 2472 | root_objectid = gang[i]->root_key.objectid; |
| 2360 | btrfs_orphan_cleanup(gang[i]); | 2473 | err = btrfs_orphan_cleanup(gang[i]); |
| 2474 | if (err) | ||
| 2475 | return err; | ||
| 2361 | } | 2476 | } |
| 2362 | root_objectid++; | 2477 | root_objectid++; |
| 2363 | } | 2478 | } |
| @@ -2868,7 +2983,10 @@ static int btrfs_destroy_pinned_extent(struct btrfs_root *root, | |||
| 2868 | break; | 2983 | break; |
| 2869 | 2984 | ||
| 2870 | /* opt_discard */ | 2985 | /* opt_discard */ |
| 2871 | ret = btrfs_error_discard_extent(root, start, end + 1 - start); | 2986 | if (btrfs_test_opt(root, DISCARD)) |
| 2987 | ret = btrfs_error_discard_extent(root, start, | ||
| 2988 | end + 1 - start, | ||
| 2989 | NULL); | ||
| 2872 | 2990 | ||
| 2873 | clear_extent_dirty(unpin, start, end, GFP_NOFS); | 2991 | clear_extent_dirty(unpin, start, end, GFP_NOFS); |
| 2874 | btrfs_error_unpin_extent_range(root, start, end); | 2992 | btrfs_error_unpin_extent_range(root, start, end); |
