From: Darrick J. Wong <djwong@xxxxxxxxxx> Change this from a hardcoded constant to a dynamic field so that fuse servers don't need to translate. Signed-off-by: "Darrick J. Wong" <djwong@xxxxxxxxxx> --- fs/fuse/fuse_i.h | 7 +++++-- fs/fuse/fuse_trace.h | 6 ++++-- fs/fuse/dir.c | 10 ++++++---- fs/fuse/inode.c | 11 +++++++---- fs/fuse/readdir.c | 10 +++++----- 5 files changed, 27 insertions(+), 17 deletions(-) diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 63ce9ddb96477c..66cf8dcf9216e7 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -665,6 +665,9 @@ struct fuse_conn { struct rcu_head rcu; + /* node id of the root directory */ + u64 root_nodeid; + /** The user id for this mount */ kuid_t user_id; @@ -1097,9 +1100,9 @@ static inline u64 get_node_id(struct inode *inode) return get_fuse_inode(inode)->nodeid; } -static inline int invalid_nodeid(u64 nodeid) +static inline int invalid_nodeid(const struct fuse_conn *fc, u64 nodeid) { - return !nodeid || nodeid == FUSE_ROOT_ID; + return !nodeid || nodeid == fc->root_nodeid; } static inline u64 fuse_get_attr_version(struct fuse_conn *fc) diff --git a/fs/fuse/fuse_trace.h b/fs/fuse/fuse_trace.h index d3a0bd066370f5..1f2ff30bececd4 100644 --- a/fs/fuse/fuse_trace.h +++ b/fs/fuse/fuse_trace.h @@ -1012,6 +1012,7 @@ TRACE_EVENT(fuse_iomap_config, TP_STRUCT__entry( __field(dev_t, connection) + __field(uint64_t, root_nodeid) __field(uint32_t, flags) __field(uint32_t, blocksize) @@ -1026,6 +1027,7 @@ TRACE_EVENT(fuse_iomap_config, TP_fast_assign( __entry->connection = fm->fc->dev; + __entry->root_nodeid = fm->fc->root_nodeid; __entry->flags = outarg->flags; __entry->blocksize = outarg->s_blocksize; __entry->max_links = outarg->s_max_links; @@ -1036,8 +1038,8 @@ TRACE_EVENT(fuse_iomap_config, __entry->uuid_len = outarg->s_uuid_len; ), - TP_printk("connection %u flags (%s) blocksize 0x%x max_links %u time_gran %u time_min %lld time_max %lld maxbytes 0x%llx uuid_len %u", - __entry->connection, + TP_printk("connection %u root_ino 0x%llx flags (%s) blocksize 0x%x max_links %u time_gran %u time_min %lld time_max %lld maxbytes 0x%llx uuid_len %u", + __entry->connection, __entry->root_nodeid, __print_flags(__entry->flags, "|", FUSE_IOMAP_CONFIG_STRINGS), __entry->blocksize, __entry->max_links, __entry->time_gran, __entry->time_min, __entry->time_max, __entry->maxbytes, diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 07aa338208b5cc..02c8e705af1e35 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -386,7 +386,7 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name err = -EIO; if (fuse_invalid_attr(&outarg->attr)) goto out_put_forget; - if (outarg->nodeid == FUSE_ROOT_ID && outarg->generation != 0) { + if (outarg->nodeid == fm->fc->root_nodeid && outarg->generation != 0) { pr_warn_once("root generation should be zero\n"); outarg->generation = 0; } @@ -436,7 +436,7 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, goto out_err; err = -EIO; - if (inode && get_node_id(inode) == FUSE_ROOT_ID) + if (inode && get_node_id(inode) == fc->root_nodeid) goto out_iput; newent = d_splice_alias(inode, entry); @@ -687,7 +687,8 @@ static int fuse_create_open(struct mnt_idmap *idmap, struct inode *dir, goto out_free_ff; err = -EIO; - if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid) || + if (!S_ISREG(outentry.attr.mode) || + invalid_nodeid(fm->fc, outentry.nodeid) || fuse_invalid_attr(&outentry.attr)) goto out_free_ff; @@ -838,7 +839,8 @@ static struct dentry *create_new_entry(struct mnt_idmap *idmap, struct fuse_moun goto out_put_forget_req; err = -EIO; - if (invalid_nodeid(outarg.nodeid) || fuse_invalid_attr(&outarg.attr)) + if (invalid_nodeid(fm->fc, outarg.nodeid) || + fuse_invalid_attr(&outarg.attr)) goto out_put_forget_req; if ((outarg.attr.mode ^ mode) & S_IFMT) diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index abb2beef3cfe1f..f2d519c0f737e6 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -1001,6 +1001,7 @@ void fuse_conn_init(struct fuse_conn *fc, struct fuse_mount *fm, fc->max_pages_limit = fuse_max_pages_limit; fc->name_max = FUSE_NAME_LOW_MAX; fc->timeout.req_timeout = 0; + fc->root_nodeid = FUSE_ROOT_ID; if (IS_ENABLED(CONFIG_FUSE_BACKING)) fuse_backing_files_init(fc); @@ -1056,12 +1057,14 @@ EXPORT_SYMBOL_GPL(fuse_conn_get); static struct inode *fuse_get_root_inode(struct super_block *sb, unsigned int mode) { struct fuse_attr attr; + struct fuse_conn *fc = get_fuse_conn_super(sb); + memset(&attr, 0, sizeof(attr)); attr.mode = mode; - attr.ino = FUSE_ROOT_ID; + attr.ino = fc->root_nodeid; attr.nlink = 1; - return fuse_iget(sb, FUSE_ROOT_ID, 0, &attr, 0, 0, 0); + return fuse_iget(sb, fc->root_nodeid, 0, &attr, 0, 0, 0); } struct fuse_inode_handle { @@ -1105,7 +1108,7 @@ static struct dentry *fuse_get_dentry(struct super_block *sb, goto out_iput; entry = d_obtain_alias(inode); - if (!IS_ERR(entry) && get_node_id(inode) != FUSE_ROOT_ID) + if (!IS_ERR(entry) && get_node_id(inode) != fc->root_nodeid) fuse_invalidate_entry_cache(entry); return entry; @@ -1198,7 +1201,7 @@ static struct dentry *fuse_get_parent(struct dentry *child) } parent = d_obtain_alias(inode); - if (!IS_ERR(parent) && get_node_id(inode) != FUSE_ROOT_ID) + if (!IS_ERR(parent) && get_node_id(inode) != fc->root_nodeid) fuse_invalidate_entry_cache(parent); return parent; diff --git a/fs/fuse/readdir.c b/fs/fuse/readdir.c index c2aae2eef0868b..45dd932eb03a5e 100644 --- a/fs/fuse/readdir.c +++ b/fs/fuse/readdir.c @@ -185,12 +185,12 @@ static int fuse_direntplus_link(struct file *file, return 0; } - if (invalid_nodeid(o->nodeid)) - return -EIO; - if (fuse_invalid_attr(&o->attr)) - return -EIO; - fc = get_fuse_conn(dir); + if (invalid_nodeid(fc, o->nodeid)) + return -EIO; + if (fuse_invalid_attr(&o->attr)) + return -EIO; + epoch = atomic_read(&fc->epoch); name.hash = full_name_hash(parent, name.name, name.len);