Skip to content

Commit e6e268c

Browse files
Lukas Czernertytso
authored andcommitted
ext4: move quota configuration out of handle_mount_opt()
At the parsing phase of mount in the new mount api sb will not be available so move quota confiquration out of handle_mount_opt() by noting the quota file names in the ext4_fs_context structure to be able to apply it later. Signed-off-by: Lukas Czerner <[email protected]> Reviewed-by: Carlos Maiolino <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Theodore Ts'o <[email protected]>
1 parent da812f6 commit e6e268c

File tree

1 file changed

+165
-93
lines changed

1 file changed

+165
-93
lines changed

fs/ext4/super.c

Lines changed: 165 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,10 @@ static void ext4_clear_request_list(void);
8989
static struct inode *ext4_get_journal_inode(struct super_block *sb,
9090
unsigned int journal_inum);
9191
static int ext4_validate_options(struct fs_context *fc);
92+
static int ext4_check_quota_consistency(struct fs_context *fc,
93+
struct super_block *sb);
94+
static void ext4_apply_quota_options(struct fs_context *fc,
95+
struct super_block *sb);
9296

9397
/*
9498
* Lock ordering
@@ -1986,71 +1990,6 @@ static const char deprecated_msg[] =
19861990
"Mount option \"%s\" will be removed by %s\n"
19871991
"Contact [email protected] if you think we should keep it.\n";
19881992

1989-
#ifdef CONFIG_QUOTA
1990-
static int set_qf_name(struct super_block *sb, int qtype,
1991-
struct fs_parameter *param)
1992-
{
1993-
struct ext4_sb_info *sbi = EXT4_SB(sb);
1994-
char *qname, *old_qname = get_qf_name(sb, sbi, qtype);
1995-
int ret = -1;
1996-
1997-
if (sb_any_quota_loaded(sb) && !old_qname) {
1998-
ext4_msg(sb, KERN_ERR,
1999-
"Cannot change journaled "
2000-
"quota options when quota turned on");
2001-
return -1;
2002-
}
2003-
if (ext4_has_feature_quota(sb)) {
2004-
ext4_msg(sb, KERN_INFO, "Journaled quota options "
2005-
"ignored when QUOTA feature is enabled");
2006-
return 1;
2007-
}
2008-
qname = kmemdup_nul(param->string, param->size, GFP_KERNEL);
2009-
if (!qname) {
2010-
ext4_msg(sb, KERN_ERR,
2011-
"Not enough memory for storing quotafile name");
2012-
return -1;
2013-
}
2014-
if (old_qname) {
2015-
if (strcmp(old_qname, qname) == 0)
2016-
ret = 1;
2017-
else
2018-
ext4_msg(sb, KERN_ERR,
2019-
"%s quota file already specified",
2020-
QTYPE2NAME(qtype));
2021-
goto errout;
2022-
}
2023-
if (strchr(qname, '/')) {
2024-
ext4_msg(sb, KERN_ERR,
2025-
"quotafile must be on filesystem root");
2026-
goto errout;
2027-
}
2028-
rcu_assign_pointer(sbi->s_qf_names[qtype], qname);
2029-
set_opt(sb, QUOTA);
2030-
return 1;
2031-
errout:
2032-
kfree(qname);
2033-
return ret;
2034-
}
2035-
2036-
static int clear_qf_name(struct super_block *sb, int qtype)
2037-
{
2038-
2039-
struct ext4_sb_info *sbi = EXT4_SB(sb);
2040-
char *old_qname = get_qf_name(sb, sbi, qtype);
2041-
2042-
if (sb_any_quota_loaded(sb) && old_qname) {
2043-
ext4_msg(sb, KERN_ERR, "Cannot change journaled quota options"
2044-
" when quota turned on");
2045-
return -1;
2046-
}
2047-
rcu_assign_pointer(sbi->s_qf_names[qtype], NULL);
2048-
synchronize_rcu();
2049-
kfree(old_qname);
2050-
return 1;
2051-
}
2052-
#endif
2053-
20541993
#define MOPT_SET 0x0001
20551994
#define MOPT_CLEAR 0x0002
20561995
#define MOPT_NOSUPPORT 0x0004
@@ -2254,11 +2193,70 @@ static int ext4_set_test_dummy_encryption(struct super_block *sb,
22542193
}
22552194

22562195
struct ext4_fs_context {
2257-
unsigned long journal_devnum;
2258-
unsigned int journal_ioprio;
2259-
int mb_optimize_scan;
2196+
char *s_qf_names[EXT4_MAXQUOTAS];
2197+
int s_jquota_fmt; /* Format of quota to use */
2198+
unsigned short qname_spec;
2199+
unsigned long journal_devnum;
2200+
unsigned int journal_ioprio;
2201+
int mb_optimize_scan;
22602202
};
22612203

2204+
#ifdef CONFIG_QUOTA
2205+
/*
2206+
* Note the name of the specified quota file.
2207+
*/
2208+
static int note_qf_name(struct fs_context *fc, int qtype,
2209+
struct fs_parameter *param)
2210+
{
2211+
struct ext4_fs_context *ctx = fc->fs_private;
2212+
char *qname;
2213+
2214+
if (param->size < 1) {
2215+
ext4_msg(NULL, KERN_ERR, "Missing quota name");
2216+
return -EINVAL;
2217+
}
2218+
if (strchr(param->string, '/')) {
2219+
ext4_msg(NULL, KERN_ERR,
2220+
"quotafile must be on filesystem root");
2221+
return -EINVAL;
2222+
}
2223+
if (ctx->s_qf_names[qtype]) {
2224+
if (strcmp(ctx->s_qf_names[qtype], param->string) != 0) {
2225+
ext4_msg(NULL, KERN_ERR,
2226+
"%s quota file already specified",
2227+
QTYPE2NAME(qtype));
2228+
return -EINVAL;
2229+
}
2230+
return 0;
2231+
}
2232+
2233+
qname = kmemdup_nul(param->string, param->size, GFP_KERNEL);
2234+
if (!qname) {
2235+
ext4_msg(NULL, KERN_ERR,
2236+
"Not enough memory for storing quotafile name");
2237+
return -ENOMEM;
2238+
}
2239+
ctx->s_qf_names[qtype] = qname;
2240+
ctx->qname_spec |= 1 << qtype;
2241+
return 0;
2242+
}
2243+
2244+
/*
2245+
* Clear the name of the specified quota file.
2246+
*/
2247+
static int unnote_qf_name(struct fs_context *fc, int qtype)
2248+
{
2249+
struct ext4_fs_context *ctx = fc->fs_private;
2250+
2251+
if (ctx->s_qf_names[qtype])
2252+
kfree(ctx->s_qf_names[qtype]);
2253+
2254+
ctx->s_qf_names[qtype] = NULL;
2255+
ctx->qname_spec |= 1 << qtype;
2256+
return 0;
2257+
}
2258+
#endif
2259+
22622260
static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param)
22632261
{
22642262
struct ext4_fs_context *ctx = fc->fs_private;
@@ -2279,14 +2277,14 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param)
22792277
#ifdef CONFIG_QUOTA
22802278
if (token == Opt_usrjquota) {
22812279
if (!*param->string)
2282-
return clear_qf_name(sb, USRQUOTA);
2280+
return unnote_qf_name(fc, USRQUOTA);
22832281
else
2284-
return set_qf_name(sb, USRQUOTA, param);
2282+
return note_qf_name(fc, USRQUOTA, param);
22852283
} else if (token == Opt_grpjquota) {
22862284
if (!*param->string)
2287-
return clear_qf_name(sb, GRPQUOTA);
2285+
return unnote_qf_name(fc, GRPQUOTA);
22882286
else
2289-
return set_qf_name(sb, GRPQUOTA, param);
2287+
return note_qf_name(fc, GRPQUOTA, param);
22902288
}
22912289
#endif
22922290
switch (token) {
@@ -2360,11 +2358,6 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param)
23602358
}
23612359
if (m->flags & MOPT_CLEAR_ERR)
23622360
clear_opt(sb, ERRORS_MASK);
2363-
if (token == Opt_noquota && sb_any_quota_loaded(sb)) {
2364-
ext4_msg(NULL, KERN_ERR, "Cannot change quota "
2365-
"options when quota turned on");
2366-
return -EINVAL;
2367-
}
23682361

23692362
if (m->flags & MOPT_NOSUPPORT) {
23702363
ext4_msg(NULL, KERN_ERR, "%s option not supported",
@@ -2486,19 +2479,7 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param)
24862479
}
24872480
#ifdef CONFIG_QUOTA
24882481
} else if (m->flags & MOPT_QFMT) {
2489-
if (sb_any_quota_loaded(sb) &&
2490-
sbi->s_jquota_fmt != m->mount_opt) {
2491-
ext4_msg(NULL, KERN_ERR, "Cannot change journaled "
2492-
"quota options when quota turned on");
2493-
return -EINVAL;
2494-
}
2495-
if (ext4_has_feature_quota(sb)) {
2496-
ext4_msg(NULL, KERN_INFO,
2497-
"Quota format mount options ignored "
2498-
"when QUOTA feature is enabled");
2499-
return 1;
2500-
}
2501-
sbi->s_jquota_fmt = m->mount_opt;
2482+
ctx->s_jquota_fmt = m->mount_opt;
25022483
#endif
25032484
} else if (token == Opt_dax || token == Opt_dax_always ||
25042485
token == Opt_dax_inode || token == Opt_dax_never) {
@@ -2595,7 +2576,7 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param)
25952576
}
25962577

25972578
static int parse_options(char *options, struct super_block *sb,
2598-
struct ext4_fs_context *ret_opts,
2579+
struct ext4_fs_context *ctx,
25992580
int is_remount)
26002581
{
26012582
struct fs_parameter param;
@@ -2607,7 +2588,7 @@ static int parse_options(char *options, struct super_block *sb,
26072588
return 1;
26082589

26092590
memset(&fc, 0, sizeof(fc));
2610-
fc.fs_private = ret_opts;
2591+
fc.fs_private = ctx;
26112592
fc.s_fs_info = EXT4_SB(sb);
26122593

26132594
if (is_remount)
@@ -2649,9 +2630,100 @@ static int parse_options(char *options, struct super_block *sb,
26492630
if (ret < 0)
26502631
return 0;
26512632

2633+
ret = ext4_check_quota_consistency(&fc, sb);
2634+
if (ret < 0)
2635+
return 0;
2636+
2637+
if (ctx->qname_spec)
2638+
ext4_apply_quota_options(&fc, sb);
2639+
26522640
return 1;
26532641
}
26542642

2643+
static void ext4_apply_quota_options(struct fs_context *fc,
2644+
struct super_block *sb)
2645+
{
2646+
#ifdef CONFIG_QUOTA
2647+
struct ext4_fs_context *ctx = fc->fs_private;
2648+
struct ext4_sb_info *sbi = EXT4_SB(sb);
2649+
char *qname;
2650+
int i;
2651+
2652+
for (i = 0; i < EXT4_MAXQUOTAS; i++) {
2653+
if (!(ctx->qname_spec & (1 << i)))
2654+
continue;
2655+
qname = ctx->s_qf_names[i]; /* May be NULL */
2656+
ctx->s_qf_names[i] = NULL;
2657+
kfree(sbi->s_qf_names[i]);
2658+
rcu_assign_pointer(sbi->s_qf_names[i], qname);
2659+
set_opt(sb, QUOTA);
2660+
}
2661+
#endif
2662+
}
2663+
2664+
/*
2665+
* Check quota settings consistency.
2666+
*/
2667+
static int ext4_check_quota_consistency(struct fs_context *fc,
2668+
struct super_block *sb)
2669+
{
2670+
#ifdef CONFIG_QUOTA
2671+
struct ext4_fs_context *ctx = fc->fs_private;
2672+
struct ext4_sb_info *sbi = EXT4_SB(sb);
2673+
bool quota_feature = ext4_has_feature_quota(sb);
2674+
bool quota_loaded = sb_any_quota_loaded(sb);
2675+
int i;
2676+
2677+
if (ctx->qname_spec && quota_loaded) {
2678+
if (quota_feature)
2679+
goto err_feature;
2680+
2681+
for (i = 0; i < EXT4_MAXQUOTAS; i++) {
2682+
if (!(ctx->qname_spec & (1 << i)))
2683+
continue;
2684+
2685+
if (!!sbi->s_qf_names[i] != !!ctx->s_qf_names[i])
2686+
goto err_jquota_change;
2687+
2688+
if (sbi->s_qf_names[i] && ctx->s_qf_names[i] &&
2689+
strcmp(sbi->s_qf_names[i],
2690+
ctx->s_qf_names[i]) != 0)
2691+
goto err_jquota_specified;
2692+
}
2693+
}
2694+
2695+
if (ctx->s_jquota_fmt) {
2696+
if (sbi->s_jquota_fmt != ctx->s_jquota_fmt && quota_loaded)
2697+
goto err_quota_change;
2698+
if (quota_feature) {
2699+
ext4_msg(NULL, KERN_INFO, "Quota format mount options "
2700+
"ignored when QUOTA feature is enabled");
2701+
return 0;
2702+
}
2703+
}
2704+
return 0;
2705+
2706+
err_quota_change:
2707+
ext4_msg(NULL, KERN_ERR,
2708+
"Cannot change quota options when quota turned on");
2709+
return -EINVAL;
2710+
err_jquota_change:
2711+
ext4_msg(NULL, KERN_ERR, "Cannot change journaled quota "
2712+
"options when quota turned on");
2713+
return -EINVAL;
2714+
err_jquota_specified:
2715+
ext4_msg(NULL, KERN_ERR, "%s quota file already specified",
2716+
QTYPE2NAME(i));
2717+
return -EINVAL;
2718+
err_feature:
2719+
ext4_msg(NULL, KERN_ERR, "Journaled quota options ignored "
2720+
"when QUOTA feature is enabled");
2721+
return 0;
2722+
#else
2723+
return 0;
2724+
#endif
2725+
}
2726+
26552727
static int ext4_validate_options(struct fs_context *fc)
26562728
{
26572729
struct ext4_sb_info *sbi = fc->s_fs_info;
@@ -4105,7 +4177,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
41054177
__u64 blocks_count;
41064178
int err = 0;
41074179
ext4_group_t first_not_zeroed;
4108-
struct ext4_fs_context parsed_opts;
4180+
struct ext4_fs_context parsed_opts = {0};
41094181

41104182
/* Set defaults for the variables that will be set during parsing */
41114183
parsed_opts.journal_ioprio = DEFAULT_JOURNAL_IOPRIO;

0 commit comments

Comments
 (0)