diff options
author | Theodore Ts'o <tytso@mit.edu> | 2009-05-17 15:38:01 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2009-05-17 15:38:01 -0400 |
commit | 6fd058f7791087648c683eb8572edf3be3c4c23c (patch) | |
tree | 0d80791532d2d022c91f20013003716eaf0afb40 /fs/ext4/super.c | |
parent | 2ac3b6e00acb46406c993d57921f86a594aafe08 (diff) |
ext4: Add a comprehensive block validity check to ext4_get_blocks()
To catch filesystem bugs or corruption which could lead to the
filesystem getting severly damaged, this patch adds a facility for
tracking all of the filesystem metadata blocks by contiguous regions
in a red-black tree. This allows quick searching of the tree to
locate extents which might overlap with filesystem metadata blocks.
This facility is also used by the multi-block allocator to assure that
it is not allocating blocks out of the system zone, as well as by the
routines used when reading indirect blocks and extents information
from disk to make sure their contents are valid.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/super.c')
-rw-r--r-- | fs/ext4/super.c | 32 |
1 files changed, 30 insertions, 2 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index dc34ed3d1327..600b7ad699b5 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -568,6 +568,7 @@ static void ext4_put_super(struct super_block *sb) | |||
568 | struct ext4_super_block *es = sbi->s_es; | 568 | struct ext4_super_block *es = sbi->s_es; |
569 | int i, err; | 569 | int i, err; |
570 | 570 | ||
571 | ext4_release_system_zone(sb); | ||
571 | ext4_mb_release(sb); | 572 | ext4_mb_release(sb); |
572 | ext4_ext_release(sb); | 573 | ext4_ext_release(sb); |
573 | ext4_xattr_put_super(sb); | 574 | ext4_xattr_put_super(sb); |
@@ -1055,6 +1056,7 @@ enum { | |||
1055 | Opt_ignore, Opt_barrier, Opt_nobarrier, Opt_err, Opt_resize, | 1056 | Opt_ignore, Opt_barrier, Opt_nobarrier, Opt_err, Opt_resize, |
1056 | Opt_usrquota, Opt_grpquota, Opt_i_version, | 1057 | Opt_usrquota, Opt_grpquota, Opt_i_version, |
1057 | Opt_stripe, Opt_delalloc, Opt_nodelalloc, | 1058 | Opt_stripe, Opt_delalloc, Opt_nodelalloc, |
1059 | Opt_block_validity, Opt_noblock_validity, | ||
1058 | Opt_inode_readahead_blks, Opt_journal_ioprio | 1060 | Opt_inode_readahead_blks, Opt_journal_ioprio |
1059 | }; | 1061 | }; |
1060 | 1062 | ||
@@ -1114,6 +1116,8 @@ static const match_table_t tokens = { | |||
1114 | {Opt_resize, "resize"}, | 1116 | {Opt_resize, "resize"}, |
1115 | {Opt_delalloc, "delalloc"}, | 1117 | {Opt_delalloc, "delalloc"}, |
1116 | {Opt_nodelalloc, "nodelalloc"}, | 1118 | {Opt_nodelalloc, "nodelalloc"}, |
1119 | {Opt_block_validity, "block_validity"}, | ||
1120 | {Opt_noblock_validity, "noblock_validity"}, | ||
1117 | {Opt_inode_readahead_blks, "inode_readahead_blks=%u"}, | 1121 | {Opt_inode_readahead_blks, "inode_readahead_blks=%u"}, |
1118 | {Opt_journal_ioprio, "journal_ioprio=%u"}, | 1122 | {Opt_journal_ioprio, "journal_ioprio=%u"}, |
1119 | {Opt_auto_da_alloc, "auto_da_alloc=%u"}, | 1123 | {Opt_auto_da_alloc, "auto_da_alloc=%u"}, |
@@ -1508,6 +1512,12 @@ set_qf_format: | |||
1508 | case Opt_delalloc: | 1512 | case Opt_delalloc: |
1509 | set_opt(sbi->s_mount_opt, DELALLOC); | 1513 | set_opt(sbi->s_mount_opt, DELALLOC); |
1510 | break; | 1514 | break; |
1515 | case Opt_block_validity: | ||
1516 | set_opt(sbi->s_mount_opt, BLOCK_VALIDITY); | ||
1517 | break; | ||
1518 | case Opt_noblock_validity: | ||
1519 | clear_opt(sbi->s_mount_opt, BLOCK_VALIDITY); | ||
1520 | break; | ||
1511 | case Opt_inode_readahead_blks: | 1521 | case Opt_inode_readahead_blks: |
1512 | if (match_int(&args[0], &option)) | 1522 | if (match_int(&args[0], &option)) |
1513 | return 0; | 1523 | return 0; |
@@ -2826,6 +2836,13 @@ no_journal: | |||
2826 | } else if (test_opt(sb, DELALLOC)) | 2836 | } else if (test_opt(sb, DELALLOC)) |
2827 | printk(KERN_INFO "EXT4-fs: delayed allocation enabled\n"); | 2837 | printk(KERN_INFO "EXT4-fs: delayed allocation enabled\n"); |
2828 | 2838 | ||
2839 | err = ext4_setup_system_zone(sb); | ||
2840 | if (err) { | ||
2841 | printk(KERN_ERR "EXT4-fs: failed to initialize system " | ||
2842 | "zone (%d)\n", err); | ||
2843 | goto failed_mount4; | ||
2844 | } | ||
2845 | |||
2829 | ext4_ext_init(sb); | 2846 | ext4_ext_init(sb); |
2830 | err = ext4_mb_init(sb, needs_recovery); | 2847 | err = ext4_mb_init(sb, needs_recovery); |
2831 | if (err) { | 2848 | if (err) { |
@@ -2875,6 +2892,7 @@ cantfind_ext4: | |||
2875 | 2892 | ||
2876 | failed_mount4: | 2893 | failed_mount4: |
2877 | printk(KERN_ERR "EXT4-fs (device %s): mount failed\n", sb->s_id); | 2894 | printk(KERN_ERR "EXT4-fs (device %s): mount failed\n", sb->s_id); |
2895 | ext4_release_system_zone(sb); | ||
2878 | if (sbi->s_journal) { | 2896 | if (sbi->s_journal) { |
2879 | jbd2_journal_destroy(sbi->s_journal); | 2897 | jbd2_journal_destroy(sbi->s_journal); |
2880 | sbi->s_journal = NULL; | 2898 | sbi->s_journal = NULL; |
@@ -3515,6 +3533,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data) | |||
3515 | sb->s_flags &= ~MS_RDONLY; | 3533 | sb->s_flags &= ~MS_RDONLY; |
3516 | } | 3534 | } |
3517 | } | 3535 | } |
3536 | ext4_setup_system_zone(sb); | ||
3518 | if (sbi->s_journal == NULL) | 3537 | if (sbi->s_journal == NULL) |
3519 | ext4_commit_super(sb, 1); | 3538 | ext4_commit_super(sb, 1); |
3520 | 3539 | ||
@@ -3927,13 +3946,16 @@ static int __init init_ext4_fs(void) | |||
3927 | { | 3946 | { |
3928 | int err; | 3947 | int err; |
3929 | 3948 | ||
3949 | err = init_ext4_system_zone(); | ||
3950 | if (err) | ||
3951 | return err; | ||
3930 | ext4_kset = kset_create_and_add("ext4", NULL, fs_kobj); | 3952 | ext4_kset = kset_create_and_add("ext4", NULL, fs_kobj); |
3931 | if (!ext4_kset) | 3953 | if (!ext4_kset) |
3932 | return -ENOMEM; | 3954 | goto out4; |
3933 | ext4_proc_root = proc_mkdir("fs/ext4", NULL); | 3955 | ext4_proc_root = proc_mkdir("fs/ext4", NULL); |
3934 | err = init_ext4_mballoc(); | 3956 | err = init_ext4_mballoc(); |
3935 | if (err) | 3957 | if (err) |
3936 | return err; | 3958 | goto out3; |
3937 | 3959 | ||
3938 | err = init_ext4_xattr(); | 3960 | err = init_ext4_xattr(); |
3939 | if (err) | 3961 | if (err) |
@@ -3958,6 +3980,11 @@ out1: | |||
3958 | exit_ext4_xattr(); | 3980 | exit_ext4_xattr(); |
3959 | out2: | 3981 | out2: |
3960 | exit_ext4_mballoc(); | 3982 | exit_ext4_mballoc(); |
3983 | out3: | ||
3984 | remove_proc_entry("fs/ext4", NULL); | ||
3985 | kset_unregister(ext4_kset); | ||
3986 | out4: | ||
3987 | exit_ext4_system_zone(); | ||
3961 | return err; | 3988 | return err; |
3962 | } | 3989 | } |
3963 | 3990 | ||
@@ -3972,6 +3999,7 @@ static void __exit exit_ext4_fs(void) | |||
3972 | exit_ext4_mballoc(); | 3999 | exit_ext4_mballoc(); |
3973 | remove_proc_entry("fs/ext4", NULL); | 4000 | remove_proc_entry("fs/ext4", NULL); |
3974 | kset_unregister(ext4_kset); | 4001 | kset_unregister(ext4_kset); |
4002 | exit_ext4_system_zone(); | ||
3975 | } | 4003 | } |
3976 | 4004 | ||
3977 | MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others"); | 4005 | MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others"); |