xref: /openbmc/linux/fs/fuse/dev.c (revision e9bb09dd)
1334f485dSMiklos Szeredi /*
2334f485dSMiklos Szeredi   FUSE: Filesystem in Userspace
31729a16cSMiklos Szeredi   Copyright (C) 2001-2008  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 
22e18b890bSChristoph Lameter static struct kmem_cache *fuse_req_cachep;
23334f485dSMiklos Szeredi 
248bfc016dSMiklos Szeredi static struct fuse_conn *fuse_get_conn(struct file *file)
25334f485dSMiklos Szeredi {
260720b315SMiklos Szeredi 	/*
270720b315SMiklos Szeredi 	 * Lockless access is OK, because file->private data is set
280720b315SMiklos Szeredi 	 * once during mount and is valid until the file is released.
290720b315SMiklos Szeredi 	 */
300720b315SMiklos Szeredi 	return file->private_data;
31334f485dSMiklos Szeredi }
32334f485dSMiklos Szeredi 
338bfc016dSMiklos Szeredi static void fuse_request_init(struct fuse_req *req)
34334f485dSMiklos Szeredi {
35334f485dSMiklos Szeredi 	memset(req, 0, sizeof(*req));
36334f485dSMiklos Szeredi 	INIT_LIST_HEAD(&req->list);
37a4d27e75SMiklos Szeredi 	INIT_LIST_HEAD(&req->intr_entry);
38334f485dSMiklos Szeredi 	init_waitqueue_head(&req->waitq);
39334f485dSMiklos Szeredi 	atomic_set(&req->count, 1);
40334f485dSMiklos Szeredi }
41334f485dSMiklos Szeredi 
42334f485dSMiklos Szeredi struct fuse_req *fuse_request_alloc(void)
43334f485dSMiklos Szeredi {
44e94b1766SChristoph Lameter 	struct fuse_req *req = kmem_cache_alloc(fuse_req_cachep, GFP_KERNEL);
45334f485dSMiklos Szeredi 	if (req)
46334f485dSMiklos Szeredi 		fuse_request_init(req);
47334f485dSMiklos Szeredi 	return req;
48334f485dSMiklos Szeredi }
49334f485dSMiklos Szeredi 
503be5a52bSMiklos Szeredi struct fuse_req *fuse_request_alloc_nofs(void)
513be5a52bSMiklos Szeredi {
523be5a52bSMiklos Szeredi 	struct fuse_req *req = kmem_cache_alloc(fuse_req_cachep, GFP_NOFS);
533be5a52bSMiklos Szeredi 	if (req)
543be5a52bSMiklos Szeredi 		fuse_request_init(req);
553be5a52bSMiklos Szeredi 	return req;
563be5a52bSMiklos Szeredi }
573be5a52bSMiklos Szeredi 
58334f485dSMiklos Szeredi void fuse_request_free(struct fuse_req *req)
59334f485dSMiklos Szeredi {
60334f485dSMiklos Szeredi 	kmem_cache_free(fuse_req_cachep, req);
61334f485dSMiklos Szeredi }
62334f485dSMiklos Szeredi 
638bfc016dSMiklos Szeredi static void block_sigs(sigset_t *oldset)
64334f485dSMiklos Szeredi {
65334f485dSMiklos Szeredi 	sigset_t mask;
66334f485dSMiklos Szeredi 
67334f485dSMiklos Szeredi 	siginitsetinv(&mask, sigmask(SIGKILL));
68334f485dSMiklos Szeredi 	sigprocmask(SIG_BLOCK, &mask, oldset);
69334f485dSMiklos Szeredi }
70334f485dSMiklos Szeredi 
718bfc016dSMiklos Szeredi static void restore_sigs(sigset_t *oldset)
72334f485dSMiklos Szeredi {
73334f485dSMiklos Szeredi 	sigprocmask(SIG_SETMASK, oldset, NULL);
74334f485dSMiklos Szeredi }
75334f485dSMiklos Szeredi 
76334f485dSMiklos Szeredi static void __fuse_get_request(struct fuse_req *req)
77334f485dSMiklos Szeredi {
78334f485dSMiklos Szeredi 	atomic_inc(&req->count);
79334f485dSMiklos Szeredi }
80334f485dSMiklos Szeredi 
81334f485dSMiklos Szeredi /* Must be called with > 1 refcount */
82334f485dSMiklos Szeredi static void __fuse_put_request(struct fuse_req *req)
83334f485dSMiklos Szeredi {
84334f485dSMiklos Szeredi 	BUG_ON(atomic_read(&req->count) < 2);
85334f485dSMiklos Szeredi 	atomic_dec(&req->count);
86334f485dSMiklos Szeredi }
87334f485dSMiklos Szeredi 
8833649c91SMiklos Szeredi static void fuse_req_init_context(struct fuse_req *req)
8933649c91SMiklos Szeredi {
9033649c91SMiklos Szeredi 	req->in.h.uid = current->fsuid;
9133649c91SMiklos Szeredi 	req->in.h.gid = current->fsgid;
9233649c91SMiklos Szeredi 	req->in.h.pid = current->pid;
9333649c91SMiklos Szeredi }
9433649c91SMiklos Szeredi 
95ce1d5a49SMiklos Szeredi struct fuse_req *fuse_get_req(struct fuse_conn *fc)
96334f485dSMiklos Szeredi {
9708a53cdcSMiklos Szeredi 	struct fuse_req *req;
9808a53cdcSMiklos Szeredi 	sigset_t oldset;
999bc5dddaSMiklos Szeredi 	int intr;
10008a53cdcSMiklos Szeredi 	int err;
10108a53cdcSMiklos Szeredi 
1029bc5dddaSMiklos Szeredi 	atomic_inc(&fc->num_waiting);
10308a53cdcSMiklos Szeredi 	block_sigs(&oldset);
1049bc5dddaSMiklos Szeredi 	intr = wait_event_interruptible(fc->blocked_waitq, !fc->blocked);
10508a53cdcSMiklos Szeredi 	restore_sigs(&oldset);
1069bc5dddaSMiklos Szeredi 	err = -EINTR;
1079bc5dddaSMiklos Szeredi 	if (intr)
1089bc5dddaSMiklos Szeredi 		goto out;
10908a53cdcSMiklos Szeredi 
11051eb01e7SMiklos Szeredi 	err = -ENOTCONN;
11151eb01e7SMiklos Szeredi 	if (!fc->connected)
11251eb01e7SMiklos Szeredi 		goto out;
11351eb01e7SMiklos Szeredi 
11408a53cdcSMiklos Szeredi 	req = fuse_request_alloc();
1159bc5dddaSMiklos Szeredi 	err = -ENOMEM;
116ce1d5a49SMiklos Szeredi 	if (!req)
1179bc5dddaSMiklos Szeredi 		goto out;
118334f485dSMiklos Szeredi 
11933649c91SMiklos Szeredi 	fuse_req_init_context(req);
1209bc5dddaSMiklos Szeredi 	req->waiting = 1;
121334f485dSMiklos Szeredi 	return req;
1229bc5dddaSMiklos Szeredi 
1239bc5dddaSMiklos Szeredi  out:
1249bc5dddaSMiklos Szeredi 	atomic_dec(&fc->num_waiting);
1259bc5dddaSMiklos Szeredi 	return ERR_PTR(err);
126334f485dSMiklos Szeredi }
127334f485dSMiklos Szeredi 
12833649c91SMiklos Szeredi /*
12933649c91SMiklos Szeredi  * Return request in fuse_file->reserved_req.  However that may
13033649c91SMiklos Szeredi  * currently be in use.  If that is the case, wait for it to become
13133649c91SMiklos Szeredi  * available.
13233649c91SMiklos Szeredi  */
13333649c91SMiklos Szeredi static struct fuse_req *get_reserved_req(struct fuse_conn *fc,
13433649c91SMiklos Szeredi 					 struct file *file)
13533649c91SMiklos Szeredi {
13633649c91SMiklos Szeredi 	struct fuse_req *req = NULL;
13733649c91SMiklos Szeredi 	struct fuse_file *ff = file->private_data;
13833649c91SMiklos Szeredi 
13933649c91SMiklos Szeredi 	do {
140de5e3decSMiklos Szeredi 		wait_event(fc->reserved_req_waitq, ff->reserved_req);
14133649c91SMiklos Szeredi 		spin_lock(&fc->lock);
14233649c91SMiklos Szeredi 		if (ff->reserved_req) {
14333649c91SMiklos Szeredi 			req = ff->reserved_req;
14433649c91SMiklos Szeredi 			ff->reserved_req = NULL;
14533649c91SMiklos Szeredi 			get_file(file);
14633649c91SMiklos Szeredi 			req->stolen_file = file;
14733649c91SMiklos Szeredi 		}
14833649c91SMiklos Szeredi 		spin_unlock(&fc->lock);
14933649c91SMiklos Szeredi 	} while (!req);
15033649c91SMiklos Szeredi 
15133649c91SMiklos Szeredi 	return req;
15233649c91SMiklos Szeredi }
15333649c91SMiklos Szeredi 
15433649c91SMiklos Szeredi /*
15533649c91SMiklos Szeredi  * Put stolen request back into fuse_file->reserved_req
15633649c91SMiklos Szeredi  */
15733649c91SMiklos Szeredi static void put_reserved_req(struct fuse_conn *fc, struct fuse_req *req)
15833649c91SMiklos Szeredi {
15933649c91SMiklos Szeredi 	struct file *file = req->stolen_file;
16033649c91SMiklos Szeredi 	struct fuse_file *ff = file->private_data;
16133649c91SMiklos Szeredi 
16233649c91SMiklos Szeredi 	spin_lock(&fc->lock);
16333649c91SMiklos Szeredi 	fuse_request_init(req);
16433649c91SMiklos Szeredi 	BUG_ON(ff->reserved_req);
16533649c91SMiklos Szeredi 	ff->reserved_req = req;
166de5e3decSMiklos Szeredi 	wake_up_all(&fc->reserved_req_waitq);
16733649c91SMiklos Szeredi 	spin_unlock(&fc->lock);
16833649c91SMiklos Szeredi 	fput(file);
16933649c91SMiklos Szeredi }
17033649c91SMiklos Szeredi 
17133649c91SMiklos Szeredi /*
17233649c91SMiklos Szeredi  * Gets a requests for a file operation, always succeeds
17333649c91SMiklos Szeredi  *
17433649c91SMiklos Szeredi  * This is used for sending the FLUSH request, which must get to
17533649c91SMiklos Szeredi  * userspace, due to POSIX locks which may need to be unlocked.
17633649c91SMiklos Szeredi  *
17733649c91SMiklos Szeredi  * If allocation fails due to OOM, use the reserved request in
17833649c91SMiklos Szeredi  * fuse_file.
17933649c91SMiklos Szeredi  *
18033649c91SMiklos Szeredi  * This is very unlikely to deadlock accidentally, since the
18133649c91SMiklos Szeredi  * filesystem should not have it's own file open.  If deadlock is
18233649c91SMiklos Szeredi  * intentional, it can still be broken by "aborting" the filesystem.
18333649c91SMiklos Szeredi  */
18433649c91SMiklos Szeredi struct fuse_req *fuse_get_req_nofail(struct fuse_conn *fc, struct file *file)
18533649c91SMiklos Szeredi {
18633649c91SMiklos Szeredi 	struct fuse_req *req;
18733649c91SMiklos Szeredi 
18833649c91SMiklos Szeredi 	atomic_inc(&fc->num_waiting);
18933649c91SMiklos Szeredi 	wait_event(fc->blocked_waitq, !fc->blocked);
19033649c91SMiklos Szeredi 	req = fuse_request_alloc();
19133649c91SMiklos Szeredi 	if (!req)
19233649c91SMiklos Szeredi 		req = get_reserved_req(fc, file);
19333649c91SMiklos Szeredi 
19433649c91SMiklos Szeredi 	fuse_req_init_context(req);
19533649c91SMiklos Szeredi 	req->waiting = 1;
19633649c91SMiklos Szeredi 	return req;
19733649c91SMiklos Szeredi }
19833649c91SMiklos Szeredi 
199334f485dSMiklos Szeredi void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req)
200334f485dSMiklos Szeredi {
2017128ec2aSMiklos Szeredi 	if (atomic_dec_and_test(&req->count)) {
2029bc5dddaSMiklos Szeredi 		if (req->waiting)
203ce1d5a49SMiklos Szeredi 			atomic_dec(&fc->num_waiting);
20433649c91SMiklos Szeredi 
20533649c91SMiklos Szeredi 		if (req->stolen_file)
20633649c91SMiklos Szeredi 			put_reserved_req(fc, req);
20733649c91SMiklos Szeredi 		else
208ce1d5a49SMiklos Szeredi 			fuse_request_free(req);
2097128ec2aSMiklos Szeredi 	}
2107128ec2aSMiklos Szeredi }
2117128ec2aSMiklos Szeredi 
212d12def1bSMiklos Szeredi static unsigned len_args(unsigned numargs, struct fuse_arg *args)
213d12def1bSMiklos Szeredi {
214d12def1bSMiklos Szeredi 	unsigned nbytes = 0;
215d12def1bSMiklos Szeredi 	unsigned i;
216d12def1bSMiklos Szeredi 
217d12def1bSMiklos Szeredi 	for (i = 0; i < numargs; i++)
218d12def1bSMiklos Szeredi 		nbytes += args[i].size;
219d12def1bSMiklos Szeredi 
220d12def1bSMiklos Szeredi 	return nbytes;
221d12def1bSMiklos Szeredi }
222d12def1bSMiklos Szeredi 
223d12def1bSMiklos Szeredi static u64 fuse_get_unique(struct fuse_conn *fc)
224d12def1bSMiklos Szeredi {
225d12def1bSMiklos Szeredi 	fc->reqctr++;
226d12def1bSMiklos Szeredi 	/* zero is special */
227d12def1bSMiklos Szeredi 	if (fc->reqctr == 0)
228d12def1bSMiklos Szeredi 		fc->reqctr = 1;
229d12def1bSMiklos Szeredi 
230d12def1bSMiklos Szeredi 	return fc->reqctr;
231d12def1bSMiklos Szeredi }
232d12def1bSMiklos Szeredi 
233d12def1bSMiklos Szeredi static void queue_request(struct fuse_conn *fc, struct fuse_req *req)
234d12def1bSMiklos Szeredi {
235d12def1bSMiklos Szeredi 	req->in.h.unique = fuse_get_unique(fc);
236d12def1bSMiklos Szeredi 	req->in.h.len = sizeof(struct fuse_in_header) +
237d12def1bSMiklos Szeredi 		len_args(req->in.numargs, (struct fuse_arg *) req->in.args);
238d12def1bSMiklos Szeredi 	list_add_tail(&req->list, &fc->pending);
239d12def1bSMiklos Szeredi 	req->state = FUSE_REQ_PENDING;
240d12def1bSMiklos Szeredi 	if (!req->waiting) {
241d12def1bSMiklos Szeredi 		req->waiting = 1;
242d12def1bSMiklos Szeredi 		atomic_inc(&fc->num_waiting);
243d12def1bSMiklos Szeredi 	}
244d12def1bSMiklos Szeredi 	wake_up(&fc->waitq);
245d12def1bSMiklos Szeredi 	kill_fasync(&fc->fasync, SIGIO, POLL_IN);
246d12def1bSMiklos Szeredi }
247d12def1bSMiklos Szeredi 
248d12def1bSMiklos Szeredi static void flush_bg_queue(struct fuse_conn *fc)
249d12def1bSMiklos Szeredi {
250d12def1bSMiklos Szeredi 	while (fc->active_background < FUSE_MAX_BACKGROUND &&
251d12def1bSMiklos Szeredi 	       !list_empty(&fc->bg_queue)) {
252d12def1bSMiklos Szeredi 		struct fuse_req *req;
253d12def1bSMiklos Szeredi 
254d12def1bSMiklos Szeredi 		req = list_entry(fc->bg_queue.next, struct fuse_req, list);
255d12def1bSMiklos Szeredi 		list_del(&req->list);
256d12def1bSMiklos Szeredi 		fc->active_background++;
257d12def1bSMiklos Szeredi 		queue_request(fc, req);
258d12def1bSMiklos Szeredi 	}
259d12def1bSMiklos Szeredi }
260d12def1bSMiklos Szeredi 
2616dbbcb12SMiklos Szeredi /*
262334f485dSMiklos Szeredi  * This function is called when a request is finished.  Either a reply
263f9a2842eSMiklos Szeredi  * has arrived or it was aborted (and not yet sent) or some error
264f43b155aSMiklos Szeredi  * occurred during communication with userspace, or the device file
26551eb01e7SMiklos Szeredi  * was closed.  The requester thread is woken up (if still waiting),
26651eb01e7SMiklos Szeredi  * the 'end' callback is called if given, else the reference to the
26751eb01e7SMiklos Szeredi  * request is released
2687128ec2aSMiklos Szeredi  *
269d7133114SMiklos Szeredi  * Called with fc->lock, unlocks it
270334f485dSMiklos Szeredi  */
271334f485dSMiklos Szeredi static void request_end(struct fuse_conn *fc, struct fuse_req *req)
272105f4d7aSJosh Triplett 	__releases(fc->lock)
273334f485dSMiklos Szeredi {
2747128ec2aSMiklos Szeredi 	void (*end) (struct fuse_conn *, struct fuse_req *) = req->end;
2757128ec2aSMiklos Szeredi 	req->end = NULL;
27651eb01e7SMiklos Szeredi 	list_del(&req->list);
277a4d27e75SMiklos Szeredi 	list_del(&req->intr_entry);
27851eb01e7SMiklos Szeredi 	req->state = FUSE_REQ_FINISHED;
27951eb01e7SMiklos Szeredi 	if (req->background) {
28051eb01e7SMiklos Szeredi 		if (fc->num_background == FUSE_MAX_BACKGROUND) {
28151eb01e7SMiklos Szeredi 			fc->blocked = 0;
28251eb01e7SMiklos Szeredi 			wake_up_all(&fc->blocked_waitq);
28351eb01e7SMiklos Szeredi 		}
284f92b99b9SMiklos Szeredi 		if (fc->num_background == FUSE_CONGESTION_THRESHOLD) {
285f92b99b9SMiklos Szeredi 			clear_bdi_congested(&fc->bdi, READ);
286f92b99b9SMiklos Szeredi 			clear_bdi_congested(&fc->bdi, WRITE);
287f92b99b9SMiklos Szeredi 		}
28851eb01e7SMiklos Szeredi 		fc->num_background--;
289d12def1bSMiklos Szeredi 		fc->active_background--;
290d12def1bSMiklos Szeredi 		flush_bg_queue(fc);
29151eb01e7SMiklos Szeredi 	}
292d7133114SMiklos Szeredi 	spin_unlock(&fc->lock);
29351eb01e7SMiklos Szeredi 	wake_up(&req->waitq);
29464c6d8edSMiklos Szeredi 	if (end)
29564c6d8edSMiklos Szeredi 		end(fc, req);
296f43b155aSMiklos Szeredi 	fuse_put_request(fc, req);
297334f485dSMiklos Szeredi }
298334f485dSMiklos Szeredi 
299a4d27e75SMiklos Szeredi static void wait_answer_interruptible(struct fuse_conn *fc,
300a4d27e75SMiklos Szeredi 				      struct fuse_req *req)
3014dbf930eSMiklos Szeredi 	__releases(fc->lock) __acquires(fc->lock)
302a4d27e75SMiklos Szeredi {
303a4d27e75SMiklos Szeredi 	if (signal_pending(current))
304a4d27e75SMiklos Szeredi 		return;
305a4d27e75SMiklos Szeredi 
306a4d27e75SMiklos Szeredi 	spin_unlock(&fc->lock);
307a4d27e75SMiklos Szeredi 	wait_event_interruptible(req->waitq, req->state == FUSE_REQ_FINISHED);
308a4d27e75SMiklos Szeredi 	spin_lock(&fc->lock);
309a4d27e75SMiklos Szeredi }
310a4d27e75SMiklos Szeredi 
311a4d27e75SMiklos Szeredi static void queue_interrupt(struct fuse_conn *fc, struct fuse_req *req)
312a4d27e75SMiklos Szeredi {
313a4d27e75SMiklos Szeredi 	list_add_tail(&req->intr_entry, &fc->interrupts);
314a4d27e75SMiklos Szeredi 	wake_up(&fc->waitq);
315a4d27e75SMiklos Szeredi 	kill_fasync(&fc->fasync, SIGIO, POLL_IN);
316a4d27e75SMiklos Szeredi }
317a4d27e75SMiklos Szeredi 
3187c352bdfSMiklos Szeredi static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)
3194dbf930eSMiklos Szeredi 	__releases(fc->lock) __acquires(fc->lock)
320334f485dSMiklos Szeredi {
321a4d27e75SMiklos Szeredi 	if (!fc->no_interrupt) {
322a4d27e75SMiklos Szeredi 		/* Any signal may interrupt this */
323a4d27e75SMiklos Szeredi 		wait_answer_interruptible(fc, req);
324334f485dSMiklos Szeredi 
325a4d27e75SMiklos Szeredi 		if (req->aborted)
326a4d27e75SMiklos Szeredi 			goto aborted;
327a4d27e75SMiklos Szeredi 		if (req->state == FUSE_REQ_FINISHED)
328334f485dSMiklos Szeredi 			return;
329334f485dSMiklos Szeredi 
330a4d27e75SMiklos Szeredi 		req->interrupted = 1;
331a4d27e75SMiklos Szeredi 		if (req->state == FUSE_REQ_SENT)
332a4d27e75SMiklos Szeredi 			queue_interrupt(fc, req);
333a4d27e75SMiklos Szeredi 	}
334a4d27e75SMiklos Szeredi 
335a131de0aSMiklos Szeredi 	if (!req->force) {
336a4d27e75SMiklos Szeredi 		sigset_t oldset;
337a4d27e75SMiklos Szeredi 
338a4d27e75SMiklos Szeredi 		/* Only fatal signals may interrupt this */
339a4d27e75SMiklos Szeredi 		block_sigs(&oldset);
340a4d27e75SMiklos Szeredi 		wait_answer_interruptible(fc, req);
341a4d27e75SMiklos Szeredi 		restore_sigs(&oldset);
342a4d27e75SMiklos Szeredi 
343a4d27e75SMiklos Szeredi 		if (req->aborted)
344a4d27e75SMiklos Szeredi 			goto aborted;
345a4d27e75SMiklos Szeredi 		if (req->state == FUSE_REQ_FINISHED)
346a4d27e75SMiklos Szeredi 			return;
347a4d27e75SMiklos Szeredi 
348a131de0aSMiklos Szeredi 		/* Request is not yet in userspace, bail out */
349a131de0aSMiklos Szeredi 		if (req->state == FUSE_REQ_PENDING) {
350a131de0aSMiklos Szeredi 			list_del(&req->list);
351a131de0aSMiklos Szeredi 			__fuse_put_request(req);
352334f485dSMiklos Szeredi 			req->out.h.error = -EINTR;
353a131de0aSMiklos Szeredi 			return;
354a131de0aSMiklos Szeredi 		}
355a131de0aSMiklos Szeredi 	}
356a131de0aSMiklos Szeredi 
357a131de0aSMiklos Szeredi 	/*
358a131de0aSMiklos Szeredi 	 * Either request is already in userspace, or it was forced.
359a131de0aSMiklos Szeredi 	 * Wait it out.
360a131de0aSMiklos Szeredi 	 */
361a131de0aSMiklos Szeredi 	spin_unlock(&fc->lock);
362a131de0aSMiklos Szeredi 	wait_event(req->waitq, req->state == FUSE_REQ_FINISHED);
363a131de0aSMiklos Szeredi 	spin_lock(&fc->lock);
364a131de0aSMiklos Szeredi 
365a131de0aSMiklos Szeredi 	if (!req->aborted)
366a131de0aSMiklos Szeredi 		return;
367a4d27e75SMiklos Szeredi 
368a4d27e75SMiklos Szeredi  aborted:
369a131de0aSMiklos Szeredi 	BUG_ON(req->state != FUSE_REQ_FINISHED);
370334f485dSMiklos Szeredi 	if (req->locked) {
371334f485dSMiklos Szeredi 		/* This is uninterruptible sleep, because data is
372334f485dSMiklos Szeredi 		   being copied to/from the buffers of req.  During
373334f485dSMiklos Szeredi 		   locked state, there mustn't be any filesystem
374334f485dSMiklos Szeredi 		   operation (e.g. page fault), since that could lead
375334f485dSMiklos Szeredi 		   to deadlock */
376d7133114SMiklos Szeredi 		spin_unlock(&fc->lock);
377334f485dSMiklos Szeredi 		wait_event(req->waitq, !req->locked);
378d7133114SMiklos Szeredi 		spin_lock(&fc->lock);
379334f485dSMiklos Szeredi 	}
380334f485dSMiklos Szeredi }
381334f485dSMiklos Szeredi 
3827c352bdfSMiklos Szeredi void request_send(struct fuse_conn *fc, struct fuse_req *req)
383334f485dSMiklos Szeredi {
384334f485dSMiklos Szeredi 	req->isreply = 1;
385d7133114SMiklos Szeredi 	spin_lock(&fc->lock);
3861e9a4ed9SMiklos Szeredi 	if (!fc->connected)
387334f485dSMiklos Szeredi 		req->out.h.error = -ENOTCONN;
388334f485dSMiklos Szeredi 	else if (fc->conn_error)
389334f485dSMiklos Szeredi 		req->out.h.error = -ECONNREFUSED;
390334f485dSMiklos Szeredi 	else {
391334f485dSMiklos Szeredi 		queue_request(fc, req);
392334f485dSMiklos Szeredi 		/* acquire extra reference, since request is still needed
393334f485dSMiklos Szeredi 		   after request_end() */
394334f485dSMiklos Szeredi 		__fuse_get_request(req);
395334f485dSMiklos Szeredi 
3967c352bdfSMiklos Szeredi 		request_wait_answer(fc, req);
397334f485dSMiklos Szeredi 	}
398d7133114SMiklos Szeredi 	spin_unlock(&fc->lock);
399334f485dSMiklos Szeredi }
400334f485dSMiklos Szeredi 
401d12def1bSMiklos Szeredi static void request_send_nowait_locked(struct fuse_conn *fc,
402d12def1bSMiklos Szeredi 				       struct fuse_req *req)
403334f485dSMiklos Szeredi {
40451eb01e7SMiklos Szeredi 	req->background = 1;
40551eb01e7SMiklos Szeredi 	fc->num_background++;
40651eb01e7SMiklos Szeredi 	if (fc->num_background == FUSE_MAX_BACKGROUND)
40751eb01e7SMiklos Szeredi 		fc->blocked = 1;
408f92b99b9SMiklos Szeredi 	if (fc->num_background == FUSE_CONGESTION_THRESHOLD) {
409f92b99b9SMiklos Szeredi 		set_bdi_congested(&fc->bdi, READ);
410f92b99b9SMiklos Szeredi 		set_bdi_congested(&fc->bdi, WRITE);
411f92b99b9SMiklos Szeredi 	}
412d12def1bSMiklos Szeredi 	list_add_tail(&req->list, &fc->bg_queue);
413d12def1bSMiklos Szeredi 	flush_bg_queue(fc);
414d12def1bSMiklos Szeredi }
41551eb01e7SMiklos Szeredi 
416d12def1bSMiklos Szeredi static void request_send_nowait(struct fuse_conn *fc, struct fuse_req *req)
417d12def1bSMiklos Szeredi {
418d12def1bSMiklos Szeredi 	spin_lock(&fc->lock);
419d12def1bSMiklos Szeredi 	if (fc->connected) {
420d12def1bSMiklos Szeredi 		request_send_nowait_locked(fc, req);
421d7133114SMiklos Szeredi 		spin_unlock(&fc->lock);
422334f485dSMiklos Szeredi 	} else {
423334f485dSMiklos Szeredi 		req->out.h.error = -ENOTCONN;
424334f485dSMiklos Szeredi 		request_end(fc, req);
425334f485dSMiklos Szeredi 	}
426334f485dSMiklos Szeredi }
427334f485dSMiklos Szeredi 
428334f485dSMiklos Szeredi void request_send_noreply(struct fuse_conn *fc, struct fuse_req *req)
429334f485dSMiklos Szeredi {
430334f485dSMiklos Szeredi 	req->isreply = 0;
431334f485dSMiklos Szeredi 	request_send_nowait(fc, req);
432334f485dSMiklos Szeredi }
433334f485dSMiklos Szeredi 
434334f485dSMiklos Szeredi void request_send_background(struct fuse_conn *fc, struct fuse_req *req)
435334f485dSMiklos Szeredi {
436334f485dSMiklos Szeredi 	req->isreply = 1;
437334f485dSMiklos Szeredi 	request_send_nowait(fc, req);
438334f485dSMiklos Szeredi }
439334f485dSMiklos Szeredi 
440334f485dSMiklos Szeredi /*
4413be5a52bSMiklos Szeredi  * Called under fc->lock
4423be5a52bSMiklos Szeredi  *
4433be5a52bSMiklos Szeredi  * fc->connected must have been checked previously
4443be5a52bSMiklos Szeredi  */
4453be5a52bSMiklos Szeredi void request_send_background_locked(struct fuse_conn *fc, struct fuse_req *req)
4463be5a52bSMiklos Szeredi {
4473be5a52bSMiklos Szeredi 	req->isreply = 1;
4483be5a52bSMiklos Szeredi 	request_send_nowait_locked(fc, req);
4493be5a52bSMiklos Szeredi }
4503be5a52bSMiklos Szeredi 
4513be5a52bSMiklos Szeredi /*
452334f485dSMiklos Szeredi  * Lock the request.  Up to the next unlock_request() there mustn't be
453334f485dSMiklos Szeredi  * anything that could cause a page-fault.  If the request was already
454f9a2842eSMiklos Szeredi  * aborted bail out.
455334f485dSMiklos Szeredi  */
456d7133114SMiklos Szeredi static int lock_request(struct fuse_conn *fc, struct fuse_req *req)
457334f485dSMiklos Szeredi {
458334f485dSMiklos Szeredi 	int err = 0;
459334f485dSMiklos Szeredi 	if (req) {
460d7133114SMiklos Szeredi 		spin_lock(&fc->lock);
461f9a2842eSMiklos Szeredi 		if (req->aborted)
462334f485dSMiklos Szeredi 			err = -ENOENT;
463334f485dSMiklos Szeredi 		else
464334f485dSMiklos Szeredi 			req->locked = 1;
465d7133114SMiklos Szeredi 		spin_unlock(&fc->lock);
466334f485dSMiklos Szeredi 	}
467334f485dSMiklos Szeredi 	return err;
468334f485dSMiklos Szeredi }
469334f485dSMiklos Szeredi 
470334f485dSMiklos Szeredi /*
471f9a2842eSMiklos Szeredi  * Unlock request.  If it was aborted during being locked, the
472334f485dSMiklos Szeredi  * requester thread is currently waiting for it to be unlocked, so
473334f485dSMiklos Szeredi  * wake it up.
474334f485dSMiklos Szeredi  */
475d7133114SMiklos Szeredi static void unlock_request(struct fuse_conn *fc, struct fuse_req *req)
476334f485dSMiklos Szeredi {
477334f485dSMiklos Szeredi 	if (req) {
478d7133114SMiklos Szeredi 		spin_lock(&fc->lock);
479334f485dSMiklos Szeredi 		req->locked = 0;
480f9a2842eSMiklos Szeredi 		if (req->aborted)
481334f485dSMiklos Szeredi 			wake_up(&req->waitq);
482d7133114SMiklos Szeredi 		spin_unlock(&fc->lock);
483334f485dSMiklos Szeredi 	}
484334f485dSMiklos Szeredi }
485334f485dSMiklos Szeredi 
486334f485dSMiklos Szeredi struct fuse_copy_state {
487d7133114SMiklos Szeredi 	struct fuse_conn *fc;
488334f485dSMiklos Szeredi 	int write;
489334f485dSMiklos Szeredi 	struct fuse_req *req;
490334f485dSMiklos Szeredi 	const struct iovec *iov;
491334f485dSMiklos Szeredi 	unsigned long nr_segs;
492334f485dSMiklos Szeredi 	unsigned long seglen;
493334f485dSMiklos Szeredi 	unsigned long addr;
494334f485dSMiklos Szeredi 	struct page *pg;
495334f485dSMiklos Szeredi 	void *mapaddr;
496334f485dSMiklos Szeredi 	void *buf;
497334f485dSMiklos Szeredi 	unsigned len;
498334f485dSMiklos Szeredi };
499334f485dSMiklos Szeredi 
500d7133114SMiklos Szeredi static void fuse_copy_init(struct fuse_copy_state *cs, struct fuse_conn *fc,
501d7133114SMiklos Szeredi 			   int write, struct fuse_req *req,
502d7133114SMiklos Szeredi 			   const struct iovec *iov, unsigned long nr_segs)
503334f485dSMiklos Szeredi {
504334f485dSMiklos Szeredi 	memset(cs, 0, sizeof(*cs));
505d7133114SMiklos Szeredi 	cs->fc = fc;
506334f485dSMiklos Szeredi 	cs->write = write;
507334f485dSMiklos Szeredi 	cs->req = req;
508334f485dSMiklos Szeredi 	cs->iov = iov;
509334f485dSMiklos Szeredi 	cs->nr_segs = nr_segs;
510334f485dSMiklos Szeredi }
511334f485dSMiklos Szeredi 
512334f485dSMiklos Szeredi /* Unmap and put previous page of userspace buffer */
5138bfc016dSMiklos Szeredi static void fuse_copy_finish(struct fuse_copy_state *cs)
514334f485dSMiklos Szeredi {
515334f485dSMiklos Szeredi 	if (cs->mapaddr) {
516334f485dSMiklos Szeredi 		kunmap_atomic(cs->mapaddr, KM_USER0);
517334f485dSMiklos Szeredi 		if (cs->write) {
518334f485dSMiklos Szeredi 			flush_dcache_page(cs->pg);
519334f485dSMiklos Szeredi 			set_page_dirty_lock(cs->pg);
520334f485dSMiklos Szeredi 		}
521334f485dSMiklos Szeredi 		put_page(cs->pg);
522334f485dSMiklos Szeredi 		cs->mapaddr = NULL;
523334f485dSMiklos Szeredi 	}
524334f485dSMiklos Szeredi }
525334f485dSMiklos Szeredi 
526334f485dSMiklos Szeredi /*
527334f485dSMiklos Szeredi  * Get another pagefull of userspace buffer, and map it to kernel
528334f485dSMiklos Szeredi  * address space, and lock request
529334f485dSMiklos Szeredi  */
530334f485dSMiklos Szeredi static int fuse_copy_fill(struct fuse_copy_state *cs)
531334f485dSMiklos Szeredi {
532334f485dSMiklos Szeredi 	unsigned long offset;
533334f485dSMiklos Szeredi 	int err;
534334f485dSMiklos Szeredi 
535d7133114SMiklos Szeredi 	unlock_request(cs->fc, cs->req);
536334f485dSMiklos Szeredi 	fuse_copy_finish(cs);
537334f485dSMiklos Szeredi 	if (!cs->seglen) {
538334f485dSMiklos Szeredi 		BUG_ON(!cs->nr_segs);
539334f485dSMiklos Szeredi 		cs->seglen = cs->iov[0].iov_len;
540334f485dSMiklos Szeredi 		cs->addr = (unsigned long) cs->iov[0].iov_base;
541334f485dSMiklos Szeredi 		cs->iov++;
542334f485dSMiklos Szeredi 		cs->nr_segs--;
543334f485dSMiklos Szeredi 	}
544334f485dSMiklos Szeredi 	down_read(&current->mm->mmap_sem);
545334f485dSMiklos Szeredi 	err = get_user_pages(current, current->mm, cs->addr, 1, cs->write, 0,
546334f485dSMiklos Szeredi 			     &cs->pg, NULL);
547334f485dSMiklos Szeredi 	up_read(&current->mm->mmap_sem);
548334f485dSMiklos Szeredi 	if (err < 0)
549334f485dSMiklos Szeredi 		return err;
550334f485dSMiklos Szeredi 	BUG_ON(err != 1);
551334f485dSMiklos Szeredi 	offset = cs->addr % PAGE_SIZE;
552334f485dSMiklos Szeredi 	cs->mapaddr = kmap_atomic(cs->pg, KM_USER0);
553334f485dSMiklos Szeredi 	cs->buf = cs->mapaddr + offset;
554334f485dSMiklos Szeredi 	cs->len = min(PAGE_SIZE - offset, cs->seglen);
555334f485dSMiklos Szeredi 	cs->seglen -= cs->len;
556334f485dSMiklos Szeredi 	cs->addr += cs->len;
557334f485dSMiklos Szeredi 
558d7133114SMiklos Szeredi 	return lock_request(cs->fc, cs->req);
559334f485dSMiklos Szeredi }
560334f485dSMiklos Szeredi 
561334f485dSMiklos Szeredi /* Do as much copy to/from userspace buffer as we can */
5628bfc016dSMiklos Szeredi static int fuse_copy_do(struct fuse_copy_state *cs, void **val, unsigned *size)
563334f485dSMiklos Szeredi {
564334f485dSMiklos Szeredi 	unsigned ncpy = min(*size, cs->len);
565334f485dSMiklos Szeredi 	if (val) {
566334f485dSMiklos Szeredi 		if (cs->write)
567334f485dSMiklos Szeredi 			memcpy(cs->buf, *val, ncpy);
568334f485dSMiklos Szeredi 		else
569334f485dSMiklos Szeredi 			memcpy(*val, cs->buf, ncpy);
570334f485dSMiklos Szeredi 		*val += ncpy;
571334f485dSMiklos Szeredi 	}
572334f485dSMiklos Szeredi 	*size -= ncpy;
573334f485dSMiklos Szeredi 	cs->len -= ncpy;
574334f485dSMiklos Szeredi 	cs->buf += ncpy;
575334f485dSMiklos Szeredi 	return ncpy;
576334f485dSMiklos Szeredi }
577334f485dSMiklos Szeredi 
578334f485dSMiklos Szeredi /*
579334f485dSMiklos Szeredi  * Copy a page in the request to/from the userspace buffer.  Must be
580334f485dSMiklos Szeredi  * done atomically
581334f485dSMiklos Szeredi  */
5828bfc016dSMiklos Szeredi static int fuse_copy_page(struct fuse_copy_state *cs, struct page *page,
583334f485dSMiklos Szeredi 			  unsigned offset, unsigned count, int zeroing)
584334f485dSMiklos Szeredi {
585334f485dSMiklos Szeredi 	if (page && zeroing && count < PAGE_SIZE) {
586334f485dSMiklos Szeredi 		void *mapaddr = kmap_atomic(page, KM_USER1);
587334f485dSMiklos Szeredi 		memset(mapaddr, 0, PAGE_SIZE);
588334f485dSMiklos Szeredi 		kunmap_atomic(mapaddr, KM_USER1);
589334f485dSMiklos Szeredi 	}
590334f485dSMiklos Szeredi 	while (count) {
5911729a16cSMiklos Szeredi 		if (!cs->len) {
5921729a16cSMiklos Szeredi 			int err = fuse_copy_fill(cs);
5931729a16cSMiklos Szeredi 			if (err)
594334f485dSMiklos Szeredi 				return err;
5951729a16cSMiklos Szeredi 		}
596334f485dSMiklos Szeredi 		if (page) {
597334f485dSMiklos Szeredi 			void *mapaddr = kmap_atomic(page, KM_USER1);
598334f485dSMiklos Szeredi 			void *buf = mapaddr + offset;
599334f485dSMiklos Szeredi 			offset += fuse_copy_do(cs, &buf, &count);
600334f485dSMiklos Szeredi 			kunmap_atomic(mapaddr, KM_USER1);
601334f485dSMiklos Szeredi 		} else
602334f485dSMiklos Szeredi 			offset += fuse_copy_do(cs, NULL, &count);
603334f485dSMiklos Szeredi 	}
604334f485dSMiklos Szeredi 	if (page && !cs->write)
605334f485dSMiklos Szeredi 		flush_dcache_page(page);
606334f485dSMiklos Szeredi 	return 0;
607334f485dSMiklos Szeredi }
608334f485dSMiklos Szeredi 
609334f485dSMiklos Szeredi /* Copy pages in the request to/from userspace buffer */
610334f485dSMiklos Szeredi static int fuse_copy_pages(struct fuse_copy_state *cs, unsigned nbytes,
611334f485dSMiklos Szeredi 			   int zeroing)
612334f485dSMiklos Szeredi {
613334f485dSMiklos Szeredi 	unsigned i;
614334f485dSMiklos Szeredi 	struct fuse_req *req = cs->req;
615334f485dSMiklos Szeredi 	unsigned offset = req->page_offset;
616334f485dSMiklos Szeredi 	unsigned count = min(nbytes, (unsigned) PAGE_SIZE - offset);
617334f485dSMiklos Szeredi 
618334f485dSMiklos Szeredi 	for (i = 0; i < req->num_pages && (nbytes || zeroing); i++) {
619334f485dSMiklos Szeredi 		struct page *page = req->pages[i];
620334f485dSMiklos Szeredi 		int err = fuse_copy_page(cs, page, offset, count, zeroing);
621334f485dSMiklos Szeredi 		if (err)
622334f485dSMiklos Szeredi 			return err;
623334f485dSMiklos Szeredi 
624334f485dSMiklos Szeredi 		nbytes -= count;
625334f485dSMiklos Szeredi 		count = min(nbytes, (unsigned) PAGE_SIZE);
626334f485dSMiklos Szeredi 		offset = 0;
627334f485dSMiklos Szeredi 	}
628334f485dSMiklos Szeredi 	return 0;
629334f485dSMiklos Szeredi }
630334f485dSMiklos Szeredi 
631334f485dSMiklos Szeredi /* Copy a single argument in the request to/from userspace buffer */
632334f485dSMiklos Szeredi static int fuse_copy_one(struct fuse_copy_state *cs, void *val, unsigned size)
633334f485dSMiklos Szeredi {
634334f485dSMiklos Szeredi 	while (size) {
6351729a16cSMiklos Szeredi 		if (!cs->len) {
6361729a16cSMiklos Szeredi 			int err = fuse_copy_fill(cs);
6371729a16cSMiklos Szeredi 			if (err)
638334f485dSMiklos Szeredi 				return err;
6391729a16cSMiklos Szeredi 		}
640334f485dSMiklos Szeredi 		fuse_copy_do(cs, &val, &size);
641334f485dSMiklos Szeredi 	}
642334f485dSMiklos Szeredi 	return 0;
643334f485dSMiklos Szeredi }
644334f485dSMiklos Szeredi 
645334f485dSMiklos Szeredi /* Copy request arguments to/from userspace buffer */
646334f485dSMiklos Szeredi static int fuse_copy_args(struct fuse_copy_state *cs, unsigned numargs,
647334f485dSMiklos Szeredi 			  unsigned argpages, struct fuse_arg *args,
648334f485dSMiklos Szeredi 			  int zeroing)
649334f485dSMiklos Szeredi {
650334f485dSMiklos Szeredi 	int err = 0;
651334f485dSMiklos Szeredi 	unsigned i;
652334f485dSMiklos Szeredi 
653334f485dSMiklos Szeredi 	for (i = 0; !err && i < numargs; i++)  {
654334f485dSMiklos Szeredi 		struct fuse_arg *arg = &args[i];
655334f485dSMiklos Szeredi 		if (i == numargs - 1 && argpages)
656334f485dSMiklos Szeredi 			err = fuse_copy_pages(cs, arg->size, zeroing);
657334f485dSMiklos Szeredi 		else
658334f485dSMiklos Szeredi 			err = fuse_copy_one(cs, arg->value, arg->size);
659334f485dSMiklos Szeredi 	}
660334f485dSMiklos Szeredi 	return err;
661334f485dSMiklos Szeredi }
662334f485dSMiklos Szeredi 
663a4d27e75SMiklos Szeredi static int request_pending(struct fuse_conn *fc)
664a4d27e75SMiklos Szeredi {
665a4d27e75SMiklos Szeredi 	return !list_empty(&fc->pending) || !list_empty(&fc->interrupts);
666a4d27e75SMiklos Szeredi }
667a4d27e75SMiklos Szeredi 
668334f485dSMiklos Szeredi /* Wait until a request is available on the pending list */
669334f485dSMiklos Szeredi static void request_wait(struct fuse_conn *fc)
670334f485dSMiklos Szeredi {
671334f485dSMiklos Szeredi 	DECLARE_WAITQUEUE(wait, current);
672334f485dSMiklos Szeredi 
673334f485dSMiklos Szeredi 	add_wait_queue_exclusive(&fc->waitq, &wait);
674a4d27e75SMiklos Szeredi 	while (fc->connected && !request_pending(fc)) {
675334f485dSMiklos Szeredi 		set_current_state(TASK_INTERRUPTIBLE);
676334f485dSMiklos Szeredi 		if (signal_pending(current))
677334f485dSMiklos Szeredi 			break;
678334f485dSMiklos Szeredi 
679d7133114SMiklos Szeredi 		spin_unlock(&fc->lock);
680334f485dSMiklos Szeredi 		schedule();
681d7133114SMiklos Szeredi 		spin_lock(&fc->lock);
682334f485dSMiklos Szeredi 	}
683334f485dSMiklos Szeredi 	set_current_state(TASK_RUNNING);
684334f485dSMiklos Szeredi 	remove_wait_queue(&fc->waitq, &wait);
685334f485dSMiklos Szeredi }
686334f485dSMiklos Szeredi 
687334f485dSMiklos Szeredi /*
688a4d27e75SMiklos Szeredi  * Transfer an interrupt request to userspace
689a4d27e75SMiklos Szeredi  *
690a4d27e75SMiklos Szeredi  * Unlike other requests this is assembled on demand, without a need
691a4d27e75SMiklos Szeredi  * to allocate a separate fuse_req structure.
692a4d27e75SMiklos Szeredi  *
693a4d27e75SMiklos Szeredi  * Called with fc->lock held, releases it
694a4d27e75SMiklos Szeredi  */
695a4d27e75SMiklos Szeredi static int fuse_read_interrupt(struct fuse_conn *fc, struct fuse_req *req,
696a4d27e75SMiklos Szeredi 			       const struct iovec *iov, unsigned long nr_segs)
697105f4d7aSJosh Triplett 	__releases(fc->lock)
698a4d27e75SMiklos Szeredi {
699a4d27e75SMiklos Szeredi 	struct fuse_copy_state cs;
700a4d27e75SMiklos Szeredi 	struct fuse_in_header ih;
701a4d27e75SMiklos Szeredi 	struct fuse_interrupt_in arg;
702a4d27e75SMiklos Szeredi 	unsigned reqsize = sizeof(ih) + sizeof(arg);
703a4d27e75SMiklos Szeredi 	int err;
704a4d27e75SMiklos Szeredi 
705a4d27e75SMiklos Szeredi 	list_del_init(&req->intr_entry);
706a4d27e75SMiklos Szeredi 	req->intr_unique = fuse_get_unique(fc);
707a4d27e75SMiklos Szeredi 	memset(&ih, 0, sizeof(ih));
708a4d27e75SMiklos Szeredi 	memset(&arg, 0, sizeof(arg));
709a4d27e75SMiklos Szeredi 	ih.len = reqsize;
710a4d27e75SMiklos Szeredi 	ih.opcode = FUSE_INTERRUPT;
711a4d27e75SMiklos Szeredi 	ih.unique = req->intr_unique;
712a4d27e75SMiklos Szeredi 	arg.unique = req->in.h.unique;
713a4d27e75SMiklos Szeredi 
714a4d27e75SMiklos Szeredi 	spin_unlock(&fc->lock);
715a4d27e75SMiklos Szeredi 	if (iov_length(iov, nr_segs) < reqsize)
716a4d27e75SMiklos Szeredi 		return -EINVAL;
717a4d27e75SMiklos Szeredi 
718a4d27e75SMiklos Szeredi 	fuse_copy_init(&cs, fc, 1, NULL, iov, nr_segs);
719a4d27e75SMiklos Szeredi 	err = fuse_copy_one(&cs, &ih, sizeof(ih));
720a4d27e75SMiklos Szeredi 	if (!err)
721a4d27e75SMiklos Szeredi 		err = fuse_copy_one(&cs, &arg, sizeof(arg));
722a4d27e75SMiklos Szeredi 	fuse_copy_finish(&cs);
723a4d27e75SMiklos Szeredi 
724a4d27e75SMiklos Szeredi 	return err ? err : reqsize;
725a4d27e75SMiklos Szeredi }
726a4d27e75SMiklos Szeredi 
727a4d27e75SMiklos Szeredi /*
728334f485dSMiklos Szeredi  * Read a single request into the userspace filesystem's buffer.  This
729334f485dSMiklos Szeredi  * function waits until a request is available, then removes it from
730334f485dSMiklos Szeredi  * the pending list and copies request data to userspace buffer.  If
731f9a2842eSMiklos Szeredi  * no reply is needed (FORGET) or request has been aborted or there
732f9a2842eSMiklos Szeredi  * was an error during the copying then it's finished by calling
733334f485dSMiklos Szeredi  * request_end().  Otherwise add it to the processing list, and set
734334f485dSMiklos Szeredi  * the 'sent' flag.
735334f485dSMiklos Szeredi  */
736ee0b3e67SBadari Pulavarty static ssize_t fuse_dev_read(struct kiocb *iocb, const struct iovec *iov,
737ee0b3e67SBadari Pulavarty 			      unsigned long nr_segs, loff_t pos)
738334f485dSMiklos Szeredi {
739334f485dSMiklos Szeredi 	int err;
740334f485dSMiklos Szeredi 	struct fuse_req *req;
741334f485dSMiklos Szeredi 	struct fuse_in *in;
742334f485dSMiklos Szeredi 	struct fuse_copy_state cs;
743334f485dSMiklos Szeredi 	unsigned reqsize;
744ee0b3e67SBadari Pulavarty 	struct file *file = iocb->ki_filp;
7450720b315SMiklos Szeredi 	struct fuse_conn *fc = fuse_get_conn(file);
7460720b315SMiklos Szeredi 	if (!fc)
7470720b315SMiklos Szeredi 		return -EPERM;
748334f485dSMiklos Szeredi 
7491d3d752bSMiklos Szeredi  restart:
750d7133114SMiklos Szeredi 	spin_lock(&fc->lock);
751e5ac1d1eSJeff Dike 	err = -EAGAIN;
752e5ac1d1eSJeff Dike 	if ((file->f_flags & O_NONBLOCK) && fc->connected &&
753a4d27e75SMiklos Szeredi 	    !request_pending(fc))
754e5ac1d1eSJeff Dike 		goto err_unlock;
755e5ac1d1eSJeff Dike 
756334f485dSMiklos Szeredi 	request_wait(fc);
757334f485dSMiklos Szeredi 	err = -ENODEV;
7589ba7cbbaSMiklos Szeredi 	if (!fc->connected)
759334f485dSMiklos Szeredi 		goto err_unlock;
760334f485dSMiklos Szeredi 	err = -ERESTARTSYS;
761a4d27e75SMiklos Szeredi 	if (!request_pending(fc))
762334f485dSMiklos Szeredi 		goto err_unlock;
763334f485dSMiklos Szeredi 
764a4d27e75SMiklos Szeredi 	if (!list_empty(&fc->interrupts)) {
765a4d27e75SMiklos Szeredi 		req = list_entry(fc->interrupts.next, struct fuse_req,
766a4d27e75SMiklos Szeredi 				 intr_entry);
767a4d27e75SMiklos Szeredi 		return fuse_read_interrupt(fc, req, iov, nr_segs);
768a4d27e75SMiklos Szeredi 	}
769a4d27e75SMiklos Szeredi 
770334f485dSMiklos Szeredi 	req = list_entry(fc->pending.next, struct fuse_req, list);
77183cfd493SMiklos Szeredi 	req->state = FUSE_REQ_READING;
772d77a1d5bSMiklos Szeredi 	list_move(&req->list, &fc->io);
773334f485dSMiklos Szeredi 
774334f485dSMiklos Szeredi 	in = &req->in;
7751d3d752bSMiklos Szeredi 	reqsize = in->h.len;
7761d3d752bSMiklos Szeredi 	/* If request is too large, reply with an error and restart the read */
7771d3d752bSMiklos Szeredi 	if (iov_length(iov, nr_segs) < reqsize) {
7781d3d752bSMiklos Szeredi 		req->out.h.error = -EIO;
7791d3d752bSMiklos Szeredi 		/* SETXATTR is special, since it may contain too large data */
7801d3d752bSMiklos Szeredi 		if (in->h.opcode == FUSE_SETXATTR)
7811d3d752bSMiklos Szeredi 			req->out.h.error = -E2BIG;
7821d3d752bSMiklos Szeredi 		request_end(fc, req);
7831d3d752bSMiklos Szeredi 		goto restart;
7841d3d752bSMiklos Szeredi 	}
785d7133114SMiklos Szeredi 	spin_unlock(&fc->lock);
786d7133114SMiklos Szeredi 	fuse_copy_init(&cs, fc, 1, req, iov, nr_segs);
787334f485dSMiklos Szeredi 	err = fuse_copy_one(&cs, &in->h, sizeof(in->h));
788334f485dSMiklos Szeredi 	if (!err)
789334f485dSMiklos Szeredi 		err = fuse_copy_args(&cs, in->numargs, in->argpages,
790334f485dSMiklos Szeredi 				     (struct fuse_arg *) in->args, 0);
791334f485dSMiklos Szeredi 	fuse_copy_finish(&cs);
792d7133114SMiklos Szeredi 	spin_lock(&fc->lock);
793334f485dSMiklos Szeredi 	req->locked = 0;
794c9c9d7dfSMiklos Szeredi 	if (req->aborted) {
795c9c9d7dfSMiklos Szeredi 		request_end(fc, req);
796c9c9d7dfSMiklos Szeredi 		return -ENODEV;
797c9c9d7dfSMiklos Szeredi 	}
798334f485dSMiklos Szeredi 	if (err) {
799334f485dSMiklos Szeredi 		req->out.h.error = -EIO;
800334f485dSMiklos Szeredi 		request_end(fc, req);
801334f485dSMiklos Szeredi 		return err;
802334f485dSMiklos Szeredi 	}
803334f485dSMiklos Szeredi 	if (!req->isreply)
804334f485dSMiklos Szeredi 		request_end(fc, req);
805334f485dSMiklos Szeredi 	else {
80683cfd493SMiklos Szeredi 		req->state = FUSE_REQ_SENT;
807d77a1d5bSMiklos Szeredi 		list_move_tail(&req->list, &fc->processing);
808a4d27e75SMiklos Szeredi 		if (req->interrupted)
809a4d27e75SMiklos Szeredi 			queue_interrupt(fc, req);
810d7133114SMiklos Szeredi 		spin_unlock(&fc->lock);
811334f485dSMiklos Szeredi 	}
812334f485dSMiklos Szeredi 	return reqsize;
813334f485dSMiklos Szeredi 
814334f485dSMiklos Szeredi  err_unlock:
815d7133114SMiklos Szeredi 	spin_unlock(&fc->lock);
816334f485dSMiklos Szeredi 	return err;
817334f485dSMiklos Szeredi }
818334f485dSMiklos Szeredi 
819334f485dSMiklos Szeredi /* Look up request on processing list by unique ID */
820334f485dSMiklos Szeredi static struct fuse_req *request_find(struct fuse_conn *fc, u64 unique)
821334f485dSMiklos Szeredi {
822334f485dSMiklos Szeredi 	struct list_head *entry;
823334f485dSMiklos Szeredi 
824334f485dSMiklos Szeredi 	list_for_each(entry, &fc->processing) {
825334f485dSMiklos Szeredi 		struct fuse_req *req;
826334f485dSMiklos Szeredi 		req = list_entry(entry, struct fuse_req, list);
827a4d27e75SMiklos Szeredi 		if (req->in.h.unique == unique || req->intr_unique == unique)
828334f485dSMiklos Szeredi 			return req;
829334f485dSMiklos Szeredi 	}
830334f485dSMiklos Szeredi 	return NULL;
831334f485dSMiklos Szeredi }
832334f485dSMiklos Szeredi 
833334f485dSMiklos Szeredi static int copy_out_args(struct fuse_copy_state *cs, struct fuse_out *out,
834334f485dSMiklos Szeredi 			 unsigned nbytes)
835334f485dSMiklos Szeredi {
836334f485dSMiklos Szeredi 	unsigned reqsize = sizeof(struct fuse_out_header);
837334f485dSMiklos Szeredi 
838334f485dSMiklos Szeredi 	if (out->h.error)
839334f485dSMiklos Szeredi 		return nbytes != reqsize ? -EINVAL : 0;
840334f485dSMiklos Szeredi 
841334f485dSMiklos Szeredi 	reqsize += len_args(out->numargs, out->args);
842334f485dSMiklos Szeredi 
843334f485dSMiklos Szeredi 	if (reqsize < nbytes || (reqsize > nbytes && !out->argvar))
844334f485dSMiklos Szeredi 		return -EINVAL;
845334f485dSMiklos Szeredi 	else if (reqsize > nbytes) {
846334f485dSMiklos Szeredi 		struct fuse_arg *lastarg = &out->args[out->numargs-1];
847334f485dSMiklos Szeredi 		unsigned diffsize = reqsize - nbytes;
848334f485dSMiklos Szeredi 		if (diffsize > lastarg->size)
849334f485dSMiklos Szeredi 			return -EINVAL;
850334f485dSMiklos Szeredi 		lastarg->size -= diffsize;
851334f485dSMiklos Szeredi 	}
852334f485dSMiklos Szeredi 	return fuse_copy_args(cs, out->numargs, out->argpages, out->args,
853334f485dSMiklos Szeredi 			      out->page_zeroing);
854334f485dSMiklos Szeredi }
855334f485dSMiklos Szeredi 
856334f485dSMiklos Szeredi /*
857334f485dSMiklos Szeredi  * Write a single reply to a request.  First the header is copied from
858334f485dSMiklos Szeredi  * the write buffer.  The request is then searched on the processing
859334f485dSMiklos Szeredi  * list by the unique ID found in the header.  If found, then remove
860334f485dSMiklos Szeredi  * it from the list and copy the rest of the buffer to the request.
861334f485dSMiklos Szeredi  * The request is finished by calling request_end()
862334f485dSMiklos Szeredi  */
863ee0b3e67SBadari Pulavarty static ssize_t fuse_dev_write(struct kiocb *iocb, const struct iovec *iov,
864ee0b3e67SBadari Pulavarty 			       unsigned long nr_segs, loff_t pos)
865334f485dSMiklos Szeredi {
866334f485dSMiklos Szeredi 	int err;
867334f485dSMiklos Szeredi 	unsigned nbytes = iov_length(iov, nr_segs);
868334f485dSMiklos Szeredi 	struct fuse_req *req;
869334f485dSMiklos Szeredi 	struct fuse_out_header oh;
870334f485dSMiklos Szeredi 	struct fuse_copy_state cs;
871ee0b3e67SBadari Pulavarty 	struct fuse_conn *fc = fuse_get_conn(iocb->ki_filp);
872334f485dSMiklos Szeredi 	if (!fc)
873a87046d8SMiklos Szeredi 		return -EPERM;
874334f485dSMiklos Szeredi 
875d7133114SMiklos Szeredi 	fuse_copy_init(&cs, fc, 0, NULL, iov, nr_segs);
876334f485dSMiklos Szeredi 	if (nbytes < sizeof(struct fuse_out_header))
877334f485dSMiklos Szeredi 		return -EINVAL;
878334f485dSMiklos Szeredi 
879334f485dSMiklos Szeredi 	err = fuse_copy_one(&cs, &oh, sizeof(oh));
880334f485dSMiklos Szeredi 	if (err)
881334f485dSMiklos Szeredi 		goto err_finish;
882334f485dSMiklos Szeredi 	err = -EINVAL;
883334f485dSMiklos Szeredi 	if (!oh.unique || oh.error <= -1000 || oh.error > 0 ||
884334f485dSMiklos Szeredi 	    oh.len != nbytes)
885334f485dSMiklos Szeredi 		goto err_finish;
886334f485dSMiklos Szeredi 
887d7133114SMiklos Szeredi 	spin_lock(&fc->lock);
88869a53bf2SMiklos Szeredi 	err = -ENOENT;
88969a53bf2SMiklos Szeredi 	if (!fc->connected)
89069a53bf2SMiklos Szeredi 		goto err_unlock;
89169a53bf2SMiklos Szeredi 
892334f485dSMiklos Szeredi 	req = request_find(fc, oh.unique);
893334f485dSMiklos Szeredi 	if (!req)
894334f485dSMiklos Szeredi 		goto err_unlock;
895334f485dSMiklos Szeredi 
896f9a2842eSMiklos Szeredi 	if (req->aborted) {
897d7133114SMiklos Szeredi 		spin_unlock(&fc->lock);
898334f485dSMiklos Szeredi 		fuse_copy_finish(&cs);
899d7133114SMiklos Szeredi 		spin_lock(&fc->lock);
900222f1d69SMiklos Szeredi 		request_end(fc, req);
901334f485dSMiklos Szeredi 		return -ENOENT;
902334f485dSMiklos Szeredi 	}
903a4d27e75SMiklos Szeredi 	/* Is it an interrupt reply? */
904a4d27e75SMiklos Szeredi 	if (req->intr_unique == oh.unique) {
905a4d27e75SMiklos Szeredi 		err = -EINVAL;
906a4d27e75SMiklos Szeredi 		if (nbytes != sizeof(struct fuse_out_header))
907a4d27e75SMiklos Szeredi 			goto err_unlock;
908a4d27e75SMiklos Szeredi 
909a4d27e75SMiklos Szeredi 		if (oh.error == -ENOSYS)
910a4d27e75SMiklos Szeredi 			fc->no_interrupt = 1;
911a4d27e75SMiklos Szeredi 		else if (oh.error == -EAGAIN)
912a4d27e75SMiklos Szeredi 			queue_interrupt(fc, req);
913a4d27e75SMiklos Szeredi 
914a4d27e75SMiklos Szeredi 		spin_unlock(&fc->lock);
915a4d27e75SMiklos Szeredi 		fuse_copy_finish(&cs);
916a4d27e75SMiklos Szeredi 		return nbytes;
917a4d27e75SMiklos Szeredi 	}
918a4d27e75SMiklos Szeredi 
919a4d27e75SMiklos Szeredi 	req->state = FUSE_REQ_WRITING;
920d77a1d5bSMiklos Szeredi 	list_move(&req->list, &fc->io);
921334f485dSMiklos Szeredi 	req->out.h = oh;
922334f485dSMiklos Szeredi 	req->locked = 1;
923334f485dSMiklos Szeredi 	cs.req = req;
924d7133114SMiklos Szeredi 	spin_unlock(&fc->lock);
925334f485dSMiklos Szeredi 
926334f485dSMiklos Szeredi 	err = copy_out_args(&cs, &req->out, nbytes);
927334f485dSMiklos Szeredi 	fuse_copy_finish(&cs);
928334f485dSMiklos Szeredi 
929d7133114SMiklos Szeredi 	spin_lock(&fc->lock);
930334f485dSMiklos Szeredi 	req->locked = 0;
931334f485dSMiklos Szeredi 	if (!err) {
932f9a2842eSMiklos Szeredi 		if (req->aborted)
933334f485dSMiklos Szeredi 			err = -ENOENT;
934f9a2842eSMiklos Szeredi 	} else if (!req->aborted)
935334f485dSMiklos Szeredi 		req->out.h.error = -EIO;
936334f485dSMiklos Szeredi 	request_end(fc, req);
937334f485dSMiklos Szeredi 
938334f485dSMiklos Szeredi 	return err ? err : nbytes;
939334f485dSMiklos Szeredi 
940334f485dSMiklos Szeredi  err_unlock:
941d7133114SMiklos Szeredi 	spin_unlock(&fc->lock);
942334f485dSMiklos Szeredi  err_finish:
943334f485dSMiklos Szeredi 	fuse_copy_finish(&cs);
944334f485dSMiklos Szeredi 	return err;
945334f485dSMiklos Szeredi }
946334f485dSMiklos Szeredi 
947334f485dSMiklos Szeredi static unsigned fuse_dev_poll(struct file *file, poll_table *wait)
948334f485dSMiklos Szeredi {
949334f485dSMiklos Szeredi 	unsigned mask = POLLOUT | POLLWRNORM;
9507025d9adSMiklos Szeredi 	struct fuse_conn *fc = fuse_get_conn(file);
951334f485dSMiklos Szeredi 	if (!fc)
9527025d9adSMiklos Szeredi 		return POLLERR;
953334f485dSMiklos Szeredi 
954334f485dSMiklos Szeredi 	poll_wait(file, &fc->waitq, wait);
955334f485dSMiklos Szeredi 
956d7133114SMiklos Szeredi 	spin_lock(&fc->lock);
9577025d9adSMiklos Szeredi 	if (!fc->connected)
9587025d9adSMiklos Szeredi 		mask = POLLERR;
959a4d27e75SMiklos Szeredi 	else if (request_pending(fc))
960334f485dSMiklos Szeredi 		mask |= POLLIN | POLLRDNORM;
961d7133114SMiklos Szeredi 	spin_unlock(&fc->lock);
962334f485dSMiklos Szeredi 
963334f485dSMiklos Szeredi 	return mask;
964334f485dSMiklos Szeredi }
965334f485dSMiklos Szeredi 
96669a53bf2SMiklos Szeredi /*
96769a53bf2SMiklos Szeredi  * Abort all requests on the given list (pending or processing)
96869a53bf2SMiklos Szeredi  *
969d7133114SMiklos Szeredi  * This function releases and reacquires fc->lock
97069a53bf2SMiklos Szeredi  */
971334f485dSMiklos Szeredi static void end_requests(struct fuse_conn *fc, struct list_head *head)
972334f485dSMiklos Szeredi {
973334f485dSMiklos Szeredi 	while (!list_empty(head)) {
974334f485dSMiklos Szeredi 		struct fuse_req *req;
975334f485dSMiklos Szeredi 		req = list_entry(head->next, struct fuse_req, list);
976334f485dSMiklos Szeredi 		req->out.h.error = -ECONNABORTED;
977334f485dSMiklos Szeredi 		request_end(fc, req);
978d7133114SMiklos Szeredi 		spin_lock(&fc->lock);
979334f485dSMiklos Szeredi 	}
980334f485dSMiklos Szeredi }
981334f485dSMiklos Szeredi 
98269a53bf2SMiklos Szeredi /*
98369a53bf2SMiklos Szeredi  * Abort requests under I/O
98469a53bf2SMiklos Szeredi  *
985f9a2842eSMiklos Szeredi  * The requests are set to aborted and finished, and the request
98669a53bf2SMiklos Szeredi  * waiter is woken up.  This will make request_wait_answer() wait
98769a53bf2SMiklos Szeredi  * until the request is unlocked and then return.
98864c6d8edSMiklos Szeredi  *
98964c6d8edSMiklos Szeredi  * If the request is asynchronous, then the end function needs to be
99064c6d8edSMiklos Szeredi  * called after waiting for the request to be unlocked (if it was
99164c6d8edSMiklos Szeredi  * locked).
99269a53bf2SMiklos Szeredi  */
99369a53bf2SMiklos Szeredi static void end_io_requests(struct fuse_conn *fc)
9944dbf930eSMiklos Szeredi 	__releases(fc->lock) __acquires(fc->lock)
99569a53bf2SMiklos Szeredi {
99669a53bf2SMiklos Szeredi 	while (!list_empty(&fc->io)) {
99764c6d8edSMiklos Szeredi 		struct fuse_req *req =
99864c6d8edSMiklos Szeredi 			list_entry(fc->io.next, struct fuse_req, list);
99964c6d8edSMiklos Szeredi 		void (*end) (struct fuse_conn *, struct fuse_req *) = req->end;
100064c6d8edSMiklos Szeredi 
1001f9a2842eSMiklos Szeredi 		req->aborted = 1;
100269a53bf2SMiklos Szeredi 		req->out.h.error = -ECONNABORTED;
100369a53bf2SMiklos Szeredi 		req->state = FUSE_REQ_FINISHED;
100469a53bf2SMiklos Szeredi 		list_del_init(&req->list);
100569a53bf2SMiklos Szeredi 		wake_up(&req->waitq);
100664c6d8edSMiklos Szeredi 		if (end) {
100764c6d8edSMiklos Szeredi 			req->end = NULL;
100864c6d8edSMiklos Szeredi 			__fuse_get_request(req);
1009d7133114SMiklos Szeredi 			spin_unlock(&fc->lock);
101064c6d8edSMiklos Szeredi 			wait_event(req->waitq, !req->locked);
101164c6d8edSMiklos Szeredi 			end(fc, req);
1012*e9bb09ddSTejun Heo 			fuse_put_request(fc, req);
1013d7133114SMiklos Szeredi 			spin_lock(&fc->lock);
101464c6d8edSMiklos Szeredi 		}
101569a53bf2SMiklos Szeredi 	}
101669a53bf2SMiklos Szeredi }
101769a53bf2SMiklos Szeredi 
101869a53bf2SMiklos Szeredi /*
101969a53bf2SMiklos Szeredi  * Abort all requests.
102069a53bf2SMiklos Szeredi  *
102169a53bf2SMiklos Szeredi  * Emergency exit in case of a malicious or accidental deadlock, or
102269a53bf2SMiklos Szeredi  * just a hung filesystem.
102369a53bf2SMiklos Szeredi  *
102469a53bf2SMiklos Szeredi  * The same effect is usually achievable through killing the
102569a53bf2SMiklos Szeredi  * filesystem daemon and all users of the filesystem.  The exception
102669a53bf2SMiklos Szeredi  * is the combination of an asynchronous request and the tricky
102769a53bf2SMiklos Szeredi  * deadlock (see Documentation/filesystems/fuse.txt).
102869a53bf2SMiklos Szeredi  *
102969a53bf2SMiklos Szeredi  * During the aborting, progression of requests from the pending and
103069a53bf2SMiklos Szeredi  * processing lists onto the io list, and progression of new requests
103169a53bf2SMiklos Szeredi  * onto the pending list is prevented by req->connected being false.
103269a53bf2SMiklos Szeredi  *
103369a53bf2SMiklos Szeredi  * Progression of requests under I/O to the processing list is
1034f9a2842eSMiklos Szeredi  * prevented by the req->aborted flag being true for these requests.
1035f9a2842eSMiklos Szeredi  * For this reason requests on the io list must be aborted first.
103669a53bf2SMiklos Szeredi  */
103769a53bf2SMiklos Szeredi void fuse_abort_conn(struct fuse_conn *fc)
103869a53bf2SMiklos Szeredi {
1039d7133114SMiklos Szeredi 	spin_lock(&fc->lock);
104069a53bf2SMiklos Szeredi 	if (fc->connected) {
104169a53bf2SMiklos Szeredi 		fc->connected = 0;
104251eb01e7SMiklos Szeredi 		fc->blocked = 0;
104369a53bf2SMiklos Szeredi 		end_io_requests(fc);
104469a53bf2SMiklos Szeredi 		end_requests(fc, &fc->pending);
104569a53bf2SMiklos Szeredi 		end_requests(fc, &fc->processing);
104669a53bf2SMiklos Szeredi 		wake_up_all(&fc->waitq);
104751eb01e7SMiklos Szeredi 		wake_up_all(&fc->blocked_waitq);
1048385a17bfSJeff Dike 		kill_fasync(&fc->fasync, SIGIO, POLL_IN);
104969a53bf2SMiklos Szeredi 	}
1050d7133114SMiklos Szeredi 	spin_unlock(&fc->lock);
105169a53bf2SMiklos Szeredi }
105269a53bf2SMiklos Szeredi 
1053334f485dSMiklos Szeredi static int fuse_dev_release(struct inode *inode, struct file *file)
1054334f485dSMiklos Szeredi {
10550720b315SMiklos Szeredi 	struct fuse_conn *fc = fuse_get_conn(file);
1056334f485dSMiklos Szeredi 	if (fc) {
1057d7133114SMiklos Szeredi 		spin_lock(&fc->lock);
10581e9a4ed9SMiklos Szeredi 		fc->connected = 0;
1059334f485dSMiklos Szeredi 		end_requests(fc, &fc->pending);
1060334f485dSMiklos Szeredi 		end_requests(fc, &fc->processing);
1061d7133114SMiklos Szeredi 		spin_unlock(&fc->lock);
1062bafa9654SMiklos Szeredi 		fuse_conn_put(fc);
1063385a17bfSJeff Dike 	}
1064f543f253SMiklos Szeredi 
1065334f485dSMiklos Szeredi 	return 0;
1066334f485dSMiklos Szeredi }
1067334f485dSMiklos Szeredi 
1068385a17bfSJeff Dike static int fuse_dev_fasync(int fd, struct file *file, int on)
1069385a17bfSJeff Dike {
1070385a17bfSJeff Dike 	struct fuse_conn *fc = fuse_get_conn(file);
1071385a17bfSJeff Dike 	if (!fc)
1072a87046d8SMiklos Szeredi 		return -EPERM;
1073385a17bfSJeff Dike 
1074385a17bfSJeff Dike 	/* No locking - fasync_helper does its own locking */
1075385a17bfSJeff Dike 	return fasync_helper(fd, file, on, &fc->fasync);
1076385a17bfSJeff Dike }
1077385a17bfSJeff Dike 
10784b6f5d20SArjan van de Ven const struct file_operations fuse_dev_operations = {
1079334f485dSMiklos Szeredi 	.owner		= THIS_MODULE,
1080334f485dSMiklos Szeredi 	.llseek		= no_llseek,
1081ee0b3e67SBadari Pulavarty 	.read		= do_sync_read,
1082ee0b3e67SBadari Pulavarty 	.aio_read	= fuse_dev_read,
1083ee0b3e67SBadari Pulavarty 	.write		= do_sync_write,
1084ee0b3e67SBadari Pulavarty 	.aio_write	= fuse_dev_write,
1085334f485dSMiklos Szeredi 	.poll		= fuse_dev_poll,
1086334f485dSMiklos Szeredi 	.release	= fuse_dev_release,
1087385a17bfSJeff Dike 	.fasync		= fuse_dev_fasync,
1088334f485dSMiklos Szeredi };
1089334f485dSMiklos Szeredi 
1090334f485dSMiklos Szeredi static struct miscdevice fuse_miscdevice = {
1091334f485dSMiklos Szeredi 	.minor = FUSE_MINOR,
1092334f485dSMiklos Szeredi 	.name  = "fuse",
1093334f485dSMiklos Szeredi 	.fops = &fuse_dev_operations,
1094334f485dSMiklos Szeredi };
1095334f485dSMiklos Szeredi 
1096334f485dSMiklos Szeredi int __init fuse_dev_init(void)
1097334f485dSMiklos Szeredi {
1098334f485dSMiklos Szeredi 	int err = -ENOMEM;
1099334f485dSMiklos Szeredi 	fuse_req_cachep = kmem_cache_create("fuse_request",
1100334f485dSMiklos Szeredi 					    sizeof(struct fuse_req),
110120c2df83SPaul Mundt 					    0, 0, NULL);
1102334f485dSMiklos Szeredi 	if (!fuse_req_cachep)
1103334f485dSMiklos Szeredi 		goto out;
1104334f485dSMiklos Szeredi 
1105334f485dSMiklos Szeredi 	err = misc_register(&fuse_miscdevice);
1106334f485dSMiklos Szeredi 	if (err)
1107334f485dSMiklos Szeredi 		goto out_cache_clean;
1108334f485dSMiklos Szeredi 
1109334f485dSMiklos Szeredi 	return 0;
1110334f485dSMiklos Szeredi 
1111334f485dSMiklos Szeredi  out_cache_clean:
1112334f485dSMiklos Szeredi 	kmem_cache_destroy(fuse_req_cachep);
1113334f485dSMiklos Szeredi  out:
1114334f485dSMiklos Szeredi 	return err;
1115334f485dSMiklos Szeredi }
1116334f485dSMiklos Szeredi 
1117334f485dSMiklos Szeredi void fuse_dev_cleanup(void)
1118334f485dSMiklos Szeredi {
1119334f485dSMiklos Szeredi 	misc_deregister(&fuse_miscdevice);
1120334f485dSMiklos Szeredi 	kmem_cache_destroy(fuse_req_cachep);
1121334f485dSMiklos Szeredi }
1122