[PATCH v2 10/21] fuse: prepare to cache statx attributes from entry replies

Joanne Koong <[email protected]> Fri, 15 May 2026 17:39:53 -0700
Newsgroups org.kernel.vger.linux-unionfs,dev.linux.lists.fuse-devel
Message-ID <[email protected]>
Add an arg for a struct fuse_statx pointer to fuse_iget() and pass it
through to fuse_change_attributes_i() so the statx attributes get
persisted in cache.

All existing callers pass in NULL for the arg. This change is in
preparation for a new struct fuse_entry2_out outarg which will contain
filled out statx information from the server returned on
LOOKUP/MKDIR/MKNOD/etc requests.

Reviewed-by: Amir Goldstein <[email protected]>
Signed-off-by: Joanne Koong <[email protected]>
---
 fs/fuse/dir.c     |  6 +++---
 fs/fuse/fuse_i.h  |  7 +++----
 fs/fuse/inode.c   | 12 ++++++------
 fs/fuse/readdir.c |  2 +-
 4 files changed, 13 insertions(+), 14 deletions(-)

diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 9a8e525f4d2b..7d3c9878b833 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -590,7 +590,7 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name
 	}
 
 	*inode = fuse_iget(sb, outarg->nodeid, outarg->generation,
-			   &outarg->attr, ATTR_TIMEOUT(outarg),
+			   &outarg->attr, NULL, ATTR_TIMEOUT(outarg),
 			   attr_version, evict_ctr);
 	err = -ENOMEM;
 	if (!*inode) {
@@ -890,7 +890,7 @@ static int fuse_create_open(struct mnt_idmap *idmap, struct inode *dir,
 	ff->nodeid = outentry.nodeid;
 	ff->open_flags = outopenp->open_flags;
 	inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
-			  &outentry.attr, ATTR_TIMEOUT(&outentry), 0, 0);
+			  &outentry.attr, NULL, ATTR_TIMEOUT(&outentry), 0, 0);
 	if (!inode) {
 		flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
 		fuse_sync_release(NULL, ff, flags, false);
@@ -1017,7 +1017,7 @@ static struct dentry *create_new_entry(struct mnt_idmap *idmap, struct fuse_moun
 		goto out_put_forget_req;
 
 	inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
-			  &outarg.attr, ATTR_TIMEOUT(&outarg), 0, 0);
+			  &outarg.attr, NULL, ATTR_TIMEOUT(&outarg), 0, 0);
 	if (!inode) {
 		fuse_chan_queue_forget(fm->fc->chan, forget, outarg.nodeid, 1);
 		return ERR_PTR(-ENOMEM);
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index a1034533ce60..1f2c849ea4e3 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -912,10 +912,9 @@ extern const struct dentry_operations fuse_dentry_operations;
 /*
  * Get a filled in inode
  */
-struct inode *fuse_iget(struct super_block *sb, u64 nodeid,
-			int generation, struct fuse_attr *attr,
-			u64 attr_valid, u64 attr_version,
-			u64 evict_ctr);
+struct inode *fuse_iget(struct super_block *sb, u64 nodeid, int generation,
+			struct fuse_attr *attr, struct fuse_statx *sx,
+			u64 attr_valid, u64 attr_version, u64 evict_ctr);
 
 int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name,
 		     struct fuse_entry_out *outarg, struct inode **inode);
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 9e9c20e846e7..8757c01e3bb2 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -457,8 +457,8 @@ static int fuse_inode_set(struct inode *inode, void *_nodeidp)
 
 struct inode *fuse_iget(struct super_block *sb, u64 nodeid,
 			int generation, struct fuse_attr *attr,
-			u64 attr_valid, u64 attr_version,
-			u64 evict_ctr)
+			struct fuse_statx *sx, u64 attr_valid,
+			u64 attr_version, u64 evict_ctr)
 {
 	struct inode *inode;
 	struct fuse_inode *fi;
@@ -520,7 +520,7 @@ struct inode *fuse_iget(struct super_block *sb, u64 nodeid,
 	fi->nlookup++;
 	spin_unlock(&fi->lock);
 done:
-	fuse_change_attributes_i(inode, attr, NULL, attr_valid, attr_version,
+	fuse_change_attributes_i(inode, attr, sx, attr_valid, attr_version,
 				 evict_ctr);
 	if (is_new_inode)
 		unlock_new_inode(inode);
@@ -1049,7 +1049,7 @@ static struct inode *fuse_get_root_inode(struct super_block *sb, unsigned int mo
 	attr.mode = mode;
 	attr.ino = FUSE_ROOT_ID;
 	attr.nlink = 1;
-	return fuse_iget(sb, FUSE_ROOT_ID, 0, &attr, 0, 0, 0);
+	return fuse_iget(sb, FUSE_ROOT_ID, 0, &attr, NULL, 0, 0, 0);
 }
 
 struct fuse_inode_handle {
@@ -1652,8 +1652,8 @@ static int fuse_fill_super_submount(struct super_block *sb,
 		return -ENOMEM;
 
 	fuse_fill_attr_from_inode(&root_attr, parent_fi);
-	root = fuse_iget(sb, parent_fi->nodeid, 0, &root_attr, 0, 0,
-			 fuse_get_evict_ctr(fm->fc));
+	root = fuse_iget(sb, parent_fi->nodeid, 0, &root_attr, NULL, 0,
+			 0, fuse_get_evict_ctr(fm->fc));
 	/*
 	 * This inode is just a duplicate, so it is not looked up and
 	 * its nlookup should not be incremented.  fuse_iget() does
diff --git a/fs/fuse/readdir.c b/fs/fuse/readdir.c
index 49226f022339..0dcb2d75d50f 100644
--- a/fs/fuse/readdir.c
+++ b/fs/fuse/readdir.c
@@ -234,7 +234,7 @@ static int fuse_direntplus_link(struct file *file,
 		 */
 	} else {
 		inode = fuse_iget(dir->i_sb, o->nodeid, o->generation,
-				  &o->attr, ATTR_TIMEOUT(o),
+				  &o->attr, NULL, ATTR_TIMEOUT(o),
 				  attr_version, evict_ctr);
 		if (!inode)
 			inode = ERR_PTR(-ENOMEM);
-- 
2.52.0