diff options
author | David Sterba <dsterba@suse.cz> | 2012-03-05 18:06:18 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2012-03-28 20:30:28 -0400 |
commit | fcd1f065daca593badb7f99d473639cf3b551795 (patch) | |
tree | b4dda48c9db913270d66344a2787829149b3a2bd /fs/btrfs/disk-io.c | |
parent | 914b20070b413ca10f832c45a58b2894990f065f (diff) |
Btrfs: enhance superblock sanity checks
Validate checksum algorithm during mount and prevent BUG_ON later in
btrfs_super_csum_size.
Signed-off-by: David Sterba <dsterba@suse.cz>
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r-- | fs/btrfs/disk-io.c | 23 |
1 files changed, 18 insertions, 5 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 438993e3d832..38c2ee1ca0d5 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -48,7 +48,7 @@ | |||
48 | static struct extent_io_ops btree_extent_io_ops; | 48 | static struct extent_io_ops btree_extent_io_ops; |
49 | static void end_workqueue_fn(struct btrfs_work *work); | 49 | static void end_workqueue_fn(struct btrfs_work *work); |
50 | static void free_fs_root(struct btrfs_root *root); | 50 | static void free_fs_root(struct btrfs_root *root); |
51 | static void btrfs_check_super_valid(struct btrfs_fs_info *fs_info, | 51 | static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info, |
52 | int read_only); | 52 | int read_only); |
53 | static void btrfs_destroy_ordered_operations(struct btrfs_root *root); | 53 | static void btrfs_destroy_ordered_operations(struct btrfs_root *root); |
54 | static void btrfs_destroy_ordered_extents(struct btrfs_root *root); | 54 | static void btrfs_destroy_ordered_extents(struct btrfs_root *root); |
@@ -2135,7 +2135,12 @@ int open_ctree(struct super_block *sb, | |||
2135 | /* check FS state, whether FS is broken. */ | 2135 | /* check FS state, whether FS is broken. */ |
2136 | fs_info->fs_state |= btrfs_super_flags(disk_super); | 2136 | fs_info->fs_state |= btrfs_super_flags(disk_super); |
2137 | 2137 | ||
2138 | btrfs_check_super_valid(fs_info, sb->s_flags & MS_RDONLY); | 2138 | ret = btrfs_check_super_valid(fs_info, sb->s_flags & MS_RDONLY); |
2139 | if (ret) { | ||
2140 | printk(KERN_ERR "btrfs: superblock contains fatal errors\n"); | ||
2141 | err = ret; | ||
2142 | goto fail_alloc; | ||
2143 | } | ||
2139 | 2144 | ||
2140 | /* | 2145 | /* |
2141 | * run through our array of backup supers and setup | 2146 | * run through our array of backup supers and setup |
@@ -3324,15 +3329,23 @@ out: | |||
3324 | return 0; | 3329 | return 0; |
3325 | } | 3330 | } |
3326 | 3331 | ||
3327 | static void btrfs_check_super_valid(struct btrfs_fs_info *fs_info, | 3332 | static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info, |
3328 | int read_only) | 3333 | int read_only) |
3329 | { | 3334 | { |
3335 | if (btrfs_super_csum_type(fs_info->super_copy) >= ARRAY_SIZE(btrfs_csum_sizes)) { | ||
3336 | printk(KERN_ERR "btrfs: unsupported checksum algorithm\n"); | ||
3337 | return -EINVAL; | ||
3338 | } | ||
3339 | |||
3330 | if (read_only) | 3340 | if (read_only) |
3331 | return; | 3341 | return 0; |
3332 | 3342 | ||
3333 | if (fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) | 3343 | if (fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) { |
3334 | printk(KERN_WARNING "warning: mount fs with errors, " | 3344 | printk(KERN_WARNING "warning: mount fs with errors, " |
3335 | "running btrfsck is recommended\n"); | 3345 | "running btrfsck is recommended\n"); |
3346 | } | ||
3347 | |||
3348 | return 0; | ||
3336 | } | 3349 | } |
3337 | 3350 | ||
3338 | int btrfs_error_commit_super(struct btrfs_root *root) | 3351 | int btrfs_error_commit_super(struct btrfs_root *root) |