diff options
-rw-r--r-- | fs/btrfs/disk-io.c | 67 |
1 files changed, 65 insertions, 2 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 09b3c8a0c790..fc8dfaa27967 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -3817,10 +3817,73 @@ int btrfs_read_buffer(struct extent_buffer *buf, u64 parent_transid) | |||
3817 | static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info, | 3817 | static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info, |
3818 | int read_only) | 3818 | int read_only) |
3819 | { | 3819 | { |
3820 | struct btrfs_super_block *sb = fs_info->super_copy; | ||
3821 | int ret = 0; | ||
3822 | |||
3823 | if (sb->root_level > BTRFS_MAX_LEVEL) { | ||
3824 | printk(KERN_ERR "BTRFS: tree_root level too big: %d > %d\n", | ||
3825 | sb->root_level, BTRFS_MAX_LEVEL); | ||
3826 | ret = -EINVAL; | ||
3827 | } | ||
3828 | if (sb->chunk_root_level > BTRFS_MAX_LEVEL) { | ||
3829 | printk(KERN_ERR "BTRFS: chunk_root level too big: %d > %d\n", | ||
3830 | sb->chunk_root_level, BTRFS_MAX_LEVEL); | ||
3831 | ret = -EINVAL; | ||
3832 | } | ||
3833 | if (sb->log_root_level > BTRFS_MAX_LEVEL) { | ||
3834 | printk(KERN_ERR "BTRFS: log_root level too big: %d > %d\n", | ||
3835 | sb->log_root_level, BTRFS_MAX_LEVEL); | ||
3836 | ret = -EINVAL; | ||
3837 | } | ||
3838 | |||
3820 | /* | 3839 | /* |
3821 | * Placeholder for checks | 3840 | * The common minimum, we don't know if we can trust the nodesize/sectorsize |
3841 | * items yet, they'll be verified later. Issue just a warning. | ||
3822 | */ | 3842 | */ |
3823 | return 0; | 3843 | if (!IS_ALIGNED(sb->root, 4096)) |
3844 | printk(KERN_WARNING "BTRFS: tree_root block unaligned: %llu\n", | ||
3845 | sb->root); | ||
3846 | if (!IS_ALIGNED(sb->chunk_root, 4096)) | ||
3847 | printk(KERN_WARNING "BTRFS: tree_root block unaligned: %llu\n", | ||
3848 | sb->chunk_root); | ||
3849 | if (!IS_ALIGNED(sb->log_root, 4096)) | ||
3850 | printk(KERN_WARNING "BTRFS: tree_root block unaligned: %llu\n", | ||
3851 | sb->log_root); | ||
3852 | |||
3853 | if (memcmp(fs_info->fsid, sb->dev_item.fsid, BTRFS_UUID_SIZE) != 0) { | ||
3854 | printk(KERN_ERR "BTRFS: dev_item UUID does not match fsid: %pU != %pU\n", | ||
3855 | fs_info->fsid, sb->dev_item.fsid); | ||
3856 | ret = -EINVAL; | ||
3857 | } | ||
3858 | |||
3859 | /* | ||
3860 | * Hint to catch really bogus numbers, bitflips or so, more exact checks are | ||
3861 | * done later | ||
3862 | */ | ||
3863 | if (sb->num_devices > (1UL << 31)) | ||
3864 | printk(KERN_WARNING "BTRFS: suspicious number of devices: %llu\n", | ||
3865 | sb->num_devices); | ||
3866 | |||
3867 | if (sb->bytenr != BTRFS_SUPER_INFO_OFFSET) { | ||
3868 | printk(KERN_ERR "BTRFS: super offset mismatch %llu != %u\n", | ||
3869 | sb->bytenr, BTRFS_SUPER_INFO_OFFSET); | ||
3870 | ret = -EINVAL; | ||
3871 | } | ||
3872 | |||
3873 | /* | ||
3874 | * The generation is a global counter, we'll trust it more than the others | ||
3875 | * but it's still possible that it's the one that's wrong. | ||
3876 | */ | ||
3877 | if (sb->generation < sb->chunk_root_generation) | ||
3878 | printk(KERN_WARNING | ||
3879 | "BTRFS: suspicious: generation < chunk_root_generation: %llu < %llu\n", | ||
3880 | sb->generation, sb->chunk_root_generation); | ||
3881 | if (sb->generation < sb->cache_generation && sb->cache_generation != (u64)-1) | ||
3882 | printk(KERN_WARNING | ||
3883 | "BTRFS: suspicious: generation < cache_generation: %llu < %llu\n", | ||
3884 | sb->generation, sb->cache_generation); | ||
3885 | |||
3886 | return ret; | ||
3824 | } | 3887 | } |
3825 | 3888 | ||
3826 | static void btrfs_error_commit_super(struct btrfs_root *root) | 3889 | static void btrfs_error_commit_super(struct btrfs_root *root) |