summaryrefslogtreecommitdiff
path: root/fs/fuse/dev_uring.c
diff options
context:
space:
mode:
authorJoanne Koong <joannelkoong@gmail.com>2025-01-22 13:55:27 -0800
committerMiklos Szeredi <mszeredi@redhat.com>2025-03-31 14:59:25 +0200
commit0f6439f61a6e2ddc92b98362c6d1afc210f56a90 (patch)
treeafefdaeeee1cfddeff0017232c15c40752a76ef5 /fs/fuse/dev_uring.c
parenteef36cf6a7016cb5353d4b0a9dbdfbd52c4bd973 (diff)
fuse: add kernel-enforced timeout option for requests
There are situations where fuse servers can become unresponsive or stuck, for example if the server is deadlocked. Currently, there's no good way to detect if a server is stuck and needs to be killed manually. This commit adds an option for enforcing a timeout (in seconds) for requests where if the timeout elapses without the server responding to the request, the connection will be automatically aborted. Please note that these timeouts are not 100% precise. For example, the request may take roughly an extra FUSE_TIMEOUT_TIMER_FREQ seconds beyond the requested timeout due to internal implementation, in order to mitigate overhead. [SzM: Bump the API version number] Signed-off-by: Joanne Koong <joannelkoong@gmail.com> Reviewed-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Diffstat (limited to 'fs/fuse/dev_uring.c')
-rw-r--r--fs/fuse/dev_uring.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/fs/fuse/dev_uring.c b/fs/fuse/dev_uring.c
index add7273c8dc4..03062ee69b70 100644
--- a/fs/fuse/dev_uring.c
+++ b/fs/fuse/dev_uring.c
@@ -140,6 +140,33 @@ void fuse_uring_abort_end_requests(struct fuse_ring *ring)
}
}
+bool fuse_uring_request_expired(struct fuse_conn *fc)
+{
+ struct fuse_ring *ring = fc->ring;
+ struct fuse_ring_queue *queue;
+ int qid;
+
+ if (!ring)
+ return false;
+
+ for (qid = 0; qid < ring->nr_queues; qid++) {
+ queue = READ_ONCE(ring->queues[qid]);
+ if (!queue)
+ continue;
+
+ spin_lock(&queue->lock);
+ if (fuse_request_expired(fc, &queue->fuse_req_queue) ||
+ fuse_request_expired(fc, &queue->fuse_req_bg_queue) ||
+ fuse_fpq_processing_expired(fc, queue->fpq.processing)) {
+ spin_unlock(&queue->lock);
+ return true;
+ }
+ spin_unlock(&queue->lock);
+ }
+
+ return false;
+}
+
void fuse_uring_destruct(struct fuse_conn *fc)
{
struct fuse_ring *ring = fc->ring;