fuse_dev_do_read() and fuse_uring_args_to_ring() both pick the error for
a request that does not fit the server's buffer, and both special-case
FUSE_SETXATTR.  Move that choice into a helper so the two transports
cannot drift apart.

No functional change.

Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Xiang Mei <[email protected]>
Reviewed-by: Joanne Koong <[email protected]>
---
v4: introduce fuse_req_too_large_error as a helper
v5: add the explaining comment Joanne suggested; add her Reviewed-by

 fs/fuse/dev.c        |  5 +----
 fs/fuse/dev_uring.c  |  2 +-
 fs/fuse/fuse_dev_i.h | 13 +++++++++++++
 3 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 5763a7cd3b37..d290d2a215d5 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -1584,10 +1584,7 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, 
struct file *file,
 
        /* If request is too large, reply with an error and restart the read */
        if (nbytes < reqsize) {
-               req->out.h.error = -EIO;
-               /* SETXATTR is special, since it may contain too large data */
-               if (args->opcode == FUSE_SETXATTR)
-                       req->out.h.error = -E2BIG;
+               req->out.h.error = fuse_req_too_large_error(args);
                fuse_request_end(req);
                goto restart;
        }
diff --git a/fs/fuse/dev_uring.c b/fs/fuse/dev_uring.c
index 248e5a3e340e..46d948a047e4 100644
--- a/fs/fuse/dev_uring.c
+++ b/fs/fuse/dev_uring.c
@@ -729,7 +729,7 @@ static int fuse_uring_args_to_ring(struct fuse_ring *ring, 
struct fuse_req *req,
        }
 
        if (fuse_len_args(num_args, (struct fuse_arg *)in_args) > 
ent->payload_sz)
-               return args->opcode == FUSE_SETXATTR ? -E2BIG : -EIO;
+               return fuse_req_too_large_error(args);
 
        /* copy the payload */
        err = fuse_copy_args(&cs, num_args, args->in_pages,
diff --git a/fs/fuse/fuse_dev_i.h b/fs/fuse/fuse_dev_i.h
index 668c8391d61c..0bd5611e57c1 100644
--- a/fs/fuse/fuse_dev_i.h
+++ b/fs/fuse/fuse_dev_i.h
@@ -13,6 +13,8 @@
 #include <linux/workqueue.h>
 #include <linux/fs.h>
 
+#include "args.h"
+
 /* Ordinary requests have even IDs, while interrupts IDs are odd */
 #define FUSE_INT_REQ_BIT (1ULL << 0)
 #define FUSE_REQ_ID_STEP (1ULL << 1)
@@ -362,6 +364,17 @@ static inline struct fuse_dev *__fuse_get_dev(struct file 
*file)
        return fud;
 }
 
+/*
+ * A request whose payload size exceeds the transport buffer size is
+ * rejected with -EIO.  The exception is FUSE_SETXATTR, whose value may
+ * legitimately be oversized and is rejected with -E2BIG, matching the
+ * vfs setxattr path.
+ */
+static inline int fuse_req_too_large_error(struct fuse_args *args)
+{
+       return args->opcode == FUSE_SETXATTR ? -E2BIG : -EIO;
+}
+
 void fuse_iqueue_init(struct fuse_iqueue *fiq, const struct fuse_iqueue_ops 
*ops, void *priv);
 
 struct fuse_dev *fuse_get_dev(struct file *file);
-- 
2.43.0


Reply via email to