Skip to content

Commit

Permalink
ext4: Allow sb to be NULL in ext4_msg()
Browse files Browse the repository at this point in the history
At the parsing phase of mount in the new mount api sb will not be
available so allow sb to be NULL in ext4_msg and use that in
handle_mount_opt().

Also change return value to appropriate -EINVAL where needed.

Signed-off-by: Lukas Czerner <lczerner@redhat.com>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Link: https://lore.kernel.org/r/20211027141857.33657-6-lczerner@redhat.com
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
  • Loading branch information
Lukas Czerner authored and Theodore Ts'o committed Dec 9, 2021
1 parent 461c3af commit da812f6
Showing 1 changed file with 78 additions and 66 deletions.
144 changes: 78 additions & 66 deletions fs/ext4/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ static void ext4_unregister_li_request(struct super_block *sb);
static void ext4_clear_request_list(void);
static struct inode *ext4_get_journal_inode(struct super_block *sb,
unsigned int journal_inum);
static int ext4_validate_options(struct super_block *sb);
static int ext4_validate_options(struct fs_context *fc);

/*
* Lock ordering
Expand Down Expand Up @@ -915,14 +915,20 @@ void __ext4_msg(struct super_block *sb,
struct va_format vaf;
va_list args;

atomic_inc(&EXT4_SB(sb)->s_msg_count);
if (!___ratelimit(&(EXT4_SB(sb)->s_msg_ratelimit_state), "EXT4-fs"))
return;
if (sb) {
atomic_inc(&EXT4_SB(sb)->s_msg_count);
if (!___ratelimit(&(EXT4_SB(sb)->s_msg_ratelimit_state),
"EXT4-fs"))
return;
}

va_start(args, fmt);
vaf.fmt = fmt;
vaf.va = &args;
printk("%sEXT4-fs (%s): %pV\n", prefix, sb->s_id, &vaf);
if (sb)
printk("%sEXT4-fs (%s): %pV\n", prefix, sb->s_id, &vaf);
else
printk("%sEXT4-fs: %pV\n", prefix, &vaf);
va_end(args);
}

Expand Down Expand Up @@ -2286,12 +2292,12 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param)
switch (token) {
case Opt_noacl:
case Opt_nouser_xattr:
ext4_msg(sb, KERN_WARNING, deprecated_msg, param->key, "3.5");
ext4_msg(NULL, KERN_WARNING, deprecated_msg, param->key, "3.5");
break;
case Opt_sb:
return 1; /* handled by get_sb_block() */
case Opt_removed:
ext4_msg(sb, KERN_WARNING, "Ignoring removed %s option",
ext4_msg(NULL, KERN_WARNING, "Ignoring removed %s option",
param->key);
return 1;
case Opt_abort:
Expand All @@ -2310,7 +2316,7 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param)
#ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT
sb->s_flags |= SB_INLINECRYPT;
#else
ext4_msg(sb, KERN_ERR, "inline encryption not supported");
ext4_msg(NULL, KERN_ERR, "inline encryption not supported");
#endif
return 1;
case Opt_errors:
Expand All @@ -2326,22 +2332,22 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param)
break;

if (m->token == Opt_err) {
ext4_msg(sb, KERN_ERR, "Unrecognized mount option \"%s\" "
ext4_msg(NULL, KERN_ERR, "Unrecognized mount option \"%s\" "
"or missing value", param->key);
return -1;
return -EINVAL;
}

if ((m->flags & MOPT_NO_EXT2) && IS_EXT2_SB(sb)) {
ext4_msg(sb, KERN_ERR,
ext4_msg(NULL, KERN_ERR,
"Mount option \"%s\" incompatible with ext2",
param->key);
return -1;
return -EINVAL;
}
if ((m->flags & MOPT_NO_EXT3) && IS_EXT3_SB(sb)) {
ext4_msg(sb, KERN_ERR,
ext4_msg(NULL, KERN_ERR,
"Mount option \"%s\" incompatible with ext3",
param->key);
return -1;
return -EINVAL;
}

if (m->flags & MOPT_EXPLICIT) {
Expand All @@ -2350,38 +2356,38 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param)
} else if (m->mount_opt & EXT4_MOUNT_JOURNAL_CHECKSUM) {
set_opt2(sb, EXPLICIT_JOURNAL_CHECKSUM);
} else
return -1;
return -EINVAL;
}
if (m->flags & MOPT_CLEAR_ERR)
clear_opt(sb, ERRORS_MASK);
if (token == Opt_noquota && sb_any_quota_loaded(sb)) {
ext4_msg(sb, KERN_ERR, "Cannot change quota "
ext4_msg(NULL, KERN_ERR, "Cannot change quota "
"options when quota turned on");
return -1;
return -EINVAL;
}

if (m->flags & MOPT_NOSUPPORT) {
ext4_msg(sb, KERN_ERR, "%s option not supported",
ext4_msg(NULL, KERN_ERR, "%s option not supported",
param->key);
} else if (token == Opt_commit) {
if (result.uint_32 == 0)
sbi->s_commit_interval = JBD2_DEFAULT_MAX_COMMIT_AGE;
else if (result.uint_32 > INT_MAX / HZ) {
ext4_msg(sb, KERN_ERR,
ext4_msg(NULL, KERN_ERR,
"Invalid commit interval %d, "
"must be smaller than %d",
result.uint_32, INT_MAX / HZ);
return -1;
return -EINVAL;
}
sbi->s_commit_interval = HZ * result.uint_32;
} else if (token == Opt_debug_want_extra_isize) {
if ((result.uint_32 & 1) ||
(result.uint_32 < 4) ||
(result.uint_32 >
(sbi->s_inode_size - EXT4_GOOD_OLD_INODE_SIZE))) {
ext4_msg(sb, KERN_ERR,
ext4_msg(NULL, KERN_ERR,
"Invalid want_extra_isize %d", result.uint_32);
return -1;
return -EINVAL;
}
sbi->s_want_extra_isize = result.uint_32;
} else if (token == Opt_max_batch_time) {
Expand All @@ -2392,10 +2398,10 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param)
if (result.uint_32 &&
(result.uint_32 > (1 << 30) ||
!is_power_of_2(result.uint_32))) {
ext4_msg(sb, KERN_ERR,
ext4_msg(NULL, KERN_ERR,
"EXT4-fs: inode_readahead_blks must be "
"0 or a power of 2 smaller than 2^31");
return -1;
return -EINVAL;
}
sbi->s_inode_readahead_blks = result.uint_32;
} else if (token == Opt_init_itable) {
Expand All @@ -2414,24 +2420,24 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param)
} else if (token == Opt_resuid) {
uid = make_kuid(current_user_ns(), result.uint_32);
if (!uid_valid(uid)) {
ext4_msg(sb, KERN_ERR, "Invalid uid value %d",
ext4_msg(NULL, KERN_ERR, "Invalid uid value %d",
result.uint_32);
return -1;
return -EINVAL;
}
sbi->s_resuid = uid;
} else if (token == Opt_resgid) {
gid = make_kgid(current_user_ns(), result.uint_32);
if (!gid_valid(gid)) {
ext4_msg(sb, KERN_ERR, "Invalid gid value %d",
ext4_msg(NULL, KERN_ERR, "Invalid gid value %d",
result.uint_32);
return -1;
return -EINVAL;
}
sbi->s_resgid = gid;
} else if (token == Opt_journal_dev) {
if (is_remount) {
ext4_msg(sb, KERN_ERR,
ext4_msg(NULL, KERN_ERR,
"Cannot specify journal on remount");
return -1;
return -EINVAL;
}
ctx->journal_devnum = result.uint_32;
} else if (token == Opt_journal_path) {
Expand All @@ -2440,26 +2446,26 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param)
int error;

if (is_remount) {
ext4_msg(sb, KERN_ERR,
ext4_msg(NULL, KERN_ERR,
"Cannot specify journal on remount");
return -1;
return -EINVAL;
}

error = fs_lookup_param(fc, param, 1, &path);
if (error) {
ext4_msg(sb, KERN_ERR, "error: could not find "
ext4_msg(NULL, KERN_ERR, "error: could not find "
"journal device path");
return -1;
return -EINVAL;
}

journal_inode = d_inode(path.dentry);
ctx->journal_devnum = new_encode_dev(journal_inode->i_rdev);
path_put(&path);
} else if (token == Opt_journal_ioprio) {
if (result.uint_32 > 7) {
ext4_msg(sb, KERN_ERR, "Invalid journal IO priority"
ext4_msg(NULL, KERN_ERR, "Invalid journal IO priority"
" (must be 0-7)");
return -1;
return -EINVAL;
}
ctx->journal_ioprio =
IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, result.uint_32);
Expand All @@ -2468,11 +2474,11 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param)
} else if (m->flags & MOPT_DATAJ) {
if (is_remount) {
if (!sbi->s_journal)
ext4_msg(sb, KERN_WARNING, "Remounting file system with no journal so ignoring journalled data option");
ext4_msg(NULL, KERN_WARNING, "Remounting file system with no journal so ignoring journalled data option");
else if (test_opt(sb, DATA_FLAGS) != m->mount_opt) {
ext4_msg(sb, KERN_ERR,
ext4_msg(NULL, KERN_ERR,
"Cannot change data mode on remount");
return -1;
return -EINVAL;
}
} else {
clear_opt(sb, DATA_FLAGS);
Expand All @@ -2482,12 +2488,12 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param)
} else if (m->flags & MOPT_QFMT) {
if (sb_any_quota_loaded(sb) &&
sbi->s_jquota_fmt != m->mount_opt) {
ext4_msg(sb, KERN_ERR, "Cannot change journaled "
ext4_msg(NULL, KERN_ERR, "Cannot change journaled "
"quota options when quota turned on");
return -1;
return -EINVAL;
}
if (ext4_has_feature_quota(sb)) {
ext4_msg(sb, KERN_INFO,
ext4_msg(NULL, KERN_INFO,
"Quota format mount options ignored "
"when QUOTA feature is enabled");
return 1;
Expand All @@ -2504,18 +2510,18 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param)
(!(sbi->s_mount_opt & EXT4_MOUNT_DAX_ALWAYS) ||
(sbi->s_mount_opt2 & EXT4_MOUNT2_DAX_NEVER))) {
fail_dax_change_remount:
ext4_msg(sb, KERN_ERR, "can't change "
ext4_msg(NULL, KERN_ERR, "can't change "
"dax mount option while remounting");
return -1;
return -EINVAL;
}
if (is_remount &&
(test_opt(sb, DATA_FLAGS) ==
EXT4_MOUNT_JOURNAL_DATA)) {
ext4_msg(sb, KERN_ERR, "can't mount with "
ext4_msg(NULL, KERN_ERR, "can't mount with "
"both data=journal and dax");
return -1;
return -EINVAL;
}
ext4_msg(sb, KERN_WARNING,
ext4_msg(NULL, KERN_WARNING,
"DAX enabled. Warning: EXPERIMENTAL, use at your own risk");
sbi->s_mount_opt |= EXT4_MOUNT_DAX_ALWAYS;
sbi->s_mount_opt2 &= ~EXT4_MOUNT2_DAX_NEVER;
Expand All @@ -2541,20 +2547,20 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param)
break;
}
#else
ext4_msg(sb, KERN_INFO, "dax option not supported");
ext4_msg(NULL, KERN_INFO, "dax option not supported");
sbi->s_mount_opt2 |= EXT4_MOUNT2_DAX_NEVER;
sbi->s_mount_opt &= ~EXT4_MOUNT_DAX_ALWAYS;
return -1;
return -EINVAL;
#endif
} else if (token == Opt_data_err_abort) {
sbi->s_mount_opt |= m->mount_opt;
} else if (token == Opt_data_err_ignore) {
sbi->s_mount_opt &= ~m->mount_opt;
} else if (token == Opt_mb_optimize_scan) {
if (result.int_32 != 0 && result.int_32 != 1) {
ext4_msg(sb, KERN_WARNING,
ext4_msg(NULL, KERN_WARNING,
"mb_optimize_scan should be set to 0 or 1.");
return -1;
return -EINVAL;
}
ctx->mb_optimize_scan = result.int_32;
} else {
Expand All @@ -2567,11 +2573,11 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param)
if (m->flags & MOPT_CLEAR)
set = !set;
else if (unlikely(!(m->flags & MOPT_SET))) {
ext4_msg(sb, KERN_WARNING,
ext4_msg(NULL, KERN_WARNING,
"buggy handling of option %s",
param->key);
WARN_ON(1);
return -1;
return -EINVAL;
}
if (m->flags & MOPT_2) {
if (set != 0)
Expand Down Expand Up @@ -2639,12 +2645,17 @@ static int parse_options(char *options, struct super_block *sb,
}
}

return ext4_validate_options(sb);
ret = ext4_validate_options(&fc);
if (ret < 0)
return 0;

return 1;
}

static int ext4_validate_options(struct super_block *sb)
static int ext4_validate_options(struct fs_context *fc)
{
struct ext4_sb_info *sbi = EXT4_SB(sb);
struct ext4_sb_info *sbi = fc->s_fs_info;
struct super_block *sb = sbi->s_sb;
#ifdef CONFIG_QUOTA
char *usr_qf_name, *grp_qf_name;
/*
Expand All @@ -2653,9 +2664,9 @@ static int ext4_validate_options(struct super_block *sb)
* to support legacy quotas in quota files.
*/
if (test_opt(sb, PRJQUOTA) && !ext4_has_feature_project(sb)) {
ext4_msg(sb, KERN_ERR, "Project quota feature not enabled. "
ext4_msg(NULL, KERN_ERR, "Project quota feature not enabled. "
"Cannot enable project quota enforcement.");
return 0;
return -EINVAL;
}
usr_qf_name = get_qf_name(sb, sbi, USRQUOTA);
grp_qf_name = get_qf_name(sb, sbi, GRPQUOTA);
Expand All @@ -2667,27 +2678,28 @@ static int ext4_validate_options(struct super_block *sb)
clear_opt(sb, GRPQUOTA);

if (test_opt(sb, GRPQUOTA) || test_opt(sb, USRQUOTA)) {
ext4_msg(sb, KERN_ERR, "old and new quota "
ext4_msg(NULL, KERN_ERR, "old and new quota "
"format mixing");
return 0;
return -EINVAL;
}

if (!sbi->s_jquota_fmt) {
ext4_msg(sb, KERN_ERR, "journaled quota format "
ext4_msg(NULL, KERN_ERR, "journaled quota format "
"not specified");
return 0;
return -EINVAL;
}
}
#endif
if (test_opt(sb, DIOREAD_NOLOCK)) {
int blocksize =
BLOCK_SIZE << le32_to_cpu(sbi->s_es->s_log_block_size);
if (blocksize < PAGE_SIZE)
ext4_msg(sb, KERN_WARNING, "Warning: mounting with an "
"experimental mount option 'dioread_nolock' "
"for blocksize < PAGE_SIZE");
ext4_msg(NULL, KERN_WARNING,
"Warning: mounting with an experimental "
"option 'dioread_nolock' for "
"blocksize < PAGE_SIZE");
}
return 1;
return 0;
}

static inline void ext4_show_quota_options(struct seq_file *seq,
Expand Down

0 comments on commit da812f6

Please sign in to comment.