From: Miklos Szeredi Date: Wed, 18 Mar 2026 17:01:27 +0000 (+0100) Subject: fuse: move request timeout to fuse_chan X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=56b4332e12a567eed708bb76eb69d43238a06183;p=thirdparty%2Fkernel%2Flinux.git fuse: move request timeout to fuse_chan Move: - timeout Signed-off-by: Miklos Szeredi --- diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 52f46efd85ba7..19b8cee3cff37 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -364,6 +364,7 @@ struct fuse_chan *fuse_chan_new(void) fch->initialized = 0; fch->blocked = 0; fch->connected = 1; + fch->timeout.req_timeout = 0; return fch; } @@ -2541,8 +2542,8 @@ void fuse_abort_conn(struct fuse_conn *fc) LIST_HEAD(to_end); unsigned int i; - if (fc->timeout.req_timeout) - cancel_delayed_work(&fc->timeout.work); + if (fc->chan->timeout.req_timeout) + cancel_delayed_work(&fc->chan->timeout.work); /* Background queuing checks fc->chan->connected under bg_lock */ spin_lock(&fc->chan->bg_lock); diff --git a/fs/fuse/dev.h b/fs/fuse/dev.h index 2630dab3ef562..df8a199b42d28 100644 --- a/fs/fuse/dev.h +++ b/fs/fuse/dev.h @@ -21,6 +21,6 @@ DEFINE_FREE(fuse_chan_free, struct fuse_chan *, if (_T) fuse_chan_free(_T)) void fuse_dev_install(struct fuse_dev *fud, struct fuse_conn *fc); void fuse_dev_put(struct fuse_dev *fud); -void fuse_init_server_timeout(struct fuse_conn *fc, unsigned int timeout); +void fuse_init_server_timeout(struct fuse_chan *fch, unsigned int timeout); #endif /* _FS_FUSE_DEV_H */ diff --git a/fs/fuse/dev_uring.c b/fs/fuse/dev_uring.c index 53bd5ae4b6860..da63fc8d0c59d 100644 --- a/fs/fuse/dev_uring.c +++ b/fs/fuse/dev_uring.c @@ -142,7 +142,7 @@ void fuse_uring_abort_end_requests(struct fuse_ring *ring) } } -static bool ent_list_request_expired(struct fuse_conn *fc, struct list_head *list) +static bool ent_list_request_expired(struct fuse_chan *fch, struct list_head *list) { struct fuse_ring_ent *ent; struct fuse_req *req; @@ -154,12 +154,12 @@ static bool ent_list_request_expired(struct fuse_conn *fc, struct list_head *lis req = ent->fuse_req; return time_is_before_jiffies(req->create_time + - fc->timeout.req_timeout); + fch->timeout.req_timeout); } -bool fuse_uring_request_expired(struct fuse_conn *fc) +bool fuse_uring_request_expired(struct fuse_chan *fch) { - struct fuse_ring *ring = fc->chan->ring; + struct fuse_ring *ring = fch->ring; struct fuse_ring_queue *queue; int qid; @@ -172,10 +172,10 @@ bool fuse_uring_request_expired(struct fuse_conn *fc) continue; spin_lock(&queue->lock); - if (fuse_request_expired(fc, &queue->fuse_req_queue) || - fuse_request_expired(fc, &queue->fuse_req_bg_queue) || - ent_list_request_expired(fc, &queue->ent_w_req_queue) || - ent_list_request_expired(fc, &queue->ent_in_userspace)) { + if (fuse_request_expired(fch, &queue->fuse_req_queue) || + fuse_request_expired(fch, &queue->fuse_req_bg_queue) || + ent_list_request_expired(fch, &queue->ent_w_req_queue) || + ent_list_request_expired(fch, &queue->ent_in_userspace)) { spin_unlock(&queue->lock); return true; } diff --git a/fs/fuse/dev_uring_i.h b/fs/fuse/dev_uring_i.h index 35604f1c7058a..c9fd92cb0f0da 100644 --- a/fs/fuse/dev_uring_i.h +++ b/fs/fuse/dev_uring_i.h @@ -144,7 +144,7 @@ int fuse_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags); void fuse_uring_queue_fuse_req(struct fuse_iqueue *fiq, struct fuse_req *req); bool fuse_uring_queue_bq_req(struct fuse_req *req); bool fuse_uring_remove_pending_req(struct fuse_req *req); -bool fuse_uring_request_expired(struct fuse_conn *fc); +bool fuse_uring_request_expired(struct fuse_chan *fch); static inline void fuse_uring_abort(struct fuse_conn *fc) { @@ -204,7 +204,7 @@ static inline bool fuse_uring_remove_pending_req(struct fuse_req *req) return false; } -static inline bool fuse_uring_request_expired(struct fuse_conn *fc) +static inline bool fuse_uring_request_expired(struct fuse_chan *fch) { return false; } diff --git a/fs/fuse/fuse_dev_i.h b/fs/fuse/fuse_dev_i.h index 188a21f1e141c..b512e484d3070 100644 --- a/fs/fuse/fuse_dev_i.h +++ b/fs/fuse/fuse_dev_i.h @@ -149,6 +149,15 @@ struct fuse_chan { /** uring connection information*/ struct fuse_ring *ring; #endif + + /** Only used if the connection opts into request timeouts */ + struct { + /* Worker for checking if any requests have timed out */ + struct delayed_work work; + + /* Request timeout (in jiffies). 0 = no timeout */ + unsigned int req_timeout; + } timeout; }; #define FUSE_PQ_HASH_BITS 8 @@ -261,7 +270,7 @@ void fuse_dev_queue_forget(struct fuse_iqueue *fiq, void fuse_dev_queue_interrupt(struct fuse_iqueue *fiq, struct fuse_req *req); bool fuse_remove_pending_req(struct fuse_req *req, spinlock_t *lock); -bool fuse_request_expired(struct fuse_conn *fc, struct list_head *list); +bool fuse_request_expired(struct fuse_chan *fch, struct list_head *list); /** * Assign a unique id to a fuse request diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 6343218563b19..7bc6c2054d1a5 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -816,15 +816,6 @@ struct fuse_conn { /** IDR for backing files ids */ struct idr backing_files_map; #endif - - /** Only used if the connection opts into request timeouts */ - struct { - /* Worker for checking if any requests have timed out */ - struct delayed_work work; - - /* Request timeout (in jiffies). 0 = no timeout */ - unsigned int req_timeout; - } timeout; }; /* diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 3d9ac14d636cb..772d9bec1362a 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -987,7 +987,6 @@ void fuse_conn_init(struct fuse_conn *fc, struct fuse_mount *fm, fc->max_pages = FUSE_DEFAULT_MAX_PAGES_PER_REQ; fc->max_pages_limit = fuse_max_pages_limit; fc->name_max = FUSE_NAME_LOW_MAX; - fc->timeout.req_timeout = 0; if (IS_ENABLED(CONFIG_FUSE_PASSTHROUGH)) fuse_backing_files_init(fc); @@ -1020,8 +1019,8 @@ void fuse_conn_put(struct fuse_conn *fc) if (IS_ENABLED(CONFIG_FUSE_DAX)) fuse_dax_conn_free(fc); - if (fc->timeout.req_timeout) - cancel_delayed_work_sync(&fc->timeout.work); + if (fc->chan->timeout.req_timeout) + cancel_delayed_work_sync(&fc->chan->timeout.work); cancel_work_sync(&fc->epoch_work); fuse_chan_release(fc->chan); put_pid_ns(fc->pid_ns); @@ -1423,7 +1422,7 @@ static void process_init_reply(struct fuse_mount *fm, struct fuse_args *args, fc->no_flock = 1; } - fuse_init_server_timeout(fc, timeout); + fuse_init_server_timeout(fc->chan, timeout); fm->sb->s_bdi->ra_pages = min(fm->sb->s_bdi->ra_pages, ra_pages); diff --git a/fs/fuse/req_timeout.c b/fs/fuse/req_timeout.c index 401d3545b0a88..ef464bebc0b6a 100644 --- a/fs/fuse/req_timeout.c +++ b/fs/fuse/req_timeout.c @@ -29,22 +29,22 @@ unsigned int fuse_default_req_timeout; */ unsigned int fuse_max_req_timeout; -bool fuse_request_expired(struct fuse_conn *fc, struct list_head *list) +bool fuse_request_expired(struct fuse_chan *fch, struct list_head *list) { struct fuse_req *req; req = list_first_entry_or_null(list, struct fuse_req, list); if (!req) return false; - return time_is_before_jiffies(req->create_time + fc->timeout.req_timeout); + return time_is_before_jiffies(req->create_time + fch->timeout.req_timeout); } -static bool fuse_fpq_processing_expired(struct fuse_conn *fc, struct list_head *processing) +static bool fuse_fpq_processing_expired(struct fuse_chan *fch, struct list_head *processing) { int i; for (i = 0; i < FUSE_PQ_HASH_SIZE; i++) - if (fuse_request_expired(fc, &processing[i])) + if (fuse_request_expired(fch, &processing[i])) return true; return false; @@ -67,68 +67,67 @@ static bool fuse_fpq_processing_expired(struct fuse_conn *fc, struct list_head * static void fuse_check_timeout(struct work_struct *work) { struct delayed_work *dwork = to_delayed_work(work); - struct fuse_conn *fc = container_of(dwork, struct fuse_conn, - timeout.work); - struct fuse_iqueue *fiq = &fc->chan->iq; + struct fuse_chan *fch = container_of(dwork, struct fuse_chan, timeout.work); + struct fuse_iqueue *fiq = &fch->iq; struct fuse_dev *fud; struct fuse_pqueue *fpq; bool expired = false; - if (!atomic_read(&fc->chan->num_waiting)) + if (!atomic_read(&fch->num_waiting)) goto out; spin_lock(&fiq->lock); - expired = fuse_request_expired(fc, &fiq->pending); + expired = fuse_request_expired(fch, &fiq->pending); spin_unlock(&fiq->lock); if (expired) goto abort_conn; - spin_lock(&fc->chan->bg_lock); - expired = fuse_request_expired(fc, &fc->chan->bg_queue); - spin_unlock(&fc->chan->bg_lock); + spin_lock(&fch->bg_lock); + expired = fuse_request_expired(fch, &fch->bg_queue); + spin_unlock(&fch->bg_lock); if (expired) goto abort_conn; - spin_lock(&fc->chan->lock); - if (!fc->chan->connected) { - spin_unlock(&fc->chan->lock); + spin_lock(&fch->lock); + if (!fch->connected) { + spin_unlock(&fch->lock); return; } - list_for_each_entry(fud, &fc->chan->devices, entry) { + list_for_each_entry(fud, &fch->devices, entry) { fpq = &fud->pq; spin_lock(&fpq->lock); - if (fuse_request_expired(fc, &fpq->io) || - fuse_fpq_processing_expired(fc, fpq->processing)) { + if (fuse_request_expired(fch, &fpq->io) || + fuse_fpq_processing_expired(fch, fpq->processing)) { spin_unlock(&fpq->lock); - spin_unlock(&fc->chan->lock); + spin_unlock(&fch->lock); goto abort_conn; } spin_unlock(&fpq->lock); } - spin_unlock(&fc->chan->lock); + spin_unlock(&fch->lock); - if (fuse_uring_request_expired(fc)) + if (fuse_uring_request_expired(fch)) goto abort_conn; out: - queue_delayed_work(system_percpu_wq, &fc->timeout.work, + queue_delayed_work(system_percpu_wq, &fch->timeout.work, fuse_timeout_timer_freq); return; abort_conn: - fuse_abort_conn(fc); + fuse_abort_conn(fch->conn); } -static void set_request_timeout(struct fuse_conn *fc, unsigned int timeout) +static void set_request_timeout(struct fuse_chan *fch, unsigned int timeout) { - fc->timeout.req_timeout = secs_to_jiffies(timeout); - INIT_DELAYED_WORK(&fc->timeout.work, fuse_check_timeout); - queue_delayed_work(system_percpu_wq, &fc->timeout.work, + fch->timeout.req_timeout = secs_to_jiffies(timeout); + INIT_DELAYED_WORK(&fch->timeout.work, fuse_check_timeout); + queue_delayed_work(system_percpu_wq, &fch->timeout.work, fuse_timeout_timer_freq); } -void fuse_init_server_timeout(struct fuse_conn *fc, unsigned int timeout) +void fuse_init_server_timeout(struct fuse_chan *fch, unsigned int timeout) { if (!timeout && !fuse_max_req_timeout && !fuse_default_req_timeout) return; @@ -145,6 +144,6 @@ void fuse_init_server_timeout(struct fuse_conn *fc, unsigned int timeout) timeout = max(FUSE_TIMEOUT_TIMER_FREQ, timeout); - set_request_timeout(fc, timeout); + set_request_timeout(fch, timeout); }