Commit e75f077f authored by Hongbo Li's avatar Hongbo Li Committed by Wentao Guan
Browse files

hostfs: fix the host directory parse when mounting.

stable inclusion
from stable-v6.6.76
commit be80de30b347dc2eae35dd5f7905ad9c9167dc08
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IBW08Q

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=be80de30b347dc2eae35dd5f7905ad9c9167dc08



--------------------------------

commit ef9ca17ca458ac7253ae71b552e601e49311fc48 upstream.

hostfs not keep the host directory when mounting. When the host
directory is none (default), fc->source is used as the host root
directory, and this is wrong. Here we use `parse_monolithic` to
handle the old mount path for parsing the root directory. For new
mount path, The `parse_param` is used for the host directory parse.

Reported-and-tested-by: default avatarMaciej Żenczykowski <maze@google.com>
Fixes: cd140ce9f611 ("hostfs: convert hostfs to use the new mount API")
Link: https://lore.kernel.org/all/CANP3RGceNzwdb7w=vPf5=7BCid5HVQDmz1K5kC9JG42+HVAh_g@mail.gmail.com/


Cc: Christian Brauner <brauner@kernel.org>
Signed-off-by: default avatarHongbo Li <lihongbo22@huawei.com>
Link: https://lore.kernel.org/r/20240725065130.1821964-1-lihongbo22@huawei.com


[brauner: minor fixes]
Signed-off-by: default avatarChristian Brauner <brauner@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
(cherry picked from commit be80de30b347dc2eae35dd5f7905ad9c9167dc08)
Signed-off-by: default avatarWentao Guan <guanwentao@uniontech.com>
parent 787e67f9
Loading
Loading
Loading
Loading
+55 −10
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include <linux/writeback.h>
#include <linux/mount.h>
#include <linux/fs_context.h>
#include <linux/fs_parser.h>
#include <linux/namei.h>
#include "hostfs.h"
#include <init.h>
@@ -925,7 +926,6 @@ static const struct inode_operations hostfs_link_iops = {
static int hostfs_fill_super(struct super_block *sb, struct fs_context *fc)
{
	struct hostfs_fs_info *fsi = sb->s_fs_info;
	const char *host_root = fc->source;
	struct inode *root_inode;
	int err;

@@ -939,15 +939,6 @@ static int hostfs_fill_super(struct super_block *sb, struct fs_context *fc)
	if (err)
		return err;

	/* NULL is printed as '(null)' by printf(): avoid that. */
	if (fc->source == NULL)
		host_root = "";

	fsi->host_root_path =
		kasprintf(GFP_KERNEL, "%s/%s", root_ino, host_root);
	if (fsi->host_root_path == NULL)
		return -ENOMEM;

	root_inode = hostfs_iget(sb, fsi->host_root_path);
	if (IS_ERR(root_inode))
		return PTR_ERR(root_inode);
@@ -973,6 +964,58 @@ static int hostfs_fill_super(struct super_block *sb, struct fs_context *fc)
	return 0;
}

enum hostfs_parma {
	Opt_hostfs,
};

static const struct fs_parameter_spec hostfs_param_specs[] = {
	fsparam_string_empty("hostfs",		Opt_hostfs),
	{}
};

static int hostfs_parse_param(struct fs_context *fc, struct fs_parameter *param)
{
	struct hostfs_fs_info *fsi = fc->s_fs_info;
	struct fs_parse_result result;
	char *host_root;
	int opt;

	opt = fs_parse(fc, hostfs_param_specs, param, &result);
	if (opt < 0)
		return opt;

	switch (opt) {
	case Opt_hostfs:
		host_root = param->string;
		if (!*host_root)
			host_root = "";
		fsi->host_root_path =
			kasprintf(GFP_KERNEL, "%s/%s", root_ino, host_root);
		if (fsi->host_root_path == NULL)
			return -ENOMEM;
		break;
	}

	return 0;
}

static int hostfs_parse_monolithic(struct fs_context *fc, void *data)
{
	struct hostfs_fs_info *fsi = fc->s_fs_info;
	char *host_root = (char *)data;

	/* NULL is printed as '(null)' by printf(): avoid that. */
	if (host_root == NULL)
		host_root = "";

	fsi->host_root_path =
		kasprintf(GFP_KERNEL, "%s/%s", root_ino, host_root);
	if (fsi->host_root_path == NULL)
		return -ENOMEM;

	return 0;
}

static int hostfs_fc_get_tree(struct fs_context *fc)
{
	return get_tree_nodev(fc, hostfs_fill_super);
@@ -990,6 +1033,8 @@ static void hostfs_fc_free(struct fs_context *fc)
}

static const struct fs_context_operations hostfs_context_ops = {
	.parse_monolithic = hostfs_parse_monolithic,
	.parse_param	= hostfs_parse_param,
	.get_tree	= hostfs_fc_get_tree,
	.free		= hostfs_fc_free,
};