aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext3/super.c
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2005-07-12 16:58:28 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-07-12 19:01:01 -0400
commit08c6a96fd77836856c090ebb39beadc81cb8484d (patch)
tree36e643a41179078abcb8a866894586cba9bbf7e0 /fs/ext3/super.c
parent5323125031799a7fd8602ce150c3902aedfdcba6 (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.c70
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;
2212restore_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
2180static int ext3_statfs (struct super_block * sb, struct kstatfs * buf) 2230static int ext3_statfs (struct super_block * sb, struct kstatfs * buf)