diff options
| author | Joanne Koong <joannelkoong@gmail.com> | 2025-01-22 13:55:27 -0800 |
|---|---|---|
| committer | Miklos Szeredi <mszeredi@redhat.com> | 2025-03-31 14:59:25 +0200 |
| commit | 0f6439f61a6e2ddc92b98362c6d1afc210f56a90 (patch) | |
| tree | afefdaeeee1cfddeff0017232c15c40752a76ef5 /fs/fuse/dev_uring.c | |
| parent | eef36cf6a7016cb5353d4b0a9dbdfbd52c4bd973 (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.c | 27 |
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; |