ext4: correct mount option parsing to detect when quota options can be changed

We should not allow user to change quota mount options when quota is
just suspended. It would make mount options and internal quota state
inconsistent. Also we should not allow user to change quota format when
quota is turned on. On the other hand we can just silently ignore when
some option is set to the value it already has (mount does this on
remount).

Cc: <linux-ext4@vger.kernel.org>
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Mingming Cao <cmm@us.ibm.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>

authored by Jan Kara and committed by Theodore Ts'o dfc5d03f 8f40f672

+20 -6
+20 -6
fs/ext4/super.c
··· 979 int data_opt = 0; 980 int option; 981 #ifdef CONFIG_QUOTA 982 - int qtype; 983 char *qname; 984 #endif 985 ··· 1162 case Opt_grpjquota: 1163 qtype = GRPQUOTA; 1164 set_qf_name: 1165 - if (sb_any_quota_enabled(sb)) { 1166 printk(KERN_ERR 1167 "EXT4-fs: Cannot change journalled " 1168 "quota options when quota turned on.\n"); ··· 1202 case Opt_offgrpjquota: 1203 qtype = GRPQUOTA; 1204 clear_qf_name: 1205 - if (sb_any_quota_enabled(sb)) { 1206 printk(KERN_ERR "EXT4-fs: Cannot change " 1207 "journalled quota options when " 1208 "quota turned on.\n"); ··· 1217 sbi->s_qf_names[qtype] = NULL; 1218 break; 1219 case Opt_jqfmt_vfsold: 1220 - sbi->s_jquota_fmt = QFMT_VFS_OLD; 1221 - break; 1222 case Opt_jqfmt_vfsv0: 1223 - sbi->s_jquota_fmt = QFMT_VFS_V0; 1224 break; 1225 case Opt_quota: 1226 case Opt_usrquota:
··· 979 int data_opt = 0; 980 int option; 981 #ifdef CONFIG_QUOTA 982 + int qtype, qfmt; 983 char *qname; 984 #endif 985 ··· 1162 case Opt_grpjquota: 1163 qtype = GRPQUOTA; 1164 set_qf_name: 1165 + if ((sb_any_quota_enabled(sb) || 1166 + sb_any_quota_suspended(sb)) && 1167 + !sbi->s_qf_names[qtype]) { 1168 printk(KERN_ERR 1169 "EXT4-fs: Cannot change journalled " 1170 "quota options when quota turned on.\n"); ··· 1200 case Opt_offgrpjquota: 1201 qtype = GRPQUOTA; 1202 clear_qf_name: 1203 + if ((sb_any_quota_enabled(sb) || 1204 + sb_any_quota_suspended(sb)) && 1205 + sbi->s_qf_names[qtype]) { 1206 printk(KERN_ERR "EXT4-fs: Cannot change " 1207 "journalled quota options when " 1208 "quota turned on.\n"); ··· 1213 sbi->s_qf_names[qtype] = NULL; 1214 break; 1215 case Opt_jqfmt_vfsold: 1216 + qfmt = QFMT_VFS_OLD; 1217 + goto set_qf_format; 1218 case Opt_jqfmt_vfsv0: 1219 + qfmt = QFMT_VFS_V0; 1220 + set_qf_format: 1221 + if ((sb_any_quota_enabled(sb) || 1222 + sb_any_quota_suspended(sb)) && 1223 + sbi->s_jquota_fmt != qfmt) { 1224 + printk(KERN_ERR "EXT4-fs: Cannot change " 1225 + "journaled quota options when " 1226 + "quota turned on.\n"); 1227 + return 0; 1228 + } 1229 + sbi->s_jquota_fmt = qfmt; 1230 break; 1231 case Opt_quota: 1232 case Opt_usrquota: