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