aboutsummaryrefslogtreecommitdiffstats
path: root/fs/reiserfs/super.c
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2008-07-25 04:46:38 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-25 13:53:33 -0400
commit00b441970a0ab48185244300ac7d4e4eb76df692 (patch)
tree5e0e7b72b0388dd889da267e669dd1e427e82946 /fs/reiserfs/super.c
parent4506567b24d3ea707e46e8aad64caef539382f4b (diff)
reiserfs: 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 (some mount versions do this on remount). Finally, we should not discard current quota options if parsing of mount options fails. Cc: <reiserfs-devel@vger.kernel.org> Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/reiserfs/super.c')
-rw-r--r--fs/reiserfs/super.c83
1 files changed, 60 insertions, 23 deletions
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index f723604c5d9b..a10a6d2a8870 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -876,7 +876,9 @@ static int reiserfs_parse_options(struct super_block *s, char *options, /* strin
876 mount options were selected. */ 876 mount options were selected. */
877 unsigned long *blocks, /* strtol-ed from NNN of resize=NNN */ 877 unsigned long *blocks, /* strtol-ed from NNN of resize=NNN */
878 char **jdev_name, 878 char **jdev_name,
879 unsigned int *commit_max_age) 879 unsigned int *commit_max_age,
880 char **qf_names,
881 unsigned int *qfmt)
880{ 882{
881 int c; 883 int c;
882 char *arg = NULL; 884 char *arg = NULL;
@@ -992,7 +994,9 @@ static int reiserfs_parse_options(struct super_block *s, char *options, /* strin
992 if (c == 'u' || c == 'g') { 994 if (c == 'u' || c == 'g') {
993 int qtype = c == 'u' ? USRQUOTA : GRPQUOTA; 995 int qtype = c == 'u' ? USRQUOTA : GRPQUOTA;
994 996
995 if (sb_any_quota_enabled(s)) { 997 if ((sb_any_quota_enabled(s) ||
998 sb_any_quota_suspended(s)) &&
999 (!*arg != !REISERFS_SB(s)->s_qf_names[qtype])) {
996 reiserfs_warning(s, 1000 reiserfs_warning(s,
997 "reiserfs_parse_options: cannot change journaled quota options when quota turned on."); 1001 "reiserfs_parse_options: cannot change journaled quota options when quota turned on.");
998 return 0; 1002 return 0;
@@ -1011,30 +1015,39 @@ static int reiserfs_parse_options(struct super_block *s, char *options, /* strin
1011 "reiserfs_parse_options: quotafile must be on filesystem root."); 1015 "reiserfs_parse_options: quotafile must be on filesystem root.");
1012 return 0; 1016 return 0;
1013 } 1017 }
1014 REISERFS_SB(s)->s_qf_names[qtype] = 1018 qf_names[qtype] =
1015 kmalloc(strlen(arg) + 1, GFP_KERNEL); 1019 kmalloc(strlen(arg) + 1, GFP_KERNEL);
1016 if (!REISERFS_SB(s)->s_qf_names[qtype]) { 1020 if (!qf_names[qtype]) {
1017 reiserfs_warning(s, 1021 reiserfs_warning(s,
1018 "reiserfs_parse_options: not enough memory for storing quotafile name."); 1022 "reiserfs_parse_options: not enough memory for storing quotafile name.");
1019 return 0; 1023 return 0;
1020 } 1024 }
1021 strcpy(REISERFS_SB(s)->s_qf_names[qtype], arg); 1025 strcpy(qf_names[qtype], arg);
1022 *mount_options |= 1 << REISERFS_QUOTA; 1026 *mount_options |= 1 << REISERFS_QUOTA;
1023 } else { 1027 } else {
1024 kfree(REISERFS_SB(s)->s_qf_names[qtype]); 1028 if (qf_names[qtype] !=
1025 REISERFS_SB(s)->s_qf_names[qtype] = NULL; 1029 REISERFS_SB(s)->s_qf_names[qtype])
1030 kfree(qf_names[qtype]);
1031 qf_names[qtype] = NULL;
1026 } 1032 }
1027 } 1033 }
1028 if (c == 'f') { 1034 if (c == 'f') {
1029 if (!strcmp(arg, "vfsold")) 1035 if (!strcmp(arg, "vfsold"))
1030 REISERFS_SB(s)->s_jquota_fmt = QFMT_VFS_OLD; 1036 *qfmt = QFMT_VFS_OLD;
1031 else if (!strcmp(arg, "vfsv0")) 1037 else if (!strcmp(arg, "vfsv0"))
1032 REISERFS_SB(s)->s_jquota_fmt = QFMT_VFS_V0; 1038 *qfmt = QFMT_VFS_V0;
1033 else { 1039 else {
1034 reiserfs_warning(s, 1040 reiserfs_warning(s,
1035 "reiserfs_parse_options: unknown quota format specified."); 1041 "reiserfs_parse_options: unknown quota format specified.");
1036 return 0; 1042 return 0;
1037 } 1043 }
1044 if ((sb_any_quota_enabled(s) ||
1045 sb_any_quota_suspended(s)) &&
1046 *qfmt != REISERFS_SB(s)->s_jquota_fmt) {
1047 reiserfs_warning(s,
1048 "reiserfs_parse_options: cannot change journaled quota options when quota turned on.");
1049 return 0;
1050 }
1038 } 1051 }
1039#else 1052#else
1040 if (c == 'u' || c == 'g' || c == 'f') { 1053 if (c == 'u' || c == 'g' || c == 'f') {
@@ -1046,9 +1059,8 @@ static int reiserfs_parse_options(struct super_block *s, char *options, /* strin
1046 } 1059 }
1047 1060
1048#ifdef CONFIG_QUOTA 1061#ifdef CONFIG_QUOTA
1049 if (!REISERFS_SB(s)->s_jquota_fmt 1062 if (!REISERFS_SB(s)->s_jquota_fmt && !*qfmt
1050 && (REISERFS_SB(s)->s_qf_names[USRQUOTA] 1063 && (qf_names[USRQUOTA] || qf_names[GRPQUOTA])) {
1051 || REISERFS_SB(s)->s_qf_names[GRPQUOTA])) {
1052 reiserfs_warning(s, 1064 reiserfs_warning(s,
1053 "reiserfs_parse_options: journaled quota format not specified."); 1065 "reiserfs_parse_options: journaled quota format not specified.");
1054 return 0; 1066 return 0;
@@ -1130,6 +1142,21 @@ static void handle_attrs(struct super_block *s)
1130 } 1142 }
1131} 1143}
1132 1144
1145#ifdef CONFIG_QUOTA
1146static void handle_quota_files(struct super_block *s, char **qf_names,
1147 unsigned int *qfmt)
1148{
1149 int i;
1150
1151 for (i = 0; i < MAXQUOTAS; i++) {
1152 if (qf_names[i] != REISERFS_SB(s)->s_qf_names[i])
1153 kfree(REISERFS_SB(s)->s_qf_names[i]);
1154 REISERFS_SB(s)->s_qf_names[i] = qf_names[i];
1155 }
1156 REISERFS_SB(s)->s_jquota_fmt = *qfmt;
1157}
1158#endif
1159
1133static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) 1160static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
1134{ 1161{
1135 struct reiserfs_super_block *rs; 1162 struct reiserfs_super_block *rs;
@@ -1141,23 +1168,30 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
1141 struct reiserfs_journal *journal = SB_JOURNAL(s); 1168 struct reiserfs_journal *journal = SB_JOURNAL(s);
1142 char *new_opts = kstrdup(arg, GFP_KERNEL); 1169 char *new_opts = kstrdup(arg, GFP_KERNEL);
1143 int err; 1170 int err;
1171 char *qf_names[MAXQUOTAS];
1172 unsigned int qfmt = 0;
1144#ifdef CONFIG_QUOTA 1173#ifdef CONFIG_QUOTA
1145 int i; 1174 int i;
1175
1176 memcpy(qf_names, REISERFS_SB(s)->s_qf_names, sizeof(qf_names));
1146#endif 1177#endif
1147 1178
1148 rs = SB_DISK_SUPER_BLOCK(s); 1179 rs = SB_DISK_SUPER_BLOCK(s);
1149 1180
1150 if (!reiserfs_parse_options 1181 if (!reiserfs_parse_options
1151 (s, arg, &mount_options, &blocks, NULL, &commit_max_age)) { 1182 (s, arg, &mount_options, &blocks, NULL, &commit_max_age,
1183 qf_names, &qfmt)) {
1152#ifdef CONFIG_QUOTA 1184#ifdef CONFIG_QUOTA
1153 for (i = 0; i < MAXQUOTAS; i++) { 1185 for (i = 0; i < MAXQUOTAS; i++)
1154 kfree(REISERFS_SB(s)->s_qf_names[i]); 1186 if (qf_names[i] != REISERFS_SB(s)->s_qf_names[i])
1155 REISERFS_SB(s)->s_qf_names[i] = NULL; 1187 kfree(qf_names[i]);
1156 }
1157#endif 1188#endif
1158 err = -EINVAL; 1189 err = -EINVAL;
1159 goto out_err; 1190 goto out_err;
1160 } 1191 }
1192#ifdef CONFIG_QUOTA
1193 handle_quota_files(s, qf_names, &qfmt);
1194#endif
1161 1195
1162 handle_attrs(s); 1196 handle_attrs(s);
1163 1197
@@ -1570,6 +1604,8 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
1570 char *jdev_name; 1604 char *jdev_name;
1571 struct reiserfs_sb_info *sbi; 1605 struct reiserfs_sb_info *sbi;
1572 int errval = -EINVAL; 1606 int errval = -EINVAL;
1607 char *qf_names[MAXQUOTAS] = {};
1608 unsigned int qfmt = 0;
1573 1609
1574 save_mount_options(s, data); 1610 save_mount_options(s, data);
1575 1611
@@ -1597,9 +1633,12 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
1597 jdev_name = NULL; 1633 jdev_name = NULL;
1598 if (reiserfs_parse_options 1634 if (reiserfs_parse_options
1599 (s, (char *)data, &(sbi->s_mount_opt), &blocks, &jdev_name, 1635 (s, (char *)data, &(sbi->s_mount_opt), &blocks, &jdev_name,
1600 &commit_max_age) == 0) { 1636 &commit_max_age, qf_names, &qfmt) == 0) {
1601 goto error; 1637 goto error;
1602 } 1638 }
1639#ifdef CONFIG_QUOTA
1640 handle_quota_files(s, qf_names, &qfmt);
1641#endif
1603 1642
1604 if (blocks) { 1643 if (blocks) {
1605 SWARN(silent, s, "jmacd-7: reiserfs_fill_super: resize option " 1644 SWARN(silent, s, "jmacd-7: reiserfs_fill_super: resize option "
@@ -1819,7 +1858,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
1819 1858
1820 return (0); 1859 return (0);
1821 1860
1822 error: 1861error:
1823 if (jinit_done) { /* kill the commit thread, free journal ram */ 1862 if (jinit_done) { /* kill the commit thread, free journal ram */
1824 journal_release_error(NULL, s); 1863 journal_release_error(NULL, s);
1825 } 1864 }
@@ -1830,10 +1869,8 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
1830#ifdef CONFIG_QUOTA 1869#ifdef CONFIG_QUOTA
1831 { 1870 {
1832 int j; 1871 int j;
1833 for (j = 0; j < MAXQUOTAS; j++) { 1872 for (j = 0; j < MAXQUOTAS; j++)
1834 kfree(sbi->s_qf_names[j]); 1873 kfree(qf_names[j]);
1835 sbi->s_qf_names[j] = NULL;
1836 }
1837 } 1874 }
1838#endif 1875#endif
1839 kfree(sbi); 1876 kfree(sbi);