diff options
Diffstat (limited to 'fs/ext3/super.c')
-rw-r--r-- | fs/ext3/super.c | 110 |
1 files changed, 89 insertions, 21 deletions
diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 9630fbfdc24a..3c3c6e399fb3 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c | |||
@@ -589,7 +589,7 @@ enum { | |||
589 | Opt_commit, Opt_journal_update, Opt_journal_inum, | 589 | Opt_commit, Opt_journal_update, Opt_journal_inum, |
590 | Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, | 590 | Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, |
591 | Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, | 591 | Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, |
592 | Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, | 592 | Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota, |
593 | Opt_ignore, Opt_barrier, Opt_err, Opt_resize, | 593 | Opt_ignore, Opt_barrier, Opt_err, Opt_resize, |
594 | }; | 594 | }; |
595 | 595 | ||
@@ -634,10 +634,10 @@ static match_table_t tokens = { | |||
634 | {Opt_grpjquota, "grpjquota=%s"}, | 634 | {Opt_grpjquota, "grpjquota=%s"}, |
635 | {Opt_jqfmt_vfsold, "jqfmt=vfsold"}, | 635 | {Opt_jqfmt_vfsold, "jqfmt=vfsold"}, |
636 | {Opt_jqfmt_vfsv0, "jqfmt=vfsv0"}, | 636 | {Opt_jqfmt_vfsv0, "jqfmt=vfsv0"}, |
637 | {Opt_ignore, "grpquota"}, | 637 | {Opt_quota, "grpquota"}, |
638 | {Opt_ignore, "noquota"}, | 638 | {Opt_noquota, "noquota"}, |
639 | {Opt_ignore, "quota"}, | 639 | {Opt_quota, "quota"}, |
640 | {Opt_ignore, "usrquota"}, | 640 | {Opt_quota, "usrquota"}, |
641 | {Opt_barrier, "barrier=%u"}, | 641 | {Opt_barrier, "barrier=%u"}, |
642 | {Opt_err, NULL}, | 642 | {Opt_err, NULL}, |
643 | {Opt_resize, "resize"}, | 643 | {Opt_resize, "resize"}, |
@@ -876,6 +876,7 @@ set_qf_name: | |||
876 | sbi->s_qf_names[qtype] = NULL; | 876 | sbi->s_qf_names[qtype] = NULL; |
877 | return 0; | 877 | return 0; |
878 | } | 878 | } |
879 | set_opt(sbi->s_mount_opt, QUOTA); | ||
879 | break; | 880 | break; |
880 | case Opt_offusrjquota: | 881 | case Opt_offusrjquota: |
881 | qtype = USRQUOTA; | 882 | qtype = USRQUOTA; |
@@ -889,7 +890,10 @@ clear_qf_name: | |||
889 | "quota turned on.\n"); | 890 | "quota turned on.\n"); |
890 | return 0; | 891 | return 0; |
891 | } | 892 | } |
892 | kfree(sbi->s_qf_names[qtype]); | 893 | /* |
894 | * The space will be released later when all options | ||
895 | * are confirmed to be correct | ||
896 | */ | ||
893 | sbi->s_qf_names[qtype] = NULL; | 897 | sbi->s_qf_names[qtype] = NULL; |
894 | break; | 898 | break; |
895 | case Opt_jqfmt_vfsold: | 899 | case Opt_jqfmt_vfsold: |
@@ -898,6 +902,17 @@ clear_qf_name: | |||
898 | case Opt_jqfmt_vfsv0: | 902 | case Opt_jqfmt_vfsv0: |
899 | sbi->s_jquota_fmt = QFMT_VFS_V0; | 903 | sbi->s_jquota_fmt = QFMT_VFS_V0; |
900 | break; | 904 | break; |
905 | case Opt_quota: | ||
906 | set_opt(sbi->s_mount_opt, QUOTA); | ||
907 | break; | ||
908 | case Opt_noquota: | ||
909 | if (sb_any_quota_enabled(sb)) { | ||
910 | printk(KERN_ERR "EXT3-fs: Cannot change quota " | ||
911 | "options when quota turned on.\n"); | ||
912 | return 0; | ||
913 | } | ||
914 | clear_opt(sbi->s_mount_opt, QUOTA); | ||
915 | break; | ||
901 | #else | 916 | #else |
902 | case Opt_usrjquota: | 917 | case Opt_usrjquota: |
903 | case Opt_grpjquota: | 918 | case Opt_grpjquota: |
@@ -909,6 +924,9 @@ clear_qf_name: | |||
909 | "EXT3-fs: journalled quota options not " | 924 | "EXT3-fs: journalled quota options not " |
910 | "supported.\n"); | 925 | "supported.\n"); |
911 | break; | 926 | break; |
927 | case Opt_quota: | ||
928 | case Opt_noquota: | ||
929 | break; | ||
912 | #endif | 930 | #endif |
913 | case Opt_abort: | 931 | case Opt_abort: |
914 | set_opt(sbi->s_mount_opt, ABORT); | 932 | set_opt(sbi->s_mount_opt, ABORT); |
@@ -924,12 +942,13 @@ clear_qf_name: | |||
924 | case Opt_ignore: | 942 | case Opt_ignore: |
925 | break; | 943 | break; |
926 | case Opt_resize: | 944 | case Opt_resize: |
927 | if (!n_blocks_count) { | 945 | if (!is_remount) { |
928 | printk("EXT3-fs: resize option only available " | 946 | printk("EXT3-fs: resize option only available " |
929 | "for remount\n"); | 947 | "for remount\n"); |
930 | return 0; | 948 | return 0; |
931 | } | 949 | } |
932 | match_int(&args[0], &option); | 950 | if (match_int(&args[0], &option) != 0) |
951 | return 0; | ||
933 | *n_blocks_count = option; | 952 | *n_blocks_count = option; |
934 | break; | 953 | break; |
935 | case Opt_nobh: | 954 | case Opt_nobh: |
@@ -2093,14 +2112,33 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data) | |||
2093 | { | 2112 | { |
2094 | struct ext3_super_block * es; | 2113 | struct ext3_super_block * es; |
2095 | struct ext3_sb_info *sbi = EXT3_SB(sb); | 2114 | struct ext3_sb_info *sbi = EXT3_SB(sb); |
2096 | unsigned long tmp; | ||
2097 | 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 | ||
2098 | 2134 | ||
2099 | /* | 2135 | /* |
2100 | * Allow the "check" option to be passed as a remount option. | 2136 | * Allow the "check" option to be passed as a remount option. |
2101 | */ | 2137 | */ |
2102 | if (!parse_options(data, sb, &tmp, &n_blocks_count, 1)) | 2138 | if (!parse_options(data, sb, NULL, &n_blocks_count, 1)) { |
2103 | return -EINVAL; | 2139 | err = -EINVAL; |
2140 | goto restore_opts; | ||
2141 | } | ||
2104 | 2142 | ||
2105 | if (sbi->s_mount_opt & EXT3_MOUNT_ABORT) | 2143 | if (sbi->s_mount_opt & EXT3_MOUNT_ABORT) |
2106 | ext3_abort(sb, __FUNCTION__, "Abort forced by user"); | 2144 | ext3_abort(sb, __FUNCTION__, "Abort forced by user"); |
@@ -2114,8 +2152,10 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data) | |||
2114 | 2152 | ||
2115 | if ((*flags & MS_RDONLY) != (sb->s_flags & MS_RDONLY) || | 2153 | if ((*flags & MS_RDONLY) != (sb->s_flags & MS_RDONLY) || |
2116 | n_blocks_count > le32_to_cpu(es->s_blocks_count)) { | 2154 | n_blocks_count > le32_to_cpu(es->s_blocks_count)) { |
2117 | if (sbi->s_mount_opt & EXT3_MOUNT_ABORT) | 2155 | if (sbi->s_mount_opt & EXT3_MOUNT_ABORT) { |
2118 | return -EROFS; | 2156 | err = -EROFS; |
2157 | goto restore_opts; | ||
2158 | } | ||
2119 | 2159 | ||
2120 | if (*flags & MS_RDONLY) { | 2160 | if (*flags & MS_RDONLY) { |
2121 | /* | 2161 | /* |
@@ -2142,7 +2182,8 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data) | |||
2142 | "remount RDWR because of unsupported " | 2182 | "remount RDWR because of unsupported " |
2143 | "optional features (%x).\n", | 2183 | "optional features (%x).\n", |
2144 | sb->s_id, le32_to_cpu(ret)); | 2184 | sb->s_id, le32_to_cpu(ret)); |
2145 | return -EROFS; | 2185 | err = -EROFS; |
2186 | goto restore_opts; | ||
2146 | } | 2187 | } |
2147 | /* | 2188 | /* |
2148 | * Mounting a RDONLY partition read-write, so reread | 2189 | * Mounting a RDONLY partition read-write, so reread |
@@ -2152,13 +2193,38 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data) | |||
2152 | */ | 2193 | */ |
2153 | ext3_clear_journal_err(sb, es); | 2194 | ext3_clear_journal_err(sb, es); |
2154 | sbi->s_mount_state = le16_to_cpu(es->s_state); | 2195 | sbi->s_mount_state = le16_to_cpu(es->s_state); |
2155 | if ((ret = ext3_group_extend(sb, es, n_blocks_count))) | 2196 | if ((ret = ext3_group_extend(sb, es, n_blocks_count))) { |
2156 | return ret; | 2197 | err = ret; |
2198 | goto restore_opts; | ||
2199 | } | ||
2157 | if (!ext3_setup_super (sb, es, 0)) | 2200 | if (!ext3_setup_super (sb, es, 0)) |
2158 | sb->s_flags &= ~MS_RDONLY; | 2201 | sb->s_flags &= ~MS_RDONLY; |
2159 | } | 2202 | } |
2160 | } | 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 | ||
2161 | return 0; | 2211 | return 0; |
2212 | restore_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; | ||
2162 | } | 2228 | } |
2163 | 2229 | ||
2164 | static int ext3_statfs (struct super_block * sb, struct kstatfs * buf) | 2230 | static int ext3_statfs (struct super_block * sb, struct kstatfs * buf) |
@@ -2238,7 +2304,7 @@ static int ext3_dquot_initialize(struct inode *inode, int type) | |||
2238 | int ret, err; | 2304 | int ret, err; |
2239 | 2305 | ||
2240 | /* We may create quota structure so we need to reserve enough blocks */ | 2306 | /* We may create quota structure so we need to reserve enough blocks */ |
2241 | handle = ext3_journal_start(inode, 2*EXT3_QUOTA_INIT_BLOCKS); | 2307 | handle = ext3_journal_start(inode, 2*EXT3_QUOTA_INIT_BLOCKS(inode->i_sb)); |
2242 | if (IS_ERR(handle)) | 2308 | if (IS_ERR(handle)) |
2243 | return PTR_ERR(handle); | 2309 | return PTR_ERR(handle); |
2244 | ret = dquot_initialize(inode, type); | 2310 | ret = dquot_initialize(inode, type); |
@@ -2254,7 +2320,7 @@ static int ext3_dquot_drop(struct inode *inode) | |||
2254 | int ret, err; | 2320 | int ret, err; |
2255 | 2321 | ||
2256 | /* We may delete quota structure so we need to reserve enough blocks */ | 2322 | /* We may delete quota structure so we need to reserve enough blocks */ |
2257 | handle = ext3_journal_start(inode, 2*EXT3_QUOTA_INIT_BLOCKS); | 2323 | handle = ext3_journal_start(inode, 2*EXT3_QUOTA_DEL_BLOCKS(inode->i_sb)); |
2258 | if (IS_ERR(handle)) | 2324 | if (IS_ERR(handle)) |
2259 | return PTR_ERR(handle); | 2325 | return PTR_ERR(handle); |
2260 | ret = dquot_drop(inode); | 2326 | ret = dquot_drop(inode); |
@@ -2272,7 +2338,7 @@ static int ext3_write_dquot(struct dquot *dquot) | |||
2272 | 2338 | ||
2273 | inode = dquot_to_inode(dquot); | 2339 | inode = dquot_to_inode(dquot); |
2274 | handle = ext3_journal_start(inode, | 2340 | handle = ext3_journal_start(inode, |
2275 | EXT3_QUOTA_TRANS_BLOCKS); | 2341 | EXT3_QUOTA_TRANS_BLOCKS(dquot->dq_sb)); |
2276 | if (IS_ERR(handle)) | 2342 | if (IS_ERR(handle)) |
2277 | return PTR_ERR(handle); | 2343 | return PTR_ERR(handle); |
2278 | ret = dquot_commit(dquot); | 2344 | ret = dquot_commit(dquot); |
@@ -2288,7 +2354,7 @@ static int ext3_acquire_dquot(struct dquot *dquot) | |||
2288 | handle_t *handle; | 2354 | handle_t *handle; |
2289 | 2355 | ||
2290 | handle = ext3_journal_start(dquot_to_inode(dquot), | 2356 | handle = ext3_journal_start(dquot_to_inode(dquot), |
2291 | EXT3_QUOTA_INIT_BLOCKS); | 2357 | EXT3_QUOTA_INIT_BLOCKS(dquot->dq_sb)); |
2292 | if (IS_ERR(handle)) | 2358 | if (IS_ERR(handle)) |
2293 | return PTR_ERR(handle); | 2359 | return PTR_ERR(handle); |
2294 | ret = dquot_acquire(dquot); | 2360 | ret = dquot_acquire(dquot); |
@@ -2304,7 +2370,7 @@ static int ext3_release_dquot(struct dquot *dquot) | |||
2304 | handle_t *handle; | 2370 | handle_t *handle; |
2305 | 2371 | ||
2306 | handle = ext3_journal_start(dquot_to_inode(dquot), | 2372 | handle = ext3_journal_start(dquot_to_inode(dquot), |
2307 | EXT3_QUOTA_INIT_BLOCKS); | 2373 | EXT3_QUOTA_DEL_BLOCKS(dquot->dq_sb)); |
2308 | if (IS_ERR(handle)) | 2374 | if (IS_ERR(handle)) |
2309 | return PTR_ERR(handle); | 2375 | return PTR_ERR(handle); |
2310 | ret = dquot_release(dquot); | 2376 | ret = dquot_release(dquot); |
@@ -2361,6 +2427,8 @@ static int ext3_quota_on(struct super_block *sb, int type, int format_id, | |||
2361 | int err; | 2427 | int err; |
2362 | struct nameidata nd; | 2428 | struct nameidata nd; |
2363 | 2429 | ||
2430 | if (!test_opt(sb, QUOTA)) | ||
2431 | return -EINVAL; | ||
2364 | /* Not journalling quota? */ | 2432 | /* Not journalling quota? */ |
2365 | if (!EXT3_SB(sb)->s_qf_names[USRQUOTA] && | 2433 | if (!EXT3_SB(sb)->s_qf_names[USRQUOTA] && |
2366 | !EXT3_SB(sb)->s_qf_names[GRPQUOTA]) | 2434 | !EXT3_SB(sb)->s_qf_names[GRPQUOTA]) |