xref: /openbmc/linux/fs/fuse/dev.c (revision 334f485d)
1334f485dSMiklos Szeredi /*
2334f485dSMiklos Szeredi   FUSE: Filesystem in Userspace
3334f485dSMiklos Szeredi   Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
4334f485dSMiklos Szeredi 
5334f485dSMiklos Szeredi   This program can be distributed under the terms of the GNU GPL.
6334f485dSMiklos Szeredi   See the file COPYING.
7334f485dSMiklos Szeredi */
8334f485dSMiklos Szeredi 
9334f485dSMiklos Szeredi #include "fuse_i.h"
10334f485dSMiklos Szeredi 
11334f485dSMiklos Szeredi #include <linux/init.h>
12334f485dSMiklos Szeredi #include <linux/module.h>
13334f485dSMiklos Szeredi #include <linux/poll.h>
14334f485dSMiklos Szeredi #include <linux/uio.h>
15334f485dSMiklos Szeredi #include <linux/miscdevice.h>
16334f485dSMiklos Szeredi #include <linux/pagemap.h>
17334f485dSMiklos Szeredi #include <linux/file.h>
18334f485dSMiklos Szeredi #include <linux/slab.h>
19334f485dSMiklos Szeredi 
20334f485dSMiklos Szeredi MODULE_ALIAS_MISCDEV(FUSE_MINOR);
21334f485dSMiklos Szeredi 
22334f485dSMiklos Szeredi static kmem_cache_t *fuse_req_cachep;
23334f485dSMiklos Szeredi 
24334f485dSMiklos Szeredi static inline struct fuse_conn *fuse_get_conn(struct file *file)
25334f485dSMiklos Szeredi {
26334f485dSMiklos Szeredi 	struct fuse_conn *fc;
27334f485dSMiklos Szeredi 	spin_lock(&fuse_lock);
28334f485dSMiklos Szeredi 	fc = file->private_data;
29334f485dSMiklos Szeredi 	if (fc && !fc->sb)
30334f485dSMiklos Szeredi 		fc = NULL;
31334f485dSMiklos Szeredi 	spin_unlock(&fuse_lock);
32334f485dSMiklos Szeredi 	return fc;
33334f485dSMiklos Szeredi }
34334f485dSMiklos Szeredi 
35334f485dSMiklos Szeredi static inline void fuse_request_init(struct fuse_req *req)
36334f485dSMiklos Szeredi {
37334f485dSMiklos Szeredi 	memset(req, 0, sizeof(*req));
38334f485dSMiklos Szeredi 	INIT_LIST_HEAD(&req->list);
39334f485dSMiklos Szeredi 	init_waitqueue_head(&req->waitq);
40334f485dSMiklos Szeredi 	atomic_set(&req->count, 1);
41334f485dSMiklos Szeredi }
42334f485dSMiklos Szeredi 
43334f485dSMiklos Szeredi struct fuse_req *fuse_request_alloc(void)
44334f485dSMiklos Szeredi {
45334f485dSMiklos Szeredi 	struct fuse_req *req = kmem_cache_alloc(fuse_req_cachep, SLAB_KERNEL);
46334f485dSMiklos Szeredi 	if (req)
47334f485dSMiklos Szeredi 		fuse_request_init(req);
48334f485dSMiklos Szeredi 	return req;
49334f485dSMiklos Szeredi }
50334f485dSMiklos Szeredi 
51334f485dSMiklos Szeredi void fuse_request_free(struct fuse_req *req)
52334f485dSMiklos Szeredi {
53334f485dSMiklos Szeredi 	kmem_cache_free(fuse_req_cachep, req);
54334f485dSMiklos Szeredi }
55334f485dSMiklos Szeredi 
56334f485dSMiklos Szeredi static inline void block_sigs(sigset_t *oldset)
57334f485dSMiklos Szeredi {
58334f485dSMiklos Szeredi 	sigset_t mask;
59334f485dSMiklos Szeredi 
60334f485dSMiklos Szeredi 	siginitsetinv(&mask, sigmask(SIGKILL));
61334f485dSMiklos Szeredi 	sigprocmask(SIG_BLOCK, &mask, oldset);
62334f485dSMiklos Szeredi }
63334f485dSMiklos Szeredi 
64334f485dSMiklos Szeredi static inline void restore_sigs(sigset_t *oldset)
65334f485dSMiklos Szeredi {
66334f485dSMiklos Szeredi 	sigprocmask(SIG_SETMASK, oldset, NULL);
67334f485dSMiklos Szeredi }
68334f485dSMiklos Szeredi 
69334f485dSMiklos Szeredi void fuse_reset_request(struct fuse_req *req)
70334f485dSMiklos Szeredi {
71334f485dSMiklos Szeredi 	int preallocated = req->preallocated;
72334f485dSMiklos Szeredi 	BUG_ON(atomic_read(&req->count) != 1);
73334f485dSMiklos Szeredi 	fuse_request_init(req);
74334f485dSMiklos Szeredi 	req->preallocated = preallocated;
75334f485dSMiklos Szeredi }
76334f485dSMiklos Szeredi 
77334f485dSMiklos Szeredi static void __fuse_get_request(struct fuse_req *req)
78334f485dSMiklos Szeredi {
79334f485dSMiklos Szeredi 	atomic_inc(&req->count);
80334f485dSMiklos Szeredi }
81334f485dSMiklos Szeredi 
82334f485dSMiklos Szeredi /* Must be called with > 1 refcount */
83334f485dSMiklos Szeredi static void __fuse_put_request(struct fuse_req *req)
84334f485dSMiklos Szeredi {
85334f485dSMiklos Szeredi 	BUG_ON(atomic_read(&req->count) < 2);
86334f485dSMiklos Szeredi 	atomic_dec(&req->count);
87334f485dSMiklos Szeredi }
88334f485dSMiklos Szeredi 
89334f485dSMiklos Szeredi static struct fuse_req *do_get_request(struct fuse_conn *fc)
90334f485dSMiklos Szeredi {
91334f485dSMiklos Szeredi 	struct fuse_req *req;
92334f485dSMiklos Szeredi 
93334f485dSMiklos Szeredi 	spin_lock(&fuse_lock);
94334f485dSMiklos Szeredi 	BUG_ON(list_empty(&fc->unused_list));
95334f485dSMiklos Szeredi 	req = list_entry(fc->unused_list.next, struct fuse_req, list);
96334f485dSMiklos Szeredi 	list_del_init(&req->list);
97334f485dSMiklos Szeredi 	spin_unlock(&fuse_lock);
98334f485dSMiklos Szeredi 	fuse_request_init(req);
99334f485dSMiklos Szeredi 	req->preallocated = 1;
100334f485dSMiklos Szeredi 	req->in.h.uid = current->fsuid;
101334f485dSMiklos Szeredi 	req->in.h.gid = current->fsgid;
102334f485dSMiklos Szeredi 	req->in.h.pid = current->pid;
103334f485dSMiklos Szeredi 	return req;
104334f485dSMiklos Szeredi }
105334f485dSMiklos Szeredi 
106334f485dSMiklos Szeredi struct fuse_req *fuse_get_request(struct fuse_conn *fc)
107334f485dSMiklos Szeredi {
108334f485dSMiklos Szeredi 	if (down_interruptible(&fc->outstanding_sem))
109334f485dSMiklos Szeredi 		return NULL;
110334f485dSMiklos Szeredi 	return do_get_request(fc);
111334f485dSMiklos Szeredi }
112334f485dSMiklos Szeredi 
113334f485dSMiklos Szeredi /*
114334f485dSMiklos Szeredi  * Non-interruptible version of the above function is for operations
115334f485dSMiklos Szeredi  * which can't legally return -ERESTART{SYS,NOINTR}.  This can still
116334f485dSMiklos Szeredi  * return NULL, but only in case the signal is SIGKILL.
117334f485dSMiklos Szeredi  */
118334f485dSMiklos Szeredi struct fuse_req *fuse_get_request_nonint(struct fuse_conn *fc)
119334f485dSMiklos Szeredi {
120334f485dSMiklos Szeredi 	int intr;
121334f485dSMiklos Szeredi 	sigset_t oldset;
122334f485dSMiklos Szeredi 
123334f485dSMiklos Szeredi 	block_sigs(&oldset);
124334f485dSMiklos Szeredi 	intr = down_interruptible(&fc->outstanding_sem);
125334f485dSMiklos Szeredi 	restore_sigs(&oldset);
126334f485dSMiklos Szeredi 	return intr ? NULL : do_get_request(fc);
127334f485dSMiklos Szeredi }
128334f485dSMiklos Szeredi 
129334f485dSMiklos Szeredi static void fuse_putback_request(struct fuse_conn *fc, struct fuse_req *req)
130334f485dSMiklos Szeredi {
131334f485dSMiklos Szeredi 	spin_lock(&fuse_lock);
132334f485dSMiklos Szeredi 	if (req->preallocated)
133334f485dSMiklos Szeredi 		list_add(&req->list, &fc->unused_list);
134334f485dSMiklos Szeredi 	else
135334f485dSMiklos Szeredi 		fuse_request_free(req);
136334f485dSMiklos Szeredi 
137334f485dSMiklos Szeredi 	/* If we are in debt decrease that first */
138334f485dSMiklos Szeredi 	if (fc->outstanding_debt)
139334f485dSMiklos Szeredi 		fc->outstanding_debt--;
140334f485dSMiklos Szeredi 	else
141334f485dSMiklos Szeredi 		up(&fc->outstanding_sem);
142334f485dSMiklos Szeredi 	spin_unlock(&fuse_lock);
143334f485dSMiklos Szeredi }
144334f485dSMiklos Szeredi 
145334f485dSMiklos Szeredi void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req)
146334f485dSMiklos Szeredi {
147334f485dSMiklos Szeredi 	if (atomic_dec_and_test(&req->count))
148334f485dSMiklos Szeredi 		fuse_putback_request(fc, req);
149334f485dSMiklos Szeredi }
150334f485dSMiklos Szeredi 
151334f485dSMiklos Szeredi /*
152334f485dSMiklos Szeredi  * This function is called when a request is finished.  Either a reply
153334f485dSMiklos Szeredi  * has arrived or it was interrupted (and not yet sent) or some error
154334f485dSMiklos Szeredi  * occured during communication with userspace, or the device file was
155334f485dSMiklos Szeredi  * closed.  It decreases the referece count for the request.  In case
156334f485dSMiklos Szeredi  * of a background request the referece to the stored objects are
157334f485dSMiklos Szeredi  * released.  The requester thread is woken up (if still waiting), and
158334f485dSMiklos Szeredi  * finally the request is either freed or put on the unused_list
159334f485dSMiklos Szeredi  *
160334f485dSMiklos Szeredi  * Called with fuse_lock, unlocks it
161334f485dSMiklos Szeredi  */
162334f485dSMiklos Szeredi static void request_end(struct fuse_conn *fc, struct fuse_req *req)
163334f485dSMiklos Szeredi {
164334f485dSMiklos Szeredi 	int putback;
165334f485dSMiklos Szeredi 	req->finished = 1;
166334f485dSMiklos Szeredi 	putback = atomic_dec_and_test(&req->count);
167334f485dSMiklos Szeredi 	spin_unlock(&fuse_lock);
168334f485dSMiklos Szeredi 	if (req->background) {
169334f485dSMiklos Szeredi 		if (req->inode)
170334f485dSMiklos Szeredi 			iput(req->inode);
171334f485dSMiklos Szeredi 		if (req->inode2)
172334f485dSMiklos Szeredi 			iput(req->inode2);
173334f485dSMiklos Szeredi 		if (req->file)
174334f485dSMiklos Szeredi 			fput(req->file);
175334f485dSMiklos Szeredi 	}
176334f485dSMiklos Szeredi 	wake_up(&req->waitq);
177334f485dSMiklos Szeredi 	if (req->in.h.opcode == FUSE_INIT) {
178334f485dSMiklos Szeredi 		int i;
179334f485dSMiklos Szeredi 
180334f485dSMiklos Szeredi 		if (req->misc.init_in_out.major != FUSE_KERNEL_VERSION)
181334f485dSMiklos Szeredi 			fc->conn_error = 1;
182334f485dSMiklos Szeredi 
183334f485dSMiklos Szeredi 		/* After INIT reply is received other requests can go
184334f485dSMiklos Szeredi 		   out.  So do (FUSE_MAX_OUTSTANDING - 1) number of
185334f485dSMiklos Szeredi 		   up()s on outstanding_sem.  The last up() is done in
186334f485dSMiklos Szeredi 		   fuse_putback_request() */
187334f485dSMiklos Szeredi 		for (i = 1; i < FUSE_MAX_OUTSTANDING; i++)
188334f485dSMiklos Szeredi 			up(&fc->outstanding_sem);
189334f485dSMiklos Szeredi 	}
190334f485dSMiklos Szeredi 	if (putback)
191334f485dSMiklos Szeredi 		fuse_putback_request(fc, req);
192334f485dSMiklos Szeredi }
193334f485dSMiklos Szeredi 
194334f485dSMiklos Szeredi static void background_request(struct fuse_req *req)
195334f485dSMiklos Szeredi {
196334f485dSMiklos Szeredi 	/* Need to get hold of the inode(s) and/or file used in the
197334f485dSMiklos Szeredi 	   request, so FORGET and RELEASE are not sent too early */
198334f485dSMiklos Szeredi 	req->background = 1;
199334f485dSMiklos Szeredi 	if (req->inode)
200334f485dSMiklos Szeredi 		req->inode = igrab(req->inode);
201334f485dSMiklos Szeredi 	if (req->inode2)
202334f485dSMiklos Szeredi 		req->inode2 = igrab(req->inode2);
203334f485dSMiklos Szeredi 	if (req->file)
204334f485dSMiklos Szeredi 		get_file(req->file);
205334f485dSMiklos Szeredi }
206334f485dSMiklos Szeredi 
207334f485dSMiklos Szeredi static int request_wait_answer_nonint(struct fuse_req *req)
208334f485dSMiklos Szeredi {
209334f485dSMiklos Szeredi 	int err;
210334f485dSMiklos Szeredi 	sigset_t oldset;
211334f485dSMiklos Szeredi 	block_sigs(&oldset);
212334f485dSMiklos Szeredi 	err = wait_event_interruptible(req->waitq, req->finished);
213334f485dSMiklos Szeredi 	restore_sigs(&oldset);
214334f485dSMiklos Szeredi 	return err;
215334f485dSMiklos Szeredi }
216334f485dSMiklos Szeredi 
217334f485dSMiklos Szeredi /* Called with fuse_lock held.  Releases, and then reacquires it. */
218334f485dSMiklos Szeredi static void request_wait_answer(struct fuse_req *req, int interruptible)
219334f485dSMiklos Szeredi {
220334f485dSMiklos Szeredi 	int intr;
221334f485dSMiklos Szeredi 
222334f485dSMiklos Szeredi 	spin_unlock(&fuse_lock);
223334f485dSMiklos Szeredi 	if (interruptible)
224334f485dSMiklos Szeredi 		intr = wait_event_interruptible(req->waitq, req->finished);
225334f485dSMiklos Szeredi 	else
226334f485dSMiklos Szeredi 		intr = request_wait_answer_nonint(req);
227334f485dSMiklos Szeredi 	spin_lock(&fuse_lock);
228334f485dSMiklos Szeredi 	if (intr && interruptible && req->sent) {
229334f485dSMiklos Szeredi 		/* If request is already in userspace, only allow KILL
230334f485dSMiklos Szeredi 		   signal to interrupt */
231334f485dSMiklos Szeredi 		spin_unlock(&fuse_lock);
232334f485dSMiklos Szeredi 		intr = request_wait_answer_nonint(req);
233334f485dSMiklos Szeredi 		spin_lock(&fuse_lock);
234334f485dSMiklos Szeredi 	}
235334f485dSMiklos Szeredi 	if (!intr)
236334f485dSMiklos Szeredi 		return;
237334f485dSMiklos Szeredi 
238334f485dSMiklos Szeredi 	if (!interruptible || req->sent)
239334f485dSMiklos Szeredi 		req->out.h.error = -EINTR;
240334f485dSMiklos Szeredi 	else
241334f485dSMiklos Szeredi 		req->out.h.error = -ERESTARTNOINTR;
242334f485dSMiklos Szeredi 
243334f485dSMiklos Szeredi 	req->interrupted = 1;
244334f485dSMiklos Szeredi 	if (req->locked) {
245334f485dSMiklos Szeredi 		/* This is uninterruptible sleep, because data is
246334f485dSMiklos Szeredi 		   being copied to/from the buffers of req.  During
247334f485dSMiklos Szeredi 		   locked state, there mustn't be any filesystem
248334f485dSMiklos Szeredi 		   operation (e.g. page fault), since that could lead
249334f485dSMiklos Szeredi 		   to deadlock */
250334f485dSMiklos Szeredi 		spin_unlock(&fuse_lock);
251334f485dSMiklos Szeredi 		wait_event(req->waitq, !req->locked);
252334f485dSMiklos Szeredi 		spin_lock(&fuse_lock);
253334f485dSMiklos Szeredi 	}
254334f485dSMiklos Szeredi 	if (!req->sent && !list_empty(&req->list)) {
255334f485dSMiklos Szeredi 		list_del(&req->list);
256334f485dSMiklos Szeredi 		__fuse_put_request(req);
257334f485dSMiklos Szeredi 	} else if (!req->finished && req->sent)
258334f485dSMiklos Szeredi 		background_request(req);
259334f485dSMiklos Szeredi }
260334f485dSMiklos Szeredi 
261334f485dSMiklos Szeredi static unsigned len_args(unsigned numargs, struct fuse_arg *args)
262334f485dSMiklos Szeredi {
263334f485dSMiklos Szeredi 	unsigned nbytes = 0;
264334f485dSMiklos Szeredi 	unsigned i;
265334f485dSMiklos Szeredi 
266334f485dSMiklos Szeredi 	for (i = 0; i < numargs; i++)
267334f485dSMiklos Szeredi 		nbytes += args[i].size;
268334f485dSMiklos Szeredi 
269334f485dSMiklos Szeredi 	return nbytes;
270334f485dSMiklos Szeredi }
271334f485dSMiklos Szeredi 
272334f485dSMiklos Szeredi static void queue_request(struct fuse_conn *fc, struct fuse_req *req)
273334f485dSMiklos Szeredi {
274334f485dSMiklos Szeredi 	fc->reqctr++;
275334f485dSMiklos Szeredi 	/* zero is special */
276334f485dSMiklos Szeredi 	if (fc->reqctr == 0)
277334f485dSMiklos Szeredi 		fc->reqctr = 1;
278334f485dSMiklos Szeredi 	req->in.h.unique = fc->reqctr;
279334f485dSMiklos Szeredi 	req->in.h.len = sizeof(struct fuse_in_header) +
280334f485dSMiklos Szeredi 		len_args(req->in.numargs, (struct fuse_arg *) req->in.args);
281334f485dSMiklos Szeredi 	if (!req->preallocated) {
282334f485dSMiklos Szeredi 		/* If request is not preallocated (either FORGET or
283334f485dSMiklos Szeredi 		   RELEASE), then still decrease outstanding_sem, so
284334f485dSMiklos Szeredi 		   user can't open infinite number of files while not
285334f485dSMiklos Szeredi 		   processing the RELEASE requests.  However for
286334f485dSMiklos Szeredi 		   efficiency do it without blocking, so if down()
287334f485dSMiklos Szeredi 		   would block, just increase the debt instead */
288334f485dSMiklos Szeredi 		if (down_trylock(&fc->outstanding_sem))
289334f485dSMiklos Szeredi 			fc->outstanding_debt++;
290334f485dSMiklos Szeredi 	}
291334f485dSMiklos Szeredi 	list_add_tail(&req->list, &fc->pending);
292334f485dSMiklos Szeredi 	wake_up(&fc->waitq);
293334f485dSMiklos Szeredi }
294334f485dSMiklos Szeredi 
295334f485dSMiklos Szeredi static void request_send_wait(struct fuse_conn *fc, struct fuse_req *req,
296334f485dSMiklos Szeredi 			      int interruptible)
297334f485dSMiklos Szeredi {
298334f485dSMiklos Szeredi 	req->isreply = 1;
299334f485dSMiklos Szeredi 	spin_lock(&fuse_lock);
300334f485dSMiklos Szeredi 	if (!fc->file)
301334f485dSMiklos Szeredi 		req->out.h.error = -ENOTCONN;
302334f485dSMiklos Szeredi 	else if (fc->conn_error)
303334f485dSMiklos Szeredi 		req->out.h.error = -ECONNREFUSED;
304334f485dSMiklos Szeredi 	else {
305334f485dSMiklos Szeredi 		queue_request(fc, req);
306334f485dSMiklos Szeredi 		/* acquire extra reference, since request is still needed
307334f485dSMiklos Szeredi 		   after request_end() */
308334f485dSMiklos Szeredi 		__fuse_get_request(req);
309334f485dSMiklos Szeredi 
310334f485dSMiklos Szeredi 		request_wait_answer(req, interruptible);
311334f485dSMiklos Szeredi 	}
312334f485dSMiklos Szeredi 	spin_unlock(&fuse_lock);
313334f485dSMiklos Szeredi }
314334f485dSMiklos Szeredi 
315334f485dSMiklos Szeredi void request_send(struct fuse_conn *fc, struct fuse_req *req)
316334f485dSMiklos Szeredi {
317334f485dSMiklos Szeredi 	request_send_wait(fc, req, 1);
318334f485dSMiklos Szeredi }
319334f485dSMiklos Szeredi 
320334f485dSMiklos Szeredi /*
321334f485dSMiklos Szeredi  * Non-interruptible version of the above function is for operations
322334f485dSMiklos Szeredi  * which can't legally return -ERESTART{SYS,NOINTR}.  This can still
323334f485dSMiklos Szeredi  * be interrupted but only with SIGKILL.
324334f485dSMiklos Szeredi  */
325334f485dSMiklos Szeredi void request_send_nonint(struct fuse_conn *fc, struct fuse_req *req)
326334f485dSMiklos Szeredi {
327334f485dSMiklos Szeredi 	request_send_wait(fc, req, 0);
328334f485dSMiklos Szeredi }
329334f485dSMiklos Szeredi 
330334f485dSMiklos Szeredi static void request_send_nowait(struct fuse_conn *fc, struct fuse_req *req)
331334f485dSMiklos Szeredi {
332334f485dSMiklos Szeredi 	spin_lock(&fuse_lock);
333334f485dSMiklos Szeredi 	if (fc->file) {
334334f485dSMiklos Szeredi 		queue_request(fc, req);
335334f485dSMiklos Szeredi 		spin_unlock(&fuse_lock);
336334f485dSMiklos Szeredi 	} else {
337334f485dSMiklos Szeredi 		req->out.h.error = -ENOTCONN;
338334f485dSMiklos Szeredi 		request_end(fc, req);
339334f485dSMiklos Szeredi 	}
340334f485dSMiklos Szeredi }
341334f485dSMiklos Szeredi 
342334f485dSMiklos Szeredi void request_send_noreply(struct fuse_conn *fc, struct fuse_req *req)
343334f485dSMiklos Szeredi {
344334f485dSMiklos Szeredi 	req->isreply = 0;
345334f485dSMiklos Szeredi 	request_send_nowait(fc, req);
346334f485dSMiklos Szeredi }
347334f485dSMiklos Szeredi 
348334f485dSMiklos Szeredi void request_send_background(struct fuse_conn *fc, struct fuse_req *req)
349334f485dSMiklos Szeredi {
350334f485dSMiklos Szeredi 	req->isreply = 1;
351334f485dSMiklos Szeredi 	background_request(req);
352334f485dSMiklos Szeredi 	request_send_nowait(fc, req);
353334f485dSMiklos Szeredi }
354334f485dSMiklos Szeredi 
355334f485dSMiklos Szeredi void fuse_send_init(struct fuse_conn *fc)
356334f485dSMiklos Szeredi {
357334f485dSMiklos Szeredi 	/* This is called from fuse_read_super() so there's guaranteed
358334f485dSMiklos Szeredi 	   to be a request available */
359334f485dSMiklos Szeredi 	struct fuse_req *req = do_get_request(fc);
360334f485dSMiklos Szeredi 	struct fuse_init_in_out *arg = &req->misc.init_in_out;
361334f485dSMiklos Szeredi 	arg->major = FUSE_KERNEL_VERSION;
362334f485dSMiklos Szeredi 	arg->minor = FUSE_KERNEL_MINOR_VERSION;
363334f485dSMiklos Szeredi 	req->in.h.opcode = FUSE_INIT;
364334f485dSMiklos Szeredi 	req->in.numargs = 1;
365334f485dSMiklos Szeredi 	req->in.args[0].size = sizeof(*arg);
366334f485dSMiklos Szeredi 	req->in.args[0].value = arg;
367334f485dSMiklos Szeredi 	req->out.numargs = 1;
368334f485dSMiklos Szeredi 	req->out.args[0].size = sizeof(*arg);
369334f485dSMiklos Szeredi 	req->out.args[0].value = arg;
370334f485dSMiklos Szeredi 	request_send_background(fc, req);
371334f485dSMiklos Szeredi }
372334f485dSMiklos Szeredi 
373334f485dSMiklos Szeredi /*
374334f485dSMiklos Szeredi  * Lock the request.  Up to the next unlock_request() there mustn't be
375334f485dSMiklos Szeredi  * anything that could cause a page-fault.  If the request was already
376334f485dSMiklos Szeredi  * interrupted bail out.
377334f485dSMiklos Szeredi  */
378334f485dSMiklos Szeredi static inline int lock_request(struct fuse_req *req)
379334f485dSMiklos Szeredi {
380334f485dSMiklos Szeredi 	int err = 0;
381334f485dSMiklos Szeredi 	if (req) {
382334f485dSMiklos Szeredi 		spin_lock(&fuse_lock);
383334f485dSMiklos Szeredi 		if (req->interrupted)
384334f485dSMiklos Szeredi 			err = -ENOENT;
385334f485dSMiklos Szeredi 		else
386334f485dSMiklos Szeredi 			req->locked = 1;
387334f485dSMiklos Szeredi 		spin_unlock(&fuse_lock);
388334f485dSMiklos Szeredi 	}
389334f485dSMiklos Szeredi 	return err;
390334f485dSMiklos Szeredi }
391334f485dSMiklos Szeredi 
392334f485dSMiklos Szeredi /*
393334f485dSMiklos Szeredi  * Unlock request.  If it was interrupted during being locked, the
394334f485dSMiklos Szeredi  * requester thread is currently waiting for it to be unlocked, so
395334f485dSMiklos Szeredi  * wake it up.
396334f485dSMiklos Szeredi  */
397334f485dSMiklos Szeredi static inline void unlock_request(struct fuse_req *req)
398334f485dSMiklos Szeredi {
399334f485dSMiklos Szeredi 	if (req) {
400334f485dSMiklos Szeredi 		spin_lock(&fuse_lock);
401334f485dSMiklos Szeredi 		req->locked = 0;
402334f485dSMiklos Szeredi 		if (req->interrupted)
403334f485dSMiklos Szeredi 			wake_up(&req->waitq);
404334f485dSMiklos Szeredi 		spin_unlock(&fuse_lock);
405334f485dSMiklos Szeredi 	}
406334f485dSMiklos Szeredi }
407334f485dSMiklos Szeredi 
408334f485dSMiklos Szeredi struct fuse_copy_state {
409334f485dSMiklos Szeredi 	int write;
410334f485dSMiklos Szeredi 	struct fuse_req *req;
411334f485dSMiklos Szeredi 	const struct iovec *iov;
412334f485dSMiklos Szeredi 	unsigned long nr_segs;
413334f485dSMiklos Szeredi 	unsigned long seglen;
414334f485dSMiklos Szeredi 	unsigned long addr;
415334f485dSMiklos Szeredi 	struct page *pg;
416334f485dSMiklos Szeredi 	void *mapaddr;
417334f485dSMiklos Szeredi 	void *buf;
418334f485dSMiklos Szeredi 	unsigned len;
419334f485dSMiklos Szeredi };
420334f485dSMiklos Szeredi 
421334f485dSMiklos Szeredi static void fuse_copy_init(struct fuse_copy_state *cs, int write,
422334f485dSMiklos Szeredi 			   struct fuse_req *req, const struct iovec *iov,
423334f485dSMiklos Szeredi 			   unsigned long nr_segs)
424334f485dSMiklos Szeredi {
425334f485dSMiklos Szeredi 	memset(cs, 0, sizeof(*cs));
426334f485dSMiklos Szeredi 	cs->write = write;
427334f485dSMiklos Szeredi 	cs->req = req;
428334f485dSMiklos Szeredi 	cs->iov = iov;
429334f485dSMiklos Szeredi 	cs->nr_segs = nr_segs;
430334f485dSMiklos Szeredi }
431334f485dSMiklos Szeredi 
432334f485dSMiklos Szeredi /* Unmap and put previous page of userspace buffer */
433334f485dSMiklos Szeredi static inline void fuse_copy_finish(struct fuse_copy_state *cs)
434334f485dSMiklos Szeredi {
435334f485dSMiklos Szeredi 	if (cs->mapaddr) {
436334f485dSMiklos Szeredi 		kunmap_atomic(cs->mapaddr, KM_USER0);
437334f485dSMiklos Szeredi 		if (cs->write) {
438334f485dSMiklos Szeredi 			flush_dcache_page(cs->pg);
439334f485dSMiklos Szeredi 			set_page_dirty_lock(cs->pg);
440334f485dSMiklos Szeredi 		}
441334f485dSMiklos Szeredi 		put_page(cs->pg);
442334f485dSMiklos Szeredi 		cs->mapaddr = NULL;
443334f485dSMiklos Szeredi 	}
444334f485dSMiklos Szeredi }
445334f485dSMiklos Szeredi 
446334f485dSMiklos Szeredi /*
447334f485dSMiklos Szeredi  * Get another pagefull of userspace buffer, and map it to kernel
448334f485dSMiklos Szeredi  * address space, and lock request
449334f485dSMiklos Szeredi  */
450334f485dSMiklos Szeredi static int fuse_copy_fill(struct fuse_copy_state *cs)
451334f485dSMiklos Szeredi {
452334f485dSMiklos Szeredi 	unsigned long offset;
453334f485dSMiklos Szeredi 	int err;
454334f485dSMiklos Szeredi 
455334f485dSMiklos Szeredi 	unlock_request(cs->req);
456334f485dSMiklos Szeredi 	fuse_copy_finish(cs);
457334f485dSMiklos Szeredi 	if (!cs->seglen) {
458334f485dSMiklos Szeredi 		BUG_ON(!cs->nr_segs);
459334f485dSMiklos Szeredi 		cs->seglen = cs->iov[0].iov_len;
460334f485dSMiklos Szeredi 		cs->addr = (unsigned long) cs->iov[0].iov_base;
461334f485dSMiklos Szeredi 		cs->iov ++;
462334f485dSMiklos Szeredi 		cs->nr_segs --;
463334f485dSMiklos Szeredi 	}
464334f485dSMiklos Szeredi 	down_read(&current->mm->mmap_sem);
465334f485dSMiklos Szeredi 	err = get_user_pages(current, current->mm, cs->addr, 1, cs->write, 0,
466334f485dSMiklos Szeredi 			     &cs->pg, NULL);
467334f485dSMiklos Szeredi 	up_read(&current->mm->mmap_sem);
468334f485dSMiklos Szeredi 	if (err < 0)
469334f485dSMiklos Szeredi 		return err;
470334f485dSMiklos Szeredi 	BUG_ON(err != 1);
471334f485dSMiklos Szeredi 	offset = cs->addr % PAGE_SIZE;
472334f485dSMiklos Szeredi 	cs->mapaddr = kmap_atomic(cs->pg, KM_USER0);
473334f485dSMiklos Szeredi 	cs->buf = cs->mapaddr + offset;
474334f485dSMiklos Szeredi 	cs->len = min(PAGE_SIZE - offset, cs->seglen);
475334f485dSMiklos Szeredi 	cs->seglen -= cs->len;
476334f485dSMiklos Szeredi 	cs->addr += cs->len;
477334f485dSMiklos Szeredi 
478334f485dSMiklos Szeredi 	return lock_request(cs->req);
479334f485dSMiklos Szeredi }
480334f485dSMiklos Szeredi 
481334f485dSMiklos Szeredi /* Do as much copy to/from userspace buffer as we can */
482334f485dSMiklos Szeredi static inline int fuse_copy_do(struct fuse_copy_state *cs, void **val,
483334f485dSMiklos Szeredi 			       unsigned *size)
484334f485dSMiklos Szeredi {
485334f485dSMiklos Szeredi 	unsigned ncpy = min(*size, cs->len);
486334f485dSMiklos Szeredi 	if (val) {
487334f485dSMiklos Szeredi 		if (cs->write)
488334f485dSMiklos Szeredi 			memcpy(cs->buf, *val, ncpy);
489334f485dSMiklos Szeredi 		else
490334f485dSMiklos Szeredi 			memcpy(*val, cs->buf, ncpy);
491334f485dSMiklos Szeredi 		*val += ncpy;
492334f485dSMiklos Szeredi 	}
493334f485dSMiklos Szeredi 	*size -= ncpy;
494334f485dSMiklos Szeredi 	cs->len -= ncpy;
495334f485dSMiklos Szeredi 	cs->buf += ncpy;
496334f485dSMiklos Szeredi 	return ncpy;
497334f485dSMiklos Szeredi }
498334f485dSMiklos Szeredi 
499334f485dSMiklos Szeredi /*
500334f485dSMiklos Szeredi  * Copy a page in the request to/from the userspace buffer.  Must be
501334f485dSMiklos Szeredi  * done atomically
502334f485dSMiklos Szeredi  */
503334f485dSMiklos Szeredi static inline int fuse_copy_page(struct fuse_copy_state *cs, struct page *page,
504334f485dSMiklos Szeredi 				 unsigned offset, unsigned count, int zeroing)
505334f485dSMiklos Szeredi {
506334f485dSMiklos Szeredi 	if (page && zeroing && count < PAGE_SIZE) {
507334f485dSMiklos Szeredi 		void *mapaddr = kmap_atomic(page, KM_USER1);
508334f485dSMiklos Szeredi 		memset(mapaddr, 0, PAGE_SIZE);
509334f485dSMiklos Szeredi 		kunmap_atomic(mapaddr, KM_USER1);
510334f485dSMiklos Szeredi 	}
511334f485dSMiklos Szeredi 	while (count) {
512334f485dSMiklos Szeredi 		int err;
513334f485dSMiklos Szeredi 		if (!cs->len && (err = fuse_copy_fill(cs)))
514334f485dSMiklos Szeredi 			return err;
515334f485dSMiklos Szeredi 		if (page) {
516334f485dSMiklos Szeredi 			void *mapaddr = kmap_atomic(page, KM_USER1);
517334f485dSMiklos Szeredi 			void *buf = mapaddr + offset;
518334f485dSMiklos Szeredi 			offset += fuse_copy_do(cs, &buf, &count);
519334f485dSMiklos Szeredi 			kunmap_atomic(mapaddr, KM_USER1);
520334f485dSMiklos Szeredi 		} else
521334f485dSMiklos Szeredi 			offset += fuse_copy_do(cs, NULL, &count);
522334f485dSMiklos Szeredi 	}
523334f485dSMiklos Szeredi 	if (page && !cs->write)
524334f485dSMiklos Szeredi 		flush_dcache_page(page);
525334f485dSMiklos Szeredi 	return 0;
526334f485dSMiklos Szeredi }
527334f485dSMiklos Szeredi 
528334f485dSMiklos Szeredi /* Copy pages in the request to/from userspace buffer */
529334f485dSMiklos Szeredi static int fuse_copy_pages(struct fuse_copy_state *cs, unsigned nbytes,
530334f485dSMiklos Szeredi 			   int zeroing)
531334f485dSMiklos Szeredi {
532334f485dSMiklos Szeredi 	unsigned i;
533334f485dSMiklos Szeredi 	struct fuse_req *req = cs->req;
534334f485dSMiklos Szeredi 	unsigned offset = req->page_offset;
535334f485dSMiklos Szeredi 	unsigned count = min(nbytes, (unsigned) PAGE_SIZE - offset);
536334f485dSMiklos Szeredi 
537334f485dSMiklos Szeredi 	for (i = 0; i < req->num_pages && (nbytes || zeroing); i++) {
538334f485dSMiklos Szeredi 		struct page *page = req->pages[i];
539334f485dSMiklos Szeredi 		int err = fuse_copy_page(cs, page, offset, count, zeroing);
540334f485dSMiklos Szeredi 		if (err)
541334f485dSMiklos Szeredi 			return err;
542334f485dSMiklos Szeredi 
543334f485dSMiklos Szeredi 		nbytes -= count;
544334f485dSMiklos Szeredi 		count = min(nbytes, (unsigned) PAGE_SIZE);
545334f485dSMiklos Szeredi 		offset = 0;
546334f485dSMiklos Szeredi 	}
547334f485dSMiklos Szeredi 	return 0;
548334f485dSMiklos Szeredi }
549334f485dSMiklos Szeredi 
550334f485dSMiklos Szeredi /* Copy a single argument in the request to/from userspace buffer */
551334f485dSMiklos Szeredi static int fuse_copy_one(struct fuse_copy_state *cs, void *val, unsigned size)
552334f485dSMiklos Szeredi {
553334f485dSMiklos Szeredi 	while (size) {
554334f485dSMiklos Szeredi 		int err;
555334f485dSMiklos Szeredi 		if (!cs->len && (err = fuse_copy_fill(cs)))
556334f485dSMiklos Szeredi 			return err;
557334f485dSMiklos Szeredi 		fuse_copy_do(cs, &val, &size);
558334f485dSMiklos Szeredi 	}
559334f485dSMiklos Szeredi 	return 0;
560334f485dSMiklos Szeredi }
561334f485dSMiklos Szeredi 
562334f485dSMiklos Szeredi /* Copy request arguments to/from userspace buffer */
563334f485dSMiklos Szeredi static int fuse_copy_args(struct fuse_copy_state *cs, unsigned numargs,
564334f485dSMiklos Szeredi 			  unsigned argpages, struct fuse_arg *args,
565334f485dSMiklos Szeredi 			  int zeroing)
566334f485dSMiklos Szeredi {
567334f485dSMiklos Szeredi 	int err = 0;
568334f485dSMiklos Szeredi 	unsigned i;
569334f485dSMiklos Szeredi 
570334f485dSMiklos Szeredi 	for (i = 0; !err && i < numargs; i++)  {
571334f485dSMiklos Szeredi 		struct fuse_arg *arg = &args[i];
572334f485dSMiklos Szeredi 		if (i == numargs - 1 && argpages)
573334f485dSMiklos Szeredi 			err = fuse_copy_pages(cs, arg->size, zeroing);
574334f485dSMiklos Szeredi 		else
575334f485dSMiklos Szeredi 			err = fuse_copy_one(cs, arg->value, arg->size);
576334f485dSMiklos Szeredi 	}
577334f485dSMiklos Szeredi 	return err;
578334f485dSMiklos Szeredi }
579334f485dSMiklos Szeredi 
580334f485dSMiklos Szeredi /* Wait until a request is available on the pending list */
581334f485dSMiklos Szeredi static void request_wait(struct fuse_conn *fc)
582334f485dSMiklos Szeredi {
583334f485dSMiklos Szeredi 	DECLARE_WAITQUEUE(wait, current);
584334f485dSMiklos Szeredi 
585334f485dSMiklos Szeredi 	add_wait_queue_exclusive(&fc->waitq, &wait);
586334f485dSMiklos Szeredi 	while (fc->sb && list_empty(&fc->pending)) {
587334f485dSMiklos Szeredi 		set_current_state(TASK_INTERRUPTIBLE);
588334f485dSMiklos Szeredi 		if (signal_pending(current))
589334f485dSMiklos Szeredi 			break;
590334f485dSMiklos Szeredi 
591334f485dSMiklos Szeredi 		spin_unlock(&fuse_lock);
592334f485dSMiklos Szeredi 		schedule();
593334f485dSMiklos Szeredi 		spin_lock(&fuse_lock);
594334f485dSMiklos Szeredi 	}
595334f485dSMiklos Szeredi 	set_current_state(TASK_RUNNING);
596334f485dSMiklos Szeredi 	remove_wait_queue(&fc->waitq, &wait);
597334f485dSMiklos Szeredi }
598334f485dSMiklos Szeredi 
599334f485dSMiklos Szeredi /*
600334f485dSMiklos Szeredi  * Read a single request into the userspace filesystem's buffer.  This
601334f485dSMiklos Szeredi  * function waits until a request is available, then removes it from
602334f485dSMiklos Szeredi  * the pending list and copies request data to userspace buffer.  If
603334f485dSMiklos Szeredi  * no reply is needed (FORGET) or request has been interrupted or
604334f485dSMiklos Szeredi  * there was an error during the copying then it's finished by calling
605334f485dSMiklos Szeredi  * request_end().  Otherwise add it to the processing list, and set
606334f485dSMiklos Szeredi  * the 'sent' flag.
607334f485dSMiklos Szeredi  */
608334f485dSMiklos Szeredi static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov,
609334f485dSMiklos Szeredi 			      unsigned long nr_segs, loff_t *off)
610334f485dSMiklos Szeredi {
611334f485dSMiklos Szeredi 	int err;
612334f485dSMiklos Szeredi 	struct fuse_conn *fc;
613334f485dSMiklos Szeredi 	struct fuse_req *req;
614334f485dSMiklos Szeredi 	struct fuse_in *in;
615334f485dSMiklos Szeredi 	struct fuse_copy_state cs;
616334f485dSMiklos Szeredi 	unsigned reqsize;
617334f485dSMiklos Szeredi 
618334f485dSMiklos Szeredi 	spin_lock(&fuse_lock);
619334f485dSMiklos Szeredi 	fc = file->private_data;
620334f485dSMiklos Szeredi 	err = -EPERM;
621334f485dSMiklos Szeredi 	if (!fc)
622334f485dSMiklos Szeredi 		goto err_unlock;
623334f485dSMiklos Szeredi 	request_wait(fc);
624334f485dSMiklos Szeredi 	err = -ENODEV;
625334f485dSMiklos Szeredi 	if (!fc->sb)
626334f485dSMiklos Szeredi 		goto err_unlock;
627334f485dSMiklos Szeredi 	err = -ERESTARTSYS;
628334f485dSMiklos Szeredi 	if (list_empty(&fc->pending))
629334f485dSMiklos Szeredi 		goto err_unlock;
630334f485dSMiklos Szeredi 
631334f485dSMiklos Szeredi 	req = list_entry(fc->pending.next, struct fuse_req, list);
632334f485dSMiklos Szeredi 	list_del_init(&req->list);
633334f485dSMiklos Szeredi 	spin_unlock(&fuse_lock);
634334f485dSMiklos Szeredi 
635334f485dSMiklos Szeredi 	in = &req->in;
636334f485dSMiklos Szeredi 	reqsize = req->in.h.len;
637334f485dSMiklos Szeredi 	fuse_copy_init(&cs, 1, req, iov, nr_segs);
638334f485dSMiklos Szeredi 	err = -EINVAL;
639334f485dSMiklos Szeredi 	if (iov_length(iov, nr_segs) >= reqsize) {
640334f485dSMiklos Szeredi 		err = fuse_copy_one(&cs, &in->h, sizeof(in->h));
641334f485dSMiklos Szeredi 		if (!err)
642334f485dSMiklos Szeredi 			err = fuse_copy_args(&cs, in->numargs, in->argpages,
643334f485dSMiklos Szeredi 					     (struct fuse_arg *) in->args, 0);
644334f485dSMiklos Szeredi 	}
645334f485dSMiklos Szeredi 	fuse_copy_finish(&cs);
646334f485dSMiklos Szeredi 
647334f485dSMiklos Szeredi 	spin_lock(&fuse_lock);
648334f485dSMiklos Szeredi 	req->locked = 0;
649334f485dSMiklos Szeredi 	if (!err && req->interrupted)
650334f485dSMiklos Szeredi 		err = -ENOENT;
651334f485dSMiklos Szeredi 	if (err) {
652334f485dSMiklos Szeredi 		if (!req->interrupted)
653334f485dSMiklos Szeredi 			req->out.h.error = -EIO;
654334f485dSMiklos Szeredi 		request_end(fc, req);
655334f485dSMiklos Szeredi 		return err;
656334f485dSMiklos Szeredi 	}
657334f485dSMiklos Szeredi 	if (!req->isreply)
658334f485dSMiklos Szeredi 		request_end(fc, req);
659334f485dSMiklos Szeredi 	else {
660334f485dSMiklos Szeredi 		req->sent = 1;
661334f485dSMiklos Szeredi 		list_add_tail(&req->list, &fc->processing);
662334f485dSMiklos Szeredi 		spin_unlock(&fuse_lock);
663334f485dSMiklos Szeredi 	}
664334f485dSMiklos Szeredi 	return reqsize;
665334f485dSMiklos Szeredi 
666334f485dSMiklos Szeredi  err_unlock:
667334f485dSMiklos Szeredi 	spin_unlock(&fuse_lock);
668334f485dSMiklos Szeredi 	return err;
669334f485dSMiklos Szeredi }
670334f485dSMiklos Szeredi 
671334f485dSMiklos Szeredi static ssize_t fuse_dev_read(struct file *file, char __user *buf,
672334f485dSMiklos Szeredi 			     size_t nbytes, loff_t *off)
673334f485dSMiklos Szeredi {
674334f485dSMiklos Szeredi 	struct iovec iov;
675334f485dSMiklos Szeredi 	iov.iov_len = nbytes;
676334f485dSMiklos Szeredi 	iov.iov_base = buf;
677334f485dSMiklos Szeredi 	return fuse_dev_readv(file, &iov, 1, off);
678334f485dSMiklos Szeredi }
679334f485dSMiklos Szeredi 
680334f485dSMiklos Szeredi /* Look up request on processing list by unique ID */
681334f485dSMiklos Szeredi static struct fuse_req *request_find(struct fuse_conn *fc, u64 unique)
682334f485dSMiklos Szeredi {
683334f485dSMiklos Szeredi 	struct list_head *entry;
684334f485dSMiklos Szeredi 
685334f485dSMiklos Szeredi 	list_for_each(entry, &fc->processing) {
686334f485dSMiklos Szeredi 		struct fuse_req *req;
687334f485dSMiklos Szeredi 		req = list_entry(entry, struct fuse_req, list);
688334f485dSMiklos Szeredi 		if (req->in.h.unique == unique)
689334f485dSMiklos Szeredi 			return req;
690334f485dSMiklos Szeredi 	}
691334f485dSMiklos Szeredi 	return NULL;
692334f485dSMiklos Szeredi }
693334f485dSMiklos Szeredi 
694334f485dSMiklos Szeredi static int copy_out_args(struct fuse_copy_state *cs, struct fuse_out *out,
695334f485dSMiklos Szeredi 			 unsigned nbytes)
696334f485dSMiklos Szeredi {
697334f485dSMiklos Szeredi 	unsigned reqsize = sizeof(struct fuse_out_header);
698334f485dSMiklos Szeredi 
699334f485dSMiklos Szeredi 	if (out->h.error)
700334f485dSMiklos Szeredi 		return nbytes != reqsize ? -EINVAL : 0;
701334f485dSMiklos Szeredi 
702334f485dSMiklos Szeredi 	reqsize += len_args(out->numargs, out->args);
703334f485dSMiklos Szeredi 
704334f485dSMiklos Szeredi 	if (reqsize < nbytes || (reqsize > nbytes && !out->argvar))
705334f485dSMiklos Szeredi 		return -EINVAL;
706334f485dSMiklos Szeredi 	else if (reqsize > nbytes) {
707334f485dSMiklos Szeredi 		struct fuse_arg *lastarg = &out->args[out->numargs-1];
708334f485dSMiklos Szeredi 		unsigned diffsize = reqsize - nbytes;
709334f485dSMiklos Szeredi 		if (diffsize > lastarg->size)
710334f485dSMiklos Szeredi 			return -EINVAL;
711334f485dSMiklos Szeredi 		lastarg->size -= diffsize;
712334f485dSMiklos Szeredi 	}
713334f485dSMiklos Szeredi 	return fuse_copy_args(cs, out->numargs, out->argpages, out->args,
714334f485dSMiklos Szeredi 			      out->page_zeroing);
715334f485dSMiklos Szeredi }
716334f485dSMiklos Szeredi 
717334f485dSMiklos Szeredi /*
718334f485dSMiklos Szeredi  * Write a single reply to a request.  First the header is copied from
719334f485dSMiklos Szeredi  * the write buffer.  The request is then searched on the processing
720334f485dSMiklos Szeredi  * list by the unique ID found in the header.  If found, then remove
721334f485dSMiklos Szeredi  * it from the list and copy the rest of the buffer to the request.
722334f485dSMiklos Szeredi  * The request is finished by calling request_end()
723334f485dSMiklos Szeredi  */
724334f485dSMiklos Szeredi static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov,
725334f485dSMiklos Szeredi 			       unsigned long nr_segs, loff_t *off)
726334f485dSMiklos Szeredi {
727334f485dSMiklos Szeredi 	int err;
728334f485dSMiklos Szeredi 	unsigned nbytes = iov_length(iov, nr_segs);
729334f485dSMiklos Szeredi 	struct fuse_req *req;
730334f485dSMiklos Szeredi 	struct fuse_out_header oh;
731334f485dSMiklos Szeredi 	struct fuse_copy_state cs;
732334f485dSMiklos Szeredi 	struct fuse_conn *fc = fuse_get_conn(file);
733334f485dSMiklos Szeredi 	if (!fc)
734334f485dSMiklos Szeredi 		return -ENODEV;
735334f485dSMiklos Szeredi 
736334f485dSMiklos Szeredi 	fuse_copy_init(&cs, 0, NULL, iov, nr_segs);
737334f485dSMiklos Szeredi 	if (nbytes < sizeof(struct fuse_out_header))
738334f485dSMiklos Szeredi 		return -EINVAL;
739334f485dSMiklos Szeredi 
740334f485dSMiklos Szeredi 	err = fuse_copy_one(&cs, &oh, sizeof(oh));
741334f485dSMiklos Szeredi 	if (err)
742334f485dSMiklos Szeredi 		goto err_finish;
743334f485dSMiklos Szeredi 	err = -EINVAL;
744334f485dSMiklos Szeredi 	if (!oh.unique || oh.error <= -1000 || oh.error > 0 ||
745334f485dSMiklos Szeredi 	    oh.len != nbytes)
746334f485dSMiklos Szeredi 		goto err_finish;
747334f485dSMiklos Szeredi 
748334f485dSMiklos Szeredi 	spin_lock(&fuse_lock);
749334f485dSMiklos Szeredi 	req = request_find(fc, oh.unique);
750334f485dSMiklos Szeredi 	err = -EINVAL;
751334f485dSMiklos Szeredi 	if (!req)
752334f485dSMiklos Szeredi 		goto err_unlock;
753334f485dSMiklos Szeredi 
754334f485dSMiklos Szeredi 	list_del_init(&req->list);
755334f485dSMiklos Szeredi 	if (req->interrupted) {
756334f485dSMiklos Szeredi 		request_end(fc, req);
757334f485dSMiklos Szeredi 		fuse_copy_finish(&cs);
758334f485dSMiklos Szeredi 		return -ENOENT;
759334f485dSMiklos Szeredi 	}
760334f485dSMiklos Szeredi 	req->out.h = oh;
761334f485dSMiklos Szeredi 	req->locked = 1;
762334f485dSMiklos Szeredi 	cs.req = req;
763334f485dSMiklos Szeredi 	spin_unlock(&fuse_lock);
764334f485dSMiklos Szeredi 
765334f485dSMiklos Szeredi 	err = copy_out_args(&cs, &req->out, nbytes);
766334f485dSMiklos Szeredi 	fuse_copy_finish(&cs);
767334f485dSMiklos Szeredi 
768334f485dSMiklos Szeredi 	spin_lock(&fuse_lock);
769334f485dSMiklos Szeredi 	req->locked = 0;
770334f485dSMiklos Szeredi 	if (!err) {
771334f485dSMiklos Szeredi 		if (req->interrupted)
772334f485dSMiklos Szeredi 			err = -ENOENT;
773334f485dSMiklos Szeredi 	} else if (!req->interrupted)
774334f485dSMiklos Szeredi 		req->out.h.error = -EIO;
775334f485dSMiklos Szeredi 	request_end(fc, req);
776334f485dSMiklos Szeredi 
777334f485dSMiklos Szeredi 	return err ? err : nbytes;
778334f485dSMiklos Szeredi 
779334f485dSMiklos Szeredi  err_unlock:
780334f485dSMiklos Szeredi 	spin_unlock(&fuse_lock);
781334f485dSMiklos Szeredi  err_finish:
782334f485dSMiklos Szeredi 	fuse_copy_finish(&cs);
783334f485dSMiklos Szeredi 	return err;
784334f485dSMiklos Szeredi }
785334f485dSMiklos Szeredi 
786334f485dSMiklos Szeredi static ssize_t fuse_dev_write(struct file *file, const char __user *buf,
787334f485dSMiklos Szeredi 			      size_t nbytes, loff_t *off)
788334f485dSMiklos Szeredi {
789334f485dSMiklos Szeredi 	struct iovec iov;
790334f485dSMiklos Szeredi 	iov.iov_len = nbytes;
791334f485dSMiklos Szeredi 	iov.iov_base = (char __user *) buf;
792334f485dSMiklos Szeredi 	return fuse_dev_writev(file, &iov, 1, off);
793334f485dSMiklos Szeredi }
794334f485dSMiklos Szeredi 
795334f485dSMiklos Szeredi static unsigned fuse_dev_poll(struct file *file, poll_table *wait)
796334f485dSMiklos Szeredi {
797334f485dSMiklos Szeredi 	struct fuse_conn *fc = fuse_get_conn(file);
798334f485dSMiklos Szeredi 	unsigned mask = POLLOUT | POLLWRNORM;
799334f485dSMiklos Szeredi 
800334f485dSMiklos Szeredi 	if (!fc)
801334f485dSMiklos Szeredi 		return -ENODEV;
802334f485dSMiklos Szeredi 
803334f485dSMiklos Szeredi 	poll_wait(file, &fc->waitq, wait);
804334f485dSMiklos Szeredi 
805334f485dSMiklos Szeredi 	spin_lock(&fuse_lock);
806334f485dSMiklos Szeredi 	if (!list_empty(&fc->pending))
807334f485dSMiklos Szeredi                 mask |= POLLIN | POLLRDNORM;
808334f485dSMiklos Szeredi 	spin_unlock(&fuse_lock);
809334f485dSMiklos Szeredi 
810334f485dSMiklos Szeredi 	return mask;
811334f485dSMiklos Szeredi }
812334f485dSMiklos Szeredi 
813334f485dSMiklos Szeredi /* Abort all requests on the given list (pending or processing) */
814334f485dSMiklos Szeredi static void end_requests(struct fuse_conn *fc, struct list_head *head)
815334f485dSMiklos Szeredi {
816334f485dSMiklos Szeredi 	while (!list_empty(head)) {
817334f485dSMiklos Szeredi 		struct fuse_req *req;
818334f485dSMiklos Szeredi 		req = list_entry(head->next, struct fuse_req, list);
819334f485dSMiklos Szeredi 		list_del_init(&req->list);
820334f485dSMiklos Szeredi 		req->out.h.error = -ECONNABORTED;
821334f485dSMiklos Szeredi 		request_end(fc, req);
822334f485dSMiklos Szeredi 		spin_lock(&fuse_lock);
823334f485dSMiklos Szeredi 	}
824334f485dSMiklos Szeredi }
825334f485dSMiklos Szeredi 
826334f485dSMiklos Szeredi static int fuse_dev_release(struct inode *inode, struct file *file)
827334f485dSMiklos Szeredi {
828334f485dSMiklos Szeredi 	struct fuse_conn *fc;
829334f485dSMiklos Szeredi 
830334f485dSMiklos Szeredi 	spin_lock(&fuse_lock);
831334f485dSMiklos Szeredi 	fc = file->private_data;
832334f485dSMiklos Szeredi 	if (fc) {
833334f485dSMiklos Szeredi 		fc->file = NULL;
834334f485dSMiklos Szeredi 		end_requests(fc, &fc->pending);
835334f485dSMiklos Szeredi 		end_requests(fc, &fc->processing);
836334f485dSMiklos Szeredi 		fuse_release_conn(fc);
837334f485dSMiklos Szeredi 	}
838334f485dSMiklos Szeredi 	spin_unlock(&fuse_lock);
839334f485dSMiklos Szeredi 	return 0;
840334f485dSMiklos Szeredi }
841334f485dSMiklos Szeredi 
842334f485dSMiklos Szeredi struct file_operations fuse_dev_operations = {
843334f485dSMiklos Szeredi 	.owner		= THIS_MODULE,
844334f485dSMiklos Szeredi 	.llseek		= no_llseek,
845334f485dSMiklos Szeredi 	.read		= fuse_dev_read,
846334f485dSMiklos Szeredi 	.readv		= fuse_dev_readv,
847334f485dSMiklos Szeredi 	.write		= fuse_dev_write,
848334f485dSMiklos Szeredi 	.writev		= fuse_dev_writev,
849334f485dSMiklos Szeredi 	.poll		= fuse_dev_poll,
850334f485dSMiklos Szeredi 	.release	= fuse_dev_release,
851334f485dSMiklos Szeredi };
852334f485dSMiklos Szeredi 
853334f485dSMiklos Szeredi static struct miscdevice fuse_miscdevice = {
854334f485dSMiklos Szeredi 	.minor = FUSE_MINOR,
855334f485dSMiklos Szeredi 	.name  = "fuse",
856334f485dSMiklos Szeredi 	.fops = &fuse_dev_operations,
857334f485dSMiklos Szeredi };
858334f485dSMiklos Szeredi 
859334f485dSMiklos Szeredi int __init fuse_dev_init(void)
860334f485dSMiklos Szeredi {
861334f485dSMiklos Szeredi 	int err = -ENOMEM;
862334f485dSMiklos Szeredi 	fuse_req_cachep = kmem_cache_create("fuse_request",
863334f485dSMiklos Szeredi 					    sizeof(struct fuse_req),
864334f485dSMiklos Szeredi 					    0, 0, NULL, NULL);
865334f485dSMiklos Szeredi 	if (!fuse_req_cachep)
866334f485dSMiklos Szeredi 		goto out;
867334f485dSMiklos Szeredi 
868334f485dSMiklos Szeredi 	err = misc_register(&fuse_miscdevice);
869334f485dSMiklos Szeredi 	if (err)
870334f485dSMiklos Szeredi 		goto out_cache_clean;
871334f485dSMiklos Szeredi 
872334f485dSMiklos Szeredi 	return 0;
873334f485dSMiklos Szeredi 
874334f485dSMiklos Szeredi  out_cache_clean:
875334f485dSMiklos Szeredi 	kmem_cache_destroy(fuse_req_cachep);
876334f485dSMiklos Szeredi  out:
877334f485dSMiklos Szeredi 	return err;
878334f485dSMiklos Szeredi }
879334f485dSMiklos Szeredi 
880334f485dSMiklos Szeredi void fuse_dev_cleanup(void)
881334f485dSMiklos Szeredi {
882334f485dSMiklos Szeredi 	misc_deregister(&fuse_miscdevice);
883334f485dSMiklos Szeredi 	kmem_cache_destroy(fuse_req_cachep);
884334f485dSMiklos Szeredi }
885