[PATCH 3/3] fuse: allow setting of root nodeid

Darrick J. Wong
2025-09-16T00:36:03Z

Provide a new mount option so that fuse servers can actually set the
root nodeid.

Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
---
fs/fuse/fuse_i.h | 2 ++
fs/fuse/inode.c | 11 +++++++++++
2 files changed, 13 insertions(+)

diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 70942340e33855..fb60686fb9c61a 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -619,6 +619,7 @@ struct fuse_fs_context {
int fd;
struct file *file;
unsigned int rootmode;
+ u64 root_nodeid;
kuid_t user_id;
kgid_t group_id;
bool is_bdev:1;
@@ -633,6 +634,7 @@ struct fuse_fs_context {
bool no_force_umount:1;
bool legacy_opts_show:1;
bool local_fs:1;
+ bool root_nodeid_present:1;
enum fuse_dax_mode dax_mode;
unsigned int max_read;
unsigned int blksize;
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 350805fa61690c..e74d39ac05a570 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -781,6 +781,7 @@ enum {
OPT_ALLOW_OTHER,
OPT_MAX_READ,
OPT_BLKSIZE,
+ OPT_ROOT_NODEID,
OPT_ERR
};

@@ -795,6 +796,7 @@ static const struct fs_parameter_spec fuse_fs_parameters[] = {
fsparam_u32 ("max_read", OPT_MAX_READ),
fsparam_u32 ("blksize", OPT_BLKSIZE),
fsparam_string ("subtype", OPT_SUBTYPE),
+ fsparam_u64 ("root_nodeid", OPT_ROOT_NODEID),
{}
};

@@ -890,6 +892,11 @@ static int fuse_parse_param(struct fs_context *fsc, struct fs_parameter *param)
ctx->blksize = result.uint_32;
break;

+ case OPT_ROOT_NODEID:
+ ctx->root_nodeid = result.uint_64;
+ ctx->root_nodeid_present = true;
+ break;
+
default:
return -EINVAL;
}
@@ -925,6 +932,8 @@ static int fuse_show_options(struct seq_file *m, struct dentry *root)
seq_printf(m, ",max_read=%u", fc->max_read);
if (sb->s_bdev && sb->s_blocksize != FUSE_DEFAULT_BLKSIZE)
seq_printf(m, ",blksize=%lu", sb->s_blocksize);
+ if (fc->root_nodeid && fc->root_nodeid != FUSE_ROOT_ID)
+ seq_printf(m, ",root_nodeid=%llu", fc->root_nodeid);
}
#ifdef CONFIG_FUSE_DAX
if (fc->dax_mode == FUSE_DAX_ALWAYS)
@@ -1910,6 +1919,8 @@ int fuse_fill_super_common(struct super_block *sb, struct fuse_fs_context *ctx)
sb->s_flags |= SB_POSIXACL;

fc->default_permissions = ctx->default_permissions;
+ if (ctx->root_nodeid_present)
+ fc->root_nodeid = ctx->root_nodeid;
fc->allow_other = ctx->allow_other;
fc->user_id = ctx->user_id;
fc->group_id = ctx->group_id;