diff options
author | Jan Kara <jack@suse.cz> | 2005-07-12 16:58:28 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-07-12 19:01:01 -0400 |
commit | 08c6a96fd77836856c090ebb39beadc81cb8484d (patch) | |
tree | 36e643a41179078abcb8a866894586cba9bbf7e0 /fs/ext3/super.c | |
parent | 5323125031799a7fd8602ce150c3902aedfdcba6 (diff) |
[PATCH] ext3: fix options parsing
Fix a problem with ext3 mount option parsing. When remount of a filesystem
fails, old options are now restored.
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/ext3/super.c')
-rw-r--r-- | fs/ext3/super.c | 70 |
1 files changed, 60 insertions, 10 deletions
diff --git a/fs/ext3/super.c b/fs/ext3/super.c index a6d1779d7de4..3c3c6e399fb3 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c | |||
@@ -890,7 +890,10 @@ clear_qf_name: | |||
890 | "quota turned on.\n"); | 890 | "quota turned on.\n"); |
891 | return 0; | 891 | return 0; |
892 | } | 892 | } |
893 | kfree(sbi->s_qf_names[qtype]); | 893 | /* |
894 | * The space will be released later when all options | ||
895 | * are confirmed to be correct | ||
896 | */ | ||
894 | sbi->s_qf_names[qtype] = NULL; | 897 | sbi->s_qf_names[qtype] = NULL; |
895 | break; | 898 | break; |
896 | case Opt_jqfmt_vfsold: | 899 | case Opt_jqfmt_vfsold: |
@@ -939,7 +942,7 @@ clear_qf_name: | |||
939 | case Opt_ignore: | 942 | case Opt_ignore: |
940 | break; | 943 | break; |
941 | case Opt_resize: | 944 | case Opt_resize: |
942 | if (!n_blocks_count) { | 945 | if (!is_remount) { |
943 | printk("EXT3-fs: resize option only available " | 946 | printk("EXT3-fs: resize option only available " |
944 | "for remount\n"); | 947 | "for remount\n"); |
945 | return 0; | 948 | return 0; |
@@ -2109,14 +2112,33 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data) | |||
2109 | { | 2112 | { |
2110 | struct ext3_super_block * es; | 2113 | struct ext3_super_block * es; |
2111 | struct ext3_sb_info *sbi = EXT3_SB(sb); | 2114 | struct ext3_sb_info *sbi = EXT3_SB(sb); |
2112 | unsigned long tmp; | ||
2113 | unsigned long n_blocks_count = 0; | 2115 | unsigned long n_blocks_count = 0; |
2116 | unsigned long old_sb_flags; | ||
2117 | struct ext3_mount_options old_opts; | ||
2118 | int err; | ||
2119 | #ifdef CONFIG_QUOTA | ||
2120 | int i; | ||
2121 | #endif | ||
2122 | |||
2123 | /* Store the original options */ | ||
2124 | old_sb_flags = sb->s_flags; | ||
2125 | old_opts.s_mount_opt = sbi->s_mount_opt; | ||
2126 | old_opts.s_resuid = sbi->s_resuid; | ||
2127 | old_opts.s_resgid = sbi->s_resgid; | ||
2128 | old_opts.s_commit_interval = sbi->s_commit_interval; | ||
2129 | #ifdef CONFIG_QUOTA | ||
2130 | old_opts.s_jquota_fmt = sbi->s_jquota_fmt; | ||
2131 | for (i = 0; i < MAXQUOTAS; i++) | ||
2132 | old_opts.s_qf_names[i] = sbi->s_qf_names[i]; | ||
2133 | #endif | ||
2114 | 2134 | ||
2115 | /* | 2135 | /* |
2116 | * Allow the "check" option to be passed as a remount option. | 2136 | * Allow the "check" option to be passed as a remount option. |
2117 | */ | 2137 | */ |
2118 | if (!parse_options(data, sb, &tmp, &n_blocks_count, 1)) | 2138 | if (!parse_options(data, sb, NULL, &n_blocks_count, 1)) { |
2119 | return -EINVAL; | 2139 | err = -EINVAL; |
2140 | goto restore_opts; | ||
2141 | } | ||
2120 | 2142 | ||
2121 | if (sbi->s_mount_opt & EXT3_MOUNT_ABORT) | 2143 | if (sbi->s_mount_opt & EXT3_MOUNT_ABORT) |
2122 | ext3_abort(sb, __FUNCTION__, "Abort forced by user"); | 2144 | ext3_abort(sb, __FUNCTION__, "Abort forced by user"); |
@@ -2130,8 +2152,10 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data) | |||
2130 | 2152 | ||
2131 | if ((*flags & MS_RDONLY) != (sb->s_flags & MS_RDONLY) || | 2153 | if ((*flags & MS_RDONLY) != (sb->s_flags & MS_RDONLY) || |
2132 | n_blocks_count > le32_to_cpu(es->s_blocks_count)) { | 2154 | n_blocks_count > le32_to_cpu(es->s_blocks_count)) { |
2133 | if (sbi->s_mount_opt & EXT3_MOUNT_ABORT) | 2155 | if (sbi->s_mount_opt & EXT3_MOUNT_ABORT) { |
2134 | return -EROFS; | 2156 | err = -EROFS; |
2157 | goto restore_opts; | ||
2158 | } | ||
2135 | 2159 | ||
2136 | if (*flags & MS_RDONLY) { | 2160 | if (*flags & MS_RDONLY) { |
2137 | /* | 2161 | /* |
@@ -2158,7 +2182,8 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data) | |||
2158 | "remount RDWR because of unsupported " | 2182 | "remount RDWR because of unsupported " |
2159 | "optional features (%x).\n", | 2183 | "optional features (%x).\n", |
2160 | sb->s_id, le32_to_cpu(ret)); | 2184 | sb->s_id, le32_to_cpu(ret)); |
2161 | return -EROFS; | 2185 | err = -EROFS; |
2186 | goto restore_opts; | ||
2162 | } | 2187 | } |
2163 | /* | 2188 | /* |
2164 | * Mounting a RDONLY partition read-write, so reread | 2189 | * Mounting a RDONLY partition read-write, so reread |
@@ -2168,13 +2193,38 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data) | |||
2168 | */ | 2193 | */ |
2169 | ext3_clear_journal_err(sb, es); | 2194 | ext3_clear_journal_err(sb, es); |
2170 | sbi->s_mount_state = le16_to_cpu(es->s_state); | 2195 | sbi->s_mount_state = le16_to_cpu(es->s_state); |
2171 | if ((ret = ext3_group_extend(sb, es, n_blocks_count))) | 2196 | if ((ret = ext3_group_extend(sb, es, n_blocks_count))) { |
2172 | return ret; | 2197 | err = ret; |
2198 | goto restore_opts; | ||
2199 | } | ||
2173 | if (!ext3_setup_super (sb, es, 0)) | 2200 | if (!ext3_setup_super (sb, es, 0)) |
2174 | sb->s_flags &= ~MS_RDONLY; | 2201 | sb->s_flags &= ~MS_RDONLY; |
2175 | } | 2202 | } |
2176 | } | 2203 | } |
2204 | #ifdef CONFIG_QUOTA | ||
2205 | /* Release old quota file names */ | ||
2206 | for (i = 0; i < MAXQUOTAS; i++) | ||
2207 | if (old_opts.s_qf_names[i] && | ||
2208 | old_opts.s_qf_names[i] != sbi->s_qf_names[i]) | ||
2209 | kfree(old_opts.s_qf_names[i]); | ||
2210 | #endif | ||
2177 | return 0; | 2211 | return 0; |
2212 | restore_opts: | ||
2213 | sb->s_flags = old_sb_flags; | ||
2214 | sbi->s_mount_opt = old_opts.s_mount_opt; | ||
2215 | sbi->s_resuid = old_opts.s_resuid; | ||
2216 | sbi->s_resgid = old_opts.s_resgid; | ||
2217 | sbi->s_commit_interval = old_opts.s_commit_interval; | ||
2218 | #ifdef CONFIG_QUOTA | ||
2219 | sbi->s_jquota_fmt = old_opts.s_jquota_fmt; | ||
2220 | for (i = 0; i < MAXQUOTAS; i++) { | ||
2221 | if (sbi->s_qf_names[i] && | ||
2222 | old_opts.s_qf_names[i] != sbi->s_qf_names[i]) | ||
2223 | kfree(sbi->s_qf_names[i]); | ||
2224 | sbi->s_qf_names[i] = old_opts.s_qf_names[i]; | ||
2225 | } | ||
2226 | #endif | ||
2227 | return err; | ||
2178 | } | 2228 | } |
2179 | 2229 | ||
2180 | static int ext3_statfs (struct super_block * sb, struct kstatfs * buf) | 2230 | static int ext3_statfs (struct super_block * sb, struct kstatfs * buf) |