[RFC PATCH v3 5/8] fuse: extract helper functions from fuse_do_statx()

Luis Henriques
2026-02-25T11:25:17Z

Split function fuse_do_statx(), so that we get two helper functions: one
to initialise the arguments and another to update the attributes and
statistics. This will allow compound operations to re-use these two helpers.

Signed-off-by: Luis Henriques <luis@igalia.com>
---
fs/fuse/dir.c | 88 +++++++++++++++++++++++++++++++--------------------
1 file changed, 53 insertions(+), 35 deletions(-)

diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 92c9ebfb4985..5c0f1364c392 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -1406,43 +1406,37 @@ static void fuse_statx_to_attr(struct fuse_statx *sx, struct fuse_attr *attr)
attr->blksize = sx->blksize;
}

-static int fuse_do_statx(struct mnt_idmap *idmap, struct inode *inode,
- struct file *file, struct kstat *stat)
+static void fuse_statx_init(struct fuse_args *args, struct fuse_statx_in *inarg,
+ u64 nodeid, struct fuse_file *ff,
+ struct fuse_statx_out *outarg)
{
- int err;
- struct fuse_attr attr;
- struct fuse_statx *sx;
- struct fuse_statx_in inarg;
- struct fuse_statx_out outarg;
- struct fuse_mount *fm = get_fuse_mount(inode);
- u64 attr_version = fuse_get_attr_version(fm->fc);
- FUSE_ARGS(args);
-
- memset(&inarg, 0, sizeof(inarg));
- memset(&outarg, 0, sizeof(outarg));
- /* Directories have separate file-handle space */
- if (file && S_ISREG(inode->i_mode)) {
- struct fuse_file *ff = file->private_data;
+ memset(inarg, 0, sizeof(*inarg));
+ memset(outarg, 0, sizeof(*outarg));

- inarg.getattr_flags |= FUSE_GETATTR_FH;
- inarg.fh = ff->fh;
+ if (ff) {
+ inarg->getattr_flags |= FUSE_GETATTR_FH;
+ inarg->fh = ff->fh;
}
/* For now leave sync hints as the default, request all stats. */
- inarg.sx_flags = 0;
- inarg.sx_mask = STATX_BASIC_STATS | STATX_BTIME;
- args.opcode = FUSE_STATX;
- args.nodeid = get_node_id(inode);
- args.in_numargs = 1;
- args.in_args[0].size = sizeof(inarg);
- args.in_args[0].value = &inarg;
- args.out_numargs = 1;
- args.out_args[0].size = sizeof(outarg);
- args.out_args[0].value = &outarg;
- err = fuse_simple_request(fm, &args);
- if (err)
- return err;
+ inarg->sx_flags = 0;
+ inarg->sx_mask = STATX_BASIC_STATS | STATX_BTIME;
+ args->opcode = FUSE_STATX;
+ args->nodeid = nodeid;
+ args->in_numargs = 1;
+ args->in_args[0].size = sizeof(*inarg);
+ args->in_args[0].value = inarg;
+ args->out_numargs = 1;
+ args->out_args[0].size = sizeof(*outarg);
+ args->out_args[0].value = outarg;
+}
+
+static int fuse_statx_update(struct mnt_idmap *idmap,
+ struct fuse_statx_out *outarg, struct inode *inode,
+ u64 attr_version, struct kstat *stat)
+{
+ struct fuse_statx *sx = &outarg->stat;
+ struct fuse_attr attr;

- sx = &outarg.stat;
if (((sx->mask & STATX_SIZE) && !fuse_valid_size(sx->size)) ||
((sx->mask & STATX_TYPE) && (!fuse_valid_type(sx->mode) ||
inode_wrong_type(inode, sx->mode)))) {
@@ -1450,10 +1444,10 @@ static int fuse_do_statx(struct mnt_idmap *idmap, struct inode *inode,
return -EIO;
}

- fuse_statx_to_attr(&outarg.stat, &attr);
+ fuse_statx_to_attr(sx, &attr);
if ((sx->mask & STATX_BASIC_STATS) == STATX_BASIC_STATS) {
- fuse_change_attributes(inode, &attr, &outarg.stat,
- ATTR_TIMEOUT(&outarg), attr_version);
+ fuse_change_attributes(inode, &attr, sx,
+ ATTR_TIMEOUT(outarg), attr_version);
}

if (stat) {
@@ -1467,6 +1461,30 @@ static int fuse_do_statx(struct mnt_idmap *idmap, struct inode *inode,
return 0;
}

+static int fuse_do_statx(struct mnt_idmap *idmap, struct inode *inode,
+ struct file *file, struct kstat *stat)
+{
+ int err;
+ struct fuse_statx_in inarg;
+ struct fuse_statx_out outarg;
+ struct fuse_mount *fm = get_fuse_mount(inode);
+ struct fuse_file *ff = NULL;
+ u64 attr_version = fuse_get_attr_version(fm->fc);
+ FUSE_ARGS(args);
+
+ /* Directories have separate file-handle space */
+ if (file && S_ISREG(inode->i_mode))
+ ff = file->private_data;
+
+ fuse_statx_init(&args, &inarg, get_node_id(inode), ff, &outarg);
+
+ err = fuse_simple_request(fm, &args);
+ if (err)
+ return err;
+
+ return fuse_statx_update(idmap, &outarg, inode, attr_version, stat);
+}
+
/*
* Helper function to initialize fuse_args for GETATTR operations
*/