]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
hostfs: fix the host directory parse when mounting.
authorHongbo Li <lihongbo22@huawei.com>
Thu, 25 Jul 2024 06:51:30 +0000 (14:51 +0800)
committerChristian Brauner <brauner@kernel.org>
Sat, 27 Jul 2024 07:56:33 +0000 (09:56 +0200)
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: Maciej Ż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: Hongbo Li <lihongbo22@huawei.com>
Link: https://lore.kernel.org/r/20240725065130.1821964-1-lihongbo22@huawei.com
[brauner: minor fixes]
Signed-off-by: Christian Brauner <brauner@kernel.org>
fs/hostfs/hostfs_kern.c

index 2b532670a561d51b1c96f2f47e30ad0b3c585494..e866b08e448f7e1c47c3dfcc006b051e6cd47b20 100644 (file)
@@ -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>
@@ -927,7 +928,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;
 
@@ -941,15 +941,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);
@@ -975,6 +966,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);
@@ -992,6 +1035,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,
 };