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