Commit da812f61 authored by Lukas Czerner's avatar Lukas Czerner Committed by Theodore Ts'o
Browse files

ext4: Allow sb to be NULL in ext4_msg()



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: default avatarLukas Czerner <lczerner@redhat.com>
Reviewed-by: default avatarCarlos Maiolino <cmaiolino@redhat.com>
Link: https://lore.kernel.org/r/20211027141857.33657-6-lczerner@redhat.com


Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
parent 461c3af0
Loading
Loading
Loading
Loading
+78 −66
Original line number Diff line number Diff line
@@ -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
@@ -915,14 +915,20 @@ void __ext4_msg(struct super_block *sb,
	struct va_format vaf;
	va_list args;

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

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

@@ -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:
@@ -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:
@@ -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) {
@@ -2350,28 +2356,28 @@ 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) {
@@ -2379,9 +2385,9 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param)
		    (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) {
@@ -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) {
@@ -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) {
@@ -2440,16 +2446,16 @@ 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);
@@ -2457,9 +2463,9 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param)
		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);
@@ -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);
@@ -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;
@@ -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;
@@ -2541,10 +2547,10 @@ 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;
@@ -2552,9 +2558,9 @@ static int handle_mount_opt(struct fs_context *fc, struct fs_parameter *param)
		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 {
@@ -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)
@@ -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;
	/*
@@ -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);
@@ -2667,15 +2678,15 @@ 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
@@ -2683,11 +2694,12 @@ static int ext4_validate_options(struct super_block *sb)
		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,