[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>
This commit is contained in:
parent
5323125031
commit
08c6a96fd7
|
@ -890,7 +890,10 @@ clear_qf_name:
|
||||||
"quota turned on.\n");
|
"quota turned on.\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
kfree(sbi->s_qf_names[qtype]);
|
/*
|
||||||
|
* The space will be released later when all options
|
||||||
|
* are confirmed to be correct
|
||||||
|
*/
|
||||||
sbi->s_qf_names[qtype] = NULL;
|
sbi->s_qf_names[qtype] = NULL;
|
||||||
break;
|
break;
|
||||||
case Opt_jqfmt_vfsold:
|
case Opt_jqfmt_vfsold:
|
||||||
|
@ -939,7 +942,7 @@ clear_qf_name:
|
||||||
case Opt_ignore:
|
case Opt_ignore:
|
||||||
break;
|
break;
|
||||||
case Opt_resize:
|
case Opt_resize:
|
||||||
if (!n_blocks_count) {
|
if (!is_remount) {
|
||||||
printk("EXT3-fs: resize option only available "
|
printk("EXT3-fs: resize option only available "
|
||||||
"for remount\n");
|
"for remount\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2109,14 +2112,33 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data)
|
||||||
{
|
{
|
||||||
struct ext3_super_block * es;
|
struct ext3_super_block * es;
|
||||||
struct ext3_sb_info *sbi = EXT3_SB(sb);
|
struct ext3_sb_info *sbi = EXT3_SB(sb);
|
||||||
unsigned long tmp;
|
|
||||||
unsigned long n_blocks_count = 0;
|
unsigned long n_blocks_count = 0;
|
||||||
|
unsigned long old_sb_flags;
|
||||||
|
struct ext3_mount_options old_opts;
|
||||||
|
int err;
|
||||||
|
#ifdef CONFIG_QUOTA
|
||||||
|
int i;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Store the original options */
|
||||||
|
old_sb_flags = sb->s_flags;
|
||||||
|
old_opts.s_mount_opt = sbi->s_mount_opt;
|
||||||
|
old_opts.s_resuid = sbi->s_resuid;
|
||||||
|
old_opts.s_resgid = sbi->s_resgid;
|
||||||
|
old_opts.s_commit_interval = sbi->s_commit_interval;
|
||||||
|
#ifdef CONFIG_QUOTA
|
||||||
|
old_opts.s_jquota_fmt = sbi->s_jquota_fmt;
|
||||||
|
for (i = 0; i < MAXQUOTAS; i++)
|
||||||
|
old_opts.s_qf_names[i] = sbi->s_qf_names[i];
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allow the "check" option to be passed as a remount option.
|
* Allow the "check" option to be passed as a remount option.
|
||||||
*/
|
*/
|
||||||
if (!parse_options(data, sb, &tmp, &n_blocks_count, 1))
|
if (!parse_options(data, sb, NULL, &n_blocks_count, 1)) {
|
||||||
return -EINVAL;
|
err = -EINVAL;
|
||||||
|
goto restore_opts;
|
||||||
|
}
|
||||||
|
|
||||||
if (sbi->s_mount_opt & EXT3_MOUNT_ABORT)
|
if (sbi->s_mount_opt & EXT3_MOUNT_ABORT)
|
||||||
ext3_abort(sb, __FUNCTION__, "Abort forced by user");
|
ext3_abort(sb, __FUNCTION__, "Abort forced by user");
|
||||||
|
@ -2130,8 +2152,10 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data)
|
||||||
|
|
||||||
if ((*flags & MS_RDONLY) != (sb->s_flags & MS_RDONLY) ||
|
if ((*flags & MS_RDONLY) != (sb->s_flags & MS_RDONLY) ||
|
||||||
n_blocks_count > le32_to_cpu(es->s_blocks_count)) {
|
n_blocks_count > le32_to_cpu(es->s_blocks_count)) {
|
||||||
if (sbi->s_mount_opt & EXT3_MOUNT_ABORT)
|
if (sbi->s_mount_opt & EXT3_MOUNT_ABORT) {
|
||||||
return -EROFS;
|
err = -EROFS;
|
||||||
|
goto restore_opts;
|
||||||
|
}
|
||||||
|
|
||||||
if (*flags & MS_RDONLY) {
|
if (*flags & MS_RDONLY) {
|
||||||
/*
|
/*
|
||||||
|
@ -2158,7 +2182,8 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data)
|
||||||
"remount RDWR because of unsupported "
|
"remount RDWR because of unsupported "
|
||||||
"optional features (%x).\n",
|
"optional features (%x).\n",
|
||||||
sb->s_id, le32_to_cpu(ret));
|
sb->s_id, le32_to_cpu(ret));
|
||||||
return -EROFS;
|
err = -EROFS;
|
||||||
|
goto restore_opts;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Mounting a RDONLY partition read-write, so reread
|
* Mounting a RDONLY partition read-write, so reread
|
||||||
|
@ -2168,13 +2193,38 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data)
|
||||||
*/
|
*/
|
||||||
ext3_clear_journal_err(sb, es);
|
ext3_clear_journal_err(sb, es);
|
||||||
sbi->s_mount_state = le16_to_cpu(es->s_state);
|
sbi->s_mount_state = le16_to_cpu(es->s_state);
|
||||||
if ((ret = ext3_group_extend(sb, es, n_blocks_count)))
|
if ((ret = ext3_group_extend(sb, es, n_blocks_count))) {
|
||||||
return ret;
|
err = ret;
|
||||||
|
goto restore_opts;
|
||||||
|
}
|
||||||
if (!ext3_setup_super (sb, es, 0))
|
if (!ext3_setup_super (sb, es, 0))
|
||||||
sb->s_flags &= ~MS_RDONLY;
|
sb->s_flags &= ~MS_RDONLY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef CONFIG_QUOTA
|
||||||
|
/* Release old quota file names */
|
||||||
|
for (i = 0; i < MAXQUOTAS; i++)
|
||||||
|
if (old_opts.s_qf_names[i] &&
|
||||||
|
old_opts.s_qf_names[i] != sbi->s_qf_names[i])
|
||||||
|
kfree(old_opts.s_qf_names[i]);
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
|
restore_opts:
|
||||||
|
sb->s_flags = old_sb_flags;
|
||||||
|
sbi->s_mount_opt = old_opts.s_mount_opt;
|
||||||
|
sbi->s_resuid = old_opts.s_resuid;
|
||||||
|
sbi->s_resgid = old_opts.s_resgid;
|
||||||
|
sbi->s_commit_interval = old_opts.s_commit_interval;
|
||||||
|
#ifdef CONFIG_QUOTA
|
||||||
|
sbi->s_jquota_fmt = old_opts.s_jquota_fmt;
|
||||||
|
for (i = 0; i < MAXQUOTAS; i++) {
|
||||||
|
if (sbi->s_qf_names[i] &&
|
||||||
|
old_opts.s_qf_names[i] != sbi->s_qf_names[i])
|
||||||
|
kfree(sbi->s_qf_names[i]);
|
||||||
|
sbi->s_qf_names[i] = old_opts.s_qf_names[i];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ext3_statfs (struct super_block * sb, struct kstatfs * buf)
|
static int ext3_statfs (struct super_block * sb, struct kstatfs * buf)
|
||||||
|
|
|
@ -238,6 +238,20 @@ struct ext3_new_group_data {
|
||||||
#define EXT3_IOC_GETRSVSZ _IOR('f', 5, long)
|
#define EXT3_IOC_GETRSVSZ _IOR('f', 5, long)
|
||||||
#define EXT3_IOC_SETRSVSZ _IOW('f', 6, long)
|
#define EXT3_IOC_SETRSVSZ _IOW('f', 6, long)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mount options
|
||||||
|
*/
|
||||||
|
struct ext3_mount_options {
|
||||||
|
unsigned long s_mount_opt;
|
||||||
|
uid_t s_resuid;
|
||||||
|
gid_t s_resgid;
|
||||||
|
unsigned long s_commit_interval;
|
||||||
|
#ifdef CONFIG_QUOTA
|
||||||
|
int s_jquota_fmt;
|
||||||
|
char *s_qf_names[MAXQUOTAS];
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Structure of an inode on the disk
|
* Structure of an inode on the disk
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue