]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
fuse: capture the unique id of fuse commands being sent
authorDarrick J. Wong <djwong@kernel.org>
Tue, 16 Sep 2025 00:24:48 +0000 (17:24 -0700)
committerMiklos Szeredi <mszeredi@redhat.com>
Tue, 23 Sep 2025 09:32:17 +0000 (11:32 +0200)
The fuse_request_{send,end} tracepoints capture the value of
req->in.h.unique in the trace output.  It would be really nice if we
could use this to match a request to its response for debugging and
latency analysis, but the call to trace_fuse_request_send occurs before
the unique id has been set:

fuse_request_send:    connection 8388608 req 0 opcode 1 (FUSE_LOOKUP) len 107
fuse_request_end:     connection 8388608 req 6 len 16 error -2

(Notice that req moves from 0 to 6)

Move the callsites to trace_fuse_request_send to after the unique id has
been set by introducing a helper to do that for standard fuse_req
requests.  FUSE_FORGET requests are not covered by this because they
appear to be synthesized into the event stream without a fuse_req
object and are never replied to.

Requests that are aborted without ever having been submitted to the fuse
server retain the behavior that only the fuse_request_end tracepoint
shows up in the trace record, and with req==0.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
fs/fuse/dev.c
fs/fuse/dev_uring.c
fs/fuse/fuse_i.h
fs/fuse/virtio_fs.c

index 4229b38546bb8637bccdc6d31aa8e1d178c7d452..1941f93190e4bd440a8597cf3cf6c06020567304 100644 (file)
@@ -371,12 +371,32 @@ void fuse_dev_queue_interrupt(struct fuse_iqueue *fiq, struct fuse_req *req)
        }
 }
 
+static inline void fuse_request_assign_unique_locked(struct fuse_iqueue *fiq,
+                                                    struct fuse_req *req)
+{
+       if (req->in.h.opcode != FUSE_NOTIFY_REPLY)
+               req->in.h.unique = fuse_get_unique_locked(fiq);
+
+       /* tracepoint captures in.h.unique and in.h.len */
+       trace_fuse_request_send(req);
+}
+
+inline void fuse_request_assign_unique(struct fuse_iqueue *fiq,
+                                      struct fuse_req *req)
+{
+       if (req->in.h.opcode != FUSE_NOTIFY_REPLY)
+               req->in.h.unique = fuse_get_unique(fiq);
+
+       /* tracepoint captures in.h.unique and in.h.len */
+       trace_fuse_request_send(req);
+}
+EXPORT_SYMBOL_GPL(fuse_request_assign_unique);
+
 static void fuse_dev_queue_req(struct fuse_iqueue *fiq, struct fuse_req *req)
 {
        spin_lock(&fiq->lock);
        if (fiq->connected) {
-               if (req->in.h.opcode != FUSE_NOTIFY_REPLY)
-                       req->in.h.unique = fuse_get_unique_locked(fiq);
+               fuse_request_assign_unique_locked(fiq, req);
                list_add_tail(&req->list, &fiq->pending);
                fuse_dev_wake_and_unlock(fiq);
        } else {
@@ -399,7 +419,6 @@ static void fuse_send_one(struct fuse_iqueue *fiq, struct fuse_req *req)
        req->in.h.len = sizeof(struct fuse_in_header) +
                fuse_len_args(req->args->in_numargs,
                              (struct fuse_arg *) req->args->in_args);
-       trace_fuse_request_send(req);
        fiq->ops->send_req(fiq, req);
 }
 
@@ -689,10 +708,10 @@ static bool fuse_request_queue_background_uring(struct fuse_conn *fc,
 {
        struct fuse_iqueue *fiq = &fc->iq;
 
-       req->in.h.unique = fuse_get_unique(fiq);
        req->in.h.len = sizeof(struct fuse_in_header) +
                fuse_len_args(req->args->in_numargs,
                              (struct fuse_arg *) req->args->in_args);
+       fuse_request_assign_unique(fiq, req);
 
        return fuse_uring_queue_bq_req(req);
 }
index bef38ed78249b055dd9852b2d909676f8a15fec0..6862fe6b7799a718154d2431fcda68ae15c4e597 100644 (file)
@@ -7,6 +7,7 @@
 #include "fuse_i.h"
 #include "dev_uring_i.h"
 #include "fuse_dev_i.h"
+#include "fuse_trace.h"
 
 #include <linux/fs.h>
 #include <linux/io_uring/cmd.h>
@@ -1268,8 +1269,7 @@ void fuse_uring_queue_fuse_req(struct fuse_iqueue *fiq, struct fuse_req *req)
        if (!queue)
                goto err;
 
-       if (req->in.h.opcode != FUSE_NOTIFY_REPLY)
-               req->in.h.unique = fuse_get_unique(fiq);
+       fuse_request_assign_unique(fiq, req);
 
        spin_lock(&queue->lock);
        err = -ENOTCONN;
index fb6604120b53d9259327e1cf47a93c3b4a78ecf5..48ec7812a1e91386bb35d0cea0dd9d83ba91b5e6 100644 (file)
@@ -1260,6 +1260,11 @@ static inline ssize_t fuse_simple_idmap_request(struct mnt_idmap *idmap,
 int fuse_simple_background(struct fuse_mount *fm, struct fuse_args *args,
                           gfp_t gfp_flags);
 
+/**
+ * Assign a unique id to a fuse request
+ */
+void fuse_request_assign_unique(struct fuse_iqueue *fiq, struct fuse_req *req);
+
 /**
  * End a finished request
  */
index c3a39061363e5b3f567e4d4850b9eb6b6fbc5d9a..7164961cb053fa7e8ac4f742790c35e215fb74bd 100644 (file)
@@ -1479,8 +1479,7 @@ static void virtio_fs_send_req(struct fuse_iqueue *fiq, struct fuse_req *req)
        struct virtio_fs_vq *fsvq;
        int ret;
 
-       if (req->in.h.opcode != FUSE_NOTIFY_REPLY)
-               req->in.h.unique = fuse_get_unique(fiq);
+       fuse_request_assign_unique(fiq, req);
 
        clear_bit(FR_PENDING, &req->flags);