Commit af5f2396 authored by Amir Goldstein's avatar Amir Goldstein
Browse files

ovl: store enum redirect_mode in config instead of a string



Do all the logic to set the mode during mount options parsing and
do not keep the option string around.

Use a constant_table to translate from enum redirect mode to string
in preperation for new mount api option parsing.

The mount option "off" is translated to either "follow" or "nofollow",
depending on the "redirect_always_follow" build/module config, so
in effect, there are only three possible redirect modes.

This results in a minor change to the string that is displayed
in show_options() - when redirect_dir is enabled by default and the user
mounts with the option "redirect_dir=off", instead of displaying the mode
"redirect_dir=off" in show_options(), the displayed mode will be either
"redirect_dir=follow" or "redirect_dir=nofollow", depending on the value
of "redirect_always_follow" build/module config.

The displayed mode reflects the effective mode, so mounting overlayfs
again with the dispalyed redirect_dir option will result with the same
effective and displayed mode.

Signed-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
parent dcb399de
Loading
Loading
Loading
Loading
+4 −5
Original line number Diff line number Diff line
@@ -231,12 +231,11 @@ Mount options:
    Redirects are enabled.
- "redirect_dir=follow":
    Redirects are not created, but followed.
- "redirect_dir=off":
    Redirects are not created and only followed if "redirect_always_follow"
    feature is enabled in the kernel/module config.
- "redirect_dir=nofollow":
    Redirects are not created and not followed (equivalent to "redirect_dir=off"
    if "redirect_always_follow" feature is not enabled).
    Redirects are not created and not followed.
- "redirect_dir=off":
    If "redirect_always_follow" is enabled in the kernel/module config,
    this "off" traslates to "follow", otherwise it translates to "nofollow".

When the NFS export feature is enabled, every copied up directory is
indexed by the file handle of the lower inode and a file handle of the
+1 −1
Original line number Diff line number Diff line
@@ -952,7 +952,7 @@ static bool ovl_type_merge_or_lower(struct dentry *dentry)

static bool ovl_can_move(struct dentry *dentry)
{
	return ovl_redirect_dir(dentry->d_sb) ||
	return ovl_redirect_dir(OVL_FS(dentry->d_sb)) ||
		!d_is_dir(dentry) || !ovl_type_merge_or_lower(dentry);
}

+3 −3
Original line number Diff line number Diff line
@@ -961,7 +961,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
		.is_dir = false,
		.opaque = false,
		.stop = false,
		.last = ofs->config.redirect_follow ? false : !ovl_numlower(poe),
		.last = ovl_redirect_follow(ofs) ? false : !ovl_numlower(poe),
		.redirect = NULL,
		.metacopy = false,
	};
@@ -1022,7 +1022,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
	for (i = 0; !d.stop && i < ovl_numlower(poe); i++) {
		struct ovl_path lower = ovl_lowerstack(poe)[i];

		if (!ofs->config.redirect_follow)
		if (!ovl_redirect_follow(ofs))
			d.last = i == ovl_numlower(poe) - 1;
		else if (d.is_dir || !ofs->numdatalayer)
			d.last = lower.layer->idx == ovl_numlower(roe);
@@ -1102,7 +1102,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
		 * this attack vector when not necessary.
		 */
		err = -EPERM;
		if (d.redirect && !ofs->config.redirect_follow) {
		if (d.redirect && !ovl_redirect_follow(ofs)) {
			pr_warn_ratelimited("refusing to follow redirect for (%pd2)\n",
					    dentry);
			goto out_put;
+27 −12
Original line number Diff line number Diff line
@@ -57,6 +57,13 @@ enum ovl_entry_flag {
	OVL_E_CONNECTED,
};

enum {
	OVL_REDIRECT_OFF,	/* "off" mode is never used. In effect	*/
	OVL_REDIRECT_FOLLOW,	/* ...it translates to either "follow"	*/
	OVL_REDIRECT_NOFOLLOW,	/* ...or "nofollow".			*/
	OVL_REDIRECT_ON,
};

enum {
	OVL_XINO_OFF,
	OVL_XINO_AUTO,
@@ -352,17 +359,6 @@ static inline bool ovl_open_flags_need_copy_up(int flags)
	return ((OPEN_FMODE(flags) & FMODE_WRITE) || (flags & O_TRUNC));
}

static inline bool ovl_allow_offline_changes(struct ovl_fs *ofs)
{
	/*
	 * To avoid regressions in existing setups with overlay lower offline
	 * changes, we allow lower changes only if none of the new features
	 * are used.
	 */
	return (!ofs->config.index && !ofs->config.metacopy &&
		!ofs->config.redirect_dir && ofs->config.xino != OVL_XINO_ON);
}


/* util.c */
int ovl_want_write(struct dentry *dentry);
@@ -421,7 +417,6 @@ bool ovl_dentry_needs_data_copy_up(struct dentry *dentry, int flags);
bool ovl_dentry_needs_data_copy_up_locked(struct dentry *dentry, int flags);
bool ovl_has_upperdata(struct inode *inode);
void ovl_set_upperdata(struct inode *inode);
bool ovl_redirect_dir(struct super_block *sb);
const char *ovl_dentry_get_redirect(struct dentry *dentry);
void ovl_dentry_set_redirect(struct dentry *dentry, const char *redirect);
void ovl_inode_update(struct inode *inode, struct dentry *upperdentry);
@@ -489,6 +484,16 @@ static inline bool ovl_is_impuredir(struct super_block *sb,
	return ovl_path_check_dir_xattr(ofs, &upperpath, OVL_XATTR_IMPURE);
}

static inline bool ovl_redirect_follow(struct ovl_fs *ofs)
{
	return ofs->config.redirect_mode != OVL_REDIRECT_NOFOLLOW;
}

static inline bool ovl_redirect_dir(struct ovl_fs *ofs)
{
	return ofs->config.redirect_mode == OVL_REDIRECT_ON;
}

/*
 * With xino=auto, we do best effort to keep all inodes on same st_dev and
 * d_ino consistent with st_ino.
@@ -499,6 +504,16 @@ static inline bool ovl_xino_warn(struct ovl_fs *ofs)
	return ofs->config.xino == OVL_XINO_ON;
}

/*
 * To avoid regressions in existing setups with overlay lower offline changes,
 * we allow lower changes only if none of the new features are used.
 */
static inline bool ovl_allow_offline_changes(struct ovl_fs *ofs)
{
	return (!ofs->config.index && !ofs->config.metacopy &&
		!ovl_redirect_dir(ofs) && !ovl_xino_warn(ofs));
}

/* All layers on same fs? */
static inline bool ovl_same_fs(struct ovl_fs *ofs)
{
+1 −3
Original line number Diff line number Diff line
@@ -10,9 +10,7 @@ struct ovl_config {
	char *upperdir;
	char *workdir;
	bool default_permissions;
	bool redirect_dir;
	bool redirect_follow;
	const char *redirect_mode;
	int redirect_mode;
	bool index;
	bool uuid;
	bool nfs_export;
Loading