xref: /linux/fs/fuse/req_timeout.c (revision 56b4332e12a567eed708bb76eb69d43238a06183)
1f1434857SMiklos Szeredi // SPDX-License-Identifier: GPL-2.0-only
2f1434857SMiklos Szeredi 
3f1434857SMiklos Szeredi #include "dev.h"
4f1434857SMiklos Szeredi #include "sysctl.h"
5f1434857SMiklos Szeredi #include "fuse_i.h"
6f1434857SMiklos Szeredi #include "fuse_dev_i.h"
7f1434857SMiklos Szeredi #include "dev_uring_i.h"
8f1434857SMiklos Szeredi 
9f1434857SMiklos Szeredi /* Frequency (in seconds) of request timeout checks, if opted into */
10f1434857SMiklos Szeredi #define FUSE_TIMEOUT_TIMER_FREQ 15
11f1434857SMiklos Szeredi 
12f1434857SMiklos Szeredi /* Frequency (in jiffies) of request timeout checks, if opted into */
13f1434857SMiklos Szeredi static const unsigned long fuse_timeout_timer_freq =
14f1434857SMiklos Szeredi 	secs_to_jiffies(FUSE_TIMEOUT_TIMER_FREQ);
15f1434857SMiklos Szeredi 
16f1434857SMiklos Szeredi /*
17f1434857SMiklos Szeredi  * Default timeout (in seconds) for the server to reply to a request
18f1434857SMiklos Szeredi  * before the connection is aborted, if no timeout was specified on mount.
19f1434857SMiklos Szeredi  *
20f1434857SMiklos Szeredi  * Exported via sysctl
21f1434857SMiklos Szeredi  */
22f1434857SMiklos Szeredi unsigned int fuse_default_req_timeout;
23f1434857SMiklos Szeredi 
24f1434857SMiklos Szeredi /*
25f1434857SMiklos Szeredi  * Max timeout (in seconds) for the server to reply to a request before
26f1434857SMiklos Szeredi  * the connection is aborted.
27f1434857SMiklos Szeredi  *
28f1434857SMiklos Szeredi  * Exported via sysctl
29f1434857SMiklos Szeredi  */
30f1434857SMiklos Szeredi unsigned int fuse_max_req_timeout;
31f1434857SMiklos Szeredi 
32*56b4332eSMiklos Szeredi bool fuse_request_expired(struct fuse_chan *fch, struct list_head *list)
33f1434857SMiklos Szeredi {
34f1434857SMiklos Szeredi 	struct fuse_req *req;
35f1434857SMiklos Szeredi 
36f1434857SMiklos Szeredi 	req = list_first_entry_or_null(list, struct fuse_req, list);
37f1434857SMiklos Szeredi 	if (!req)
38f1434857SMiklos Szeredi 		return false;
39*56b4332eSMiklos Szeredi 	return time_is_before_jiffies(req->create_time + fch->timeout.req_timeout);
40f1434857SMiklos Szeredi }
41f1434857SMiklos Szeredi 
42*56b4332eSMiklos Szeredi static bool fuse_fpq_processing_expired(struct fuse_chan *fch, struct list_head *processing)
43f1434857SMiklos Szeredi {
44f1434857SMiklos Szeredi 	int i;
45f1434857SMiklos Szeredi 
46f1434857SMiklos Szeredi 	for (i = 0; i < FUSE_PQ_HASH_SIZE; i++)
47*56b4332eSMiklos Szeredi 		if (fuse_request_expired(fch, &processing[i]))
48f1434857SMiklos Szeredi 			return true;
49f1434857SMiklos Szeredi 
50f1434857SMiklos Szeredi 	return false;
51f1434857SMiklos Szeredi }
52f1434857SMiklos Szeredi 
53f1434857SMiklos Szeredi /*
54f1434857SMiklos Szeredi  * Check if any requests aren't being completed by the time the request timeout
55f1434857SMiklos Szeredi  * elapses. To do so, we:
56f1434857SMiklos Szeredi  * - check the fiq pending list
57f1434857SMiklos Szeredi  * - check the bg queue
58f1434857SMiklos Szeredi  * - check the fpq io and processing lists
59f1434857SMiklos Szeredi  *
60f1434857SMiklos Szeredi  * To make this fast, we only check against the head request on each list since
61f1434857SMiklos Szeredi  * these are generally queued in order of creation time (eg newer requests get
62f1434857SMiklos Szeredi  * queued to the tail). We might miss a few edge cases (eg requests transitioning
63f1434857SMiklos Szeredi  * between lists, re-sent requests at the head of the pending list having a
64f1434857SMiklos Szeredi  * later creation time than other requests on that list, etc.) but that is fine
65f1434857SMiklos Szeredi  * since if the request never gets fulfilled, it will eventually be caught.
66f1434857SMiklos Szeredi  */
67f1434857SMiklos Szeredi static void fuse_check_timeout(struct work_struct *work)
68f1434857SMiklos Szeredi {
69f1434857SMiklos Szeredi 	struct delayed_work *dwork = to_delayed_work(work);
70*56b4332eSMiklos Szeredi 	struct fuse_chan *fch = container_of(dwork, struct fuse_chan, timeout.work);
71*56b4332eSMiklos Szeredi 	struct fuse_iqueue *fiq = &fch->iq;
72f1434857SMiklos Szeredi 	struct fuse_dev *fud;
73f1434857SMiklos Szeredi 	struct fuse_pqueue *fpq;
74f1434857SMiklos Szeredi 	bool expired = false;
75f1434857SMiklos Szeredi 
76*56b4332eSMiklos Szeredi 	if (!atomic_read(&fch->num_waiting))
77f1434857SMiklos Szeredi 		goto out;
78f1434857SMiklos Szeredi 
79f1434857SMiklos Szeredi 	spin_lock(&fiq->lock);
80*56b4332eSMiklos Szeredi 	expired = fuse_request_expired(fch, &fiq->pending);
81f1434857SMiklos Szeredi 	spin_unlock(&fiq->lock);
82f1434857SMiklos Szeredi 	if (expired)
83f1434857SMiklos Szeredi 		goto abort_conn;
84f1434857SMiklos Szeredi 
85*56b4332eSMiklos Szeredi 	spin_lock(&fch->bg_lock);
86*56b4332eSMiklos Szeredi 	expired = fuse_request_expired(fch, &fch->bg_queue);
87*56b4332eSMiklos Szeredi 	spin_unlock(&fch->bg_lock);
88f1434857SMiklos Szeredi 	if (expired)
89f1434857SMiklos Szeredi 		goto abort_conn;
90f1434857SMiklos Szeredi 
91*56b4332eSMiklos Szeredi 	spin_lock(&fch->lock);
92*56b4332eSMiklos Szeredi 	if (!fch->connected) {
93*56b4332eSMiklos Szeredi 		spin_unlock(&fch->lock);
94f1434857SMiklos Szeredi 		return;
95f1434857SMiklos Szeredi 	}
96*56b4332eSMiklos Szeredi 	list_for_each_entry(fud, &fch->devices, entry) {
97f1434857SMiklos Szeredi 		fpq = &fud->pq;
98f1434857SMiklos Szeredi 		spin_lock(&fpq->lock);
99*56b4332eSMiklos Szeredi 		if (fuse_request_expired(fch, &fpq->io) ||
100*56b4332eSMiklos Szeredi 		    fuse_fpq_processing_expired(fch, fpq->processing)) {
101f1434857SMiklos Szeredi 			spin_unlock(&fpq->lock);
102*56b4332eSMiklos Szeredi 			spin_unlock(&fch->lock);
103f1434857SMiklos Szeredi 			goto abort_conn;
104f1434857SMiklos Szeredi 		}
105f1434857SMiklos Szeredi 
106f1434857SMiklos Szeredi 		spin_unlock(&fpq->lock);
107f1434857SMiklos Szeredi 	}
108*56b4332eSMiklos Szeredi 	spin_unlock(&fch->lock);
109f1434857SMiklos Szeredi 
110*56b4332eSMiklos Szeredi 	if (fuse_uring_request_expired(fch))
111f1434857SMiklos Szeredi 		goto abort_conn;
112f1434857SMiklos Szeredi 
113f1434857SMiklos Szeredi out:
114*56b4332eSMiklos Szeredi 	queue_delayed_work(system_percpu_wq, &fch->timeout.work,
115f1434857SMiklos Szeredi 			   fuse_timeout_timer_freq);
116f1434857SMiklos Szeredi 	return;
117f1434857SMiklos Szeredi 
118f1434857SMiklos Szeredi abort_conn:
119*56b4332eSMiklos Szeredi 	fuse_abort_conn(fch->conn);
120f1434857SMiklos Szeredi }
121f1434857SMiklos Szeredi 
122*56b4332eSMiklos Szeredi static void set_request_timeout(struct fuse_chan *fch, unsigned int timeout)
123f1434857SMiklos Szeredi {
124*56b4332eSMiklos Szeredi 	fch->timeout.req_timeout = secs_to_jiffies(timeout);
125*56b4332eSMiklos Szeredi 	INIT_DELAYED_WORK(&fch->timeout.work, fuse_check_timeout);
126*56b4332eSMiklos Szeredi 	queue_delayed_work(system_percpu_wq, &fch->timeout.work,
127f1434857SMiklos Szeredi 			   fuse_timeout_timer_freq);
128f1434857SMiklos Szeredi }
129f1434857SMiklos Szeredi 
130*56b4332eSMiklos Szeredi void fuse_init_server_timeout(struct fuse_chan *fch, unsigned int timeout)
131f1434857SMiklos Szeredi {
132f1434857SMiklos Szeredi 	if (!timeout && !fuse_max_req_timeout && !fuse_default_req_timeout)
133f1434857SMiklos Szeredi 		return;
134f1434857SMiklos Szeredi 
135f1434857SMiklos Szeredi 	if (!timeout)
136f1434857SMiklos Szeredi 		timeout = fuse_default_req_timeout;
137f1434857SMiklos Szeredi 
138f1434857SMiklos Szeredi 	if (fuse_max_req_timeout) {
139f1434857SMiklos Szeredi 		if (timeout)
140f1434857SMiklos Szeredi 			timeout = min(fuse_max_req_timeout, timeout);
141f1434857SMiklos Szeredi 		else
142f1434857SMiklos Szeredi 			timeout = fuse_max_req_timeout;
143f1434857SMiklos Szeredi 	}
144f1434857SMiklos Szeredi 
145f1434857SMiklos Szeredi 	timeout = max(FUSE_TIMEOUT_TIMER_FREQ, timeout);
146f1434857SMiklos Szeredi 
147*56b4332eSMiklos Szeredi 	set_request_timeout(fch, timeout);
148f1434857SMiklos Szeredi }
149f1434857SMiklos Szeredi 
150