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