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>
14174cd4b1SIngo Molnar #include <linux/sched/signal.h>
15334f485dSMiklos Szeredi #include <linux/uio.h>
16334f485dSMiklos Szeredi #include <linux/miscdevice.h>
17334f485dSMiklos Szeredi #include <linux/pagemap.h>
18334f485dSMiklos Szeredi #include <linux/file.h>
19334f485dSMiklos Szeredi #include <linux/slab.h>
20dd3bb14fSMiklos Szeredi #include <linux/pipe_fs_i.h>
21ce534fb0SMiklos Szeredi #include <linux/swap.h>
22ce534fb0SMiklos Szeredi #include <linux/splice.h>
230b6e9ea0SSeth Forshee #include <linux/sched.h>
24334f485dSMiklos Szeredi
25334f485dSMiklos Szeredi MODULE_ALIAS_MISCDEV(FUSE_MINOR);
26578454ffSKay Sievers MODULE_ALIAS("devname:fuse");
27334f485dSMiklos Szeredi
28c59fd85eSKirill Tkhai /* Ordinary requests have even IDs, while interrupts IDs are odd */
29c59fd85eSKirill Tkhai #define FUSE_INT_REQ_BIT (1ULL << 0)
30c59fd85eSKirill Tkhai #define FUSE_REQ_ID_STEP (1ULL << 1)
31c59fd85eSKirill Tkhai
32e18b890bSChristoph Lameter static struct kmem_cache *fuse_req_cachep;
33334f485dSMiklos Szeredi
fuse_get_dev(struct file * file)34cc080e9eSMiklos Szeredi static struct fuse_dev *fuse_get_dev(struct file *file)
35334f485dSMiklos Szeredi {
360720b315SMiklos Szeredi /*
370720b315SMiklos Szeredi * Lockless access is OK, because file->private data is set
380720b315SMiklos Szeredi * once during mount and is valid until the file is released.
390720b315SMiklos Szeredi */
406aa7de05SMark Rutland return READ_ONCE(file->private_data);
41334f485dSMiklos Szeredi }
42334f485dSMiklos Szeredi
fuse_request_init(struct fuse_mount * fm,struct fuse_req * req)43fcee216bSMax Reitz static void fuse_request_init(struct fuse_mount *fm, struct fuse_req *req)
44334f485dSMiklos Szeredi {
45334f485dSMiklos Szeredi INIT_LIST_HEAD(&req->list);
46a4d27e75SMiklos Szeredi INIT_LIST_HEAD(&req->intr_entry);
47334f485dSMiklos Szeredi init_waitqueue_head(&req->waitq);
48ec99f6d3SElena Reshetova refcount_set(&req->count, 1);
4933e14b4dSMiklos Szeredi __set_bit(FR_PENDING, &req->flags);
50fcee216bSMax Reitz req->fm = fm;
51334f485dSMiklos Szeredi }
52334f485dSMiklos Szeredi
fuse_request_alloc(struct fuse_mount * fm,gfp_t flags)53fcee216bSMax Reitz static struct fuse_req *fuse_request_alloc(struct fuse_mount *fm, gfp_t flags)
54334f485dSMiklos Szeredi {
558a7aa286SMiklos Szeredi struct fuse_req *req = kmem_cache_zalloc(fuse_req_cachep, flags);
567213394cSMiklos Szeredi if (req)
57fcee216bSMax Reitz fuse_request_init(fm, req);
584250c066SMaxim Patlasov
59334f485dSMiklos Szeredi return req;
60334f485dSMiklos Szeredi }
614250c066SMaxim Patlasov
fuse_request_free(struct fuse_req * req)6266abc359SMiklos Szeredi static void fuse_request_free(struct fuse_req *req)
63e52a8250SMiklos Szeredi {
64334f485dSMiklos Szeredi kmem_cache_free(fuse_req_cachep, req);
65334f485dSMiklos Szeredi }
66334f485dSMiklos Szeredi
__fuse_get_request(struct fuse_req * req)6766abc359SMiklos Szeredi static void __fuse_get_request(struct fuse_req *req)
68334f485dSMiklos Szeredi {
69ec99f6d3SElena Reshetova refcount_inc(&req->count);
70334f485dSMiklos Szeredi }
71334f485dSMiklos Szeredi
72334f485dSMiklos Szeredi /* Must be called with > 1 refcount */
__fuse_put_request(struct fuse_req * req)73334f485dSMiklos Szeredi static void __fuse_put_request(struct fuse_req *req)
74334f485dSMiklos Szeredi {
75ec99f6d3SElena Reshetova refcount_dec(&req->count);
76334f485dSMiklos Szeredi }
77334f485dSMiklos Szeredi
fuse_set_initialized(struct fuse_conn * fc)789759bd51SMiklos Szeredi void fuse_set_initialized(struct fuse_conn *fc)
799759bd51SMiklos Szeredi {
809759bd51SMiklos Szeredi /* Make sure stores before this are seen on another CPU */
819759bd51SMiklos Szeredi smp_wmb();
829759bd51SMiklos Szeredi fc->initialized = 1;
839759bd51SMiklos Szeredi }
849759bd51SMiklos Szeredi
fuse_block_alloc(struct fuse_conn * fc,bool for_background)850aada884SMaxim Patlasov static bool fuse_block_alloc(struct fuse_conn *fc, bool for_background)
860aada884SMaxim Patlasov {
870aada884SMaxim Patlasov return !fc->initialized || (for_background && fc->blocked);
880aada884SMaxim Patlasov }
890aada884SMaxim Patlasov
fuse_drop_waiting(struct fuse_conn * fc)90b8f95e5dSMiklos Szeredi static void fuse_drop_waiting(struct fuse_conn *fc)
91b8f95e5dSMiklos Szeredi {
922d84a2d1SMiklos Szeredi /*
932d84a2d1SMiklos Szeredi * lockess check of fc->connected is okay, because atomic_dec_and_test()
94c4e0cd4eSZheng Yongjun * provides a memory barrier matched with the one in fuse_wait_aborted()
952d84a2d1SMiklos Szeredi * to ensure no wake-up is missed.
962d84a2d1SMiklos Szeredi */
972d84a2d1SMiklos Szeredi if (atomic_dec_and_test(&fc->num_waiting) &&
982d84a2d1SMiklos Szeredi !READ_ONCE(fc->connected)) {
99b8f95e5dSMiklos Szeredi /* wake up aborters */
100b8f95e5dSMiklos Szeredi wake_up_all(&fc->blocked_waitq);
101b8f95e5dSMiklos Szeredi }
102b8f95e5dSMiklos Szeredi }
103b8f95e5dSMiklos Szeredi
1048f622e94SMax Reitz static void fuse_put_request(struct fuse_req *req);
10566abc359SMiklos Szeredi
fuse_get_req(struct fuse_mount * fm,bool for_background)106fcee216bSMax Reitz static struct fuse_req *fuse_get_req(struct fuse_mount *fm, bool for_background)
107334f485dSMiklos Szeredi {
108fcee216bSMax Reitz struct fuse_conn *fc = fm->fc;
10908a53cdcSMiklos Szeredi struct fuse_req *req;
1100aada884SMaxim Patlasov int err;
1110aada884SMaxim Patlasov atomic_inc(&fc->num_waiting);
1120aada884SMaxim Patlasov
1130aada884SMaxim Patlasov if (fuse_block_alloc(fc, for_background)) {
1149bc5dddaSMiklos Szeredi err = -EINTR;
1157d3a07fcSAl Viro if (wait_event_killable_exclusive(fc->blocked_waitq,
1167d3a07fcSAl Viro !fuse_block_alloc(fc, for_background)))
1179bc5dddaSMiklos Szeredi goto out;
1180aada884SMaxim Patlasov }
1199759bd51SMiklos Szeredi /* Matches smp_wmb() in fuse_set_initialized() */
1209759bd51SMiklos Szeredi smp_rmb();
12108a53cdcSMiklos Szeredi
12251eb01e7SMiklos Szeredi err = -ENOTCONN;
12351eb01e7SMiklos Szeredi if (!fc->connected)
12451eb01e7SMiklos Szeredi goto out;
12551eb01e7SMiklos Szeredi
126de155226SMiklos Szeredi err = -ECONNREFUSED;
127de155226SMiklos Szeredi if (fc->conn_error)
128de155226SMiklos Szeredi goto out;
129de155226SMiklos Szeredi
130fcee216bSMax Reitz req = fuse_request_alloc(fm, GFP_KERNEL);
1319bc5dddaSMiklos Szeredi err = -ENOMEM;
132722d2beaSMaxim Patlasov if (!req) {
133722d2beaSMaxim Patlasov if (for_background)
134722d2beaSMaxim Patlasov wake_up(&fc->blocked_waitq);
1359bc5dddaSMiklos Szeredi goto out;
136722d2beaSMaxim Patlasov }
137334f485dSMiklos Szeredi
1388cb08329SEric W. Biederman req->in.h.uid = from_kuid(fc->user_ns, current_fsuid());
1398cb08329SEric W. Biederman req->in.h.gid = from_kgid(fc->user_ns, current_fsgid());
140c9582eb0SEric W. Biederman req->in.h.pid = pid_nr_ns(task_pid(current), fc->pid_ns);
141c9582eb0SEric W. Biederman
142825d6d33SMiklos Szeredi __set_bit(FR_WAITING, &req->flags);
143825d6d33SMiklos Szeredi if (for_background)
144825d6d33SMiklos Szeredi __set_bit(FR_BACKGROUND, &req->flags);
145825d6d33SMiklos Szeredi
146c9582eb0SEric W. Biederman if (unlikely(req->in.h.uid == ((uid_t)-1) ||
147c9582eb0SEric W. Biederman req->in.h.gid == ((gid_t)-1))) {
1488f622e94SMax Reitz fuse_put_request(req);
149c9582eb0SEric W. Biederman return ERR_PTR(-EOVERFLOW);
150c9582eb0SEric W. Biederman }
151334f485dSMiklos Szeredi return req;
1529bc5dddaSMiklos Szeredi
1539bc5dddaSMiklos Szeredi out:
154b8f95e5dSMiklos Szeredi fuse_drop_waiting(fc);
1559bc5dddaSMiklos Szeredi return ERR_PTR(err);
156334f485dSMiklos Szeredi }
1578b41e671SMaxim Patlasov
fuse_put_request(struct fuse_req * req)1588f622e94SMax Reitz static void fuse_put_request(struct fuse_req *req)
159334f485dSMiklos Szeredi {
160fcee216bSMax Reitz struct fuse_conn *fc = req->fm->fc;
1618f622e94SMax Reitz
162ec99f6d3SElena Reshetova if (refcount_dec_and_test(&req->count)) {
163825d6d33SMiklos Szeredi if (test_bit(FR_BACKGROUND, &req->flags)) {
164722d2beaSMaxim Patlasov /*
165722d2beaSMaxim Patlasov * We get here in the unlikely case that a background
166722d2beaSMaxim Patlasov * request was allocated but not sent
167722d2beaSMaxim Patlasov */
168ae2dffa3SKirill Tkhai spin_lock(&fc->bg_lock);
169722d2beaSMaxim Patlasov if (!fc->blocked)
170722d2beaSMaxim Patlasov wake_up(&fc->blocked_waitq);
171ae2dffa3SKirill Tkhai spin_unlock(&fc->bg_lock);
172722d2beaSMaxim Patlasov }
173722d2beaSMaxim Patlasov
174825d6d33SMiklos Szeredi if (test_bit(FR_WAITING, &req->flags)) {
175825d6d33SMiklos Szeredi __clear_bit(FR_WAITING, &req->flags);
176b8f95e5dSMiklos Szeredi fuse_drop_waiting(fc);
17773e0e738SMiklos Szeredi }
17833649c91SMiklos Szeredi
179ce1d5a49SMiklos Szeredi fuse_request_free(req);
1807128ec2aSMiklos Szeredi }
1817128ec2aSMiklos Szeredi }
1827128ec2aSMiklos Szeredi
fuse_len_args(unsigned int numargs,struct fuse_arg * args)18314d46d7aSStefan Hajnoczi unsigned int fuse_len_args(unsigned int numargs, struct fuse_arg *args)
184d12def1bSMiklos Szeredi {
185d12def1bSMiklos Szeredi unsigned nbytes = 0;
186d12def1bSMiklos Szeredi unsigned i;
187d12def1bSMiklos Szeredi
188d12def1bSMiklos Szeredi for (i = 0; i < numargs; i++)
189d12def1bSMiklos Szeredi nbytes += args[i].size;
190d12def1bSMiklos Szeredi
191d12def1bSMiklos Szeredi return nbytes;
192d12def1bSMiklos Szeredi }
19314d46d7aSStefan Hajnoczi EXPORT_SYMBOL_GPL(fuse_len_args);
194d12def1bSMiklos Szeredi
fuse_get_unique(struct fuse_iqueue * fiq)19579d96effSStefan Hajnoczi u64 fuse_get_unique(struct fuse_iqueue *fiq)
196d12def1bSMiklos Szeredi {
197c59fd85eSKirill Tkhai fiq->reqctr += FUSE_REQ_ID_STEP;
198c59fd85eSKirill Tkhai return fiq->reqctr;
199d12def1bSMiklos Szeredi }
20079d96effSStefan Hajnoczi EXPORT_SYMBOL_GPL(fuse_get_unique);
201d12def1bSMiklos Szeredi
fuse_req_hash(u64 unique)202be2ff42cSKirill Tkhai static unsigned int fuse_req_hash(u64 unique)
203be2ff42cSKirill Tkhai {
204be2ff42cSKirill Tkhai return hash_long(unique & ~FUSE_INT_REQ_BIT, FUSE_PQ_HASH_BITS);
205be2ff42cSKirill Tkhai }
206be2ff42cSKirill Tkhai
20706bbb761SRandy Dunlap /*
208ae3aad77SStefan Hajnoczi * A new request is available, wake fiq->waitq
209ae3aad77SStefan Hajnoczi */
fuse_dev_wake_and_unlock(struct fuse_iqueue * fiq)210ae3aad77SStefan Hajnoczi static void fuse_dev_wake_and_unlock(struct fuse_iqueue *fiq)
211ae3aad77SStefan Hajnoczi __releases(fiq->lock)
212ae3aad77SStefan Hajnoczi {
213ae3aad77SStefan Hajnoczi wake_up(&fiq->waitq);
214ae3aad77SStefan Hajnoczi kill_fasync(&fiq->fasync, SIGIO, POLL_IN);
215ae3aad77SStefan Hajnoczi spin_unlock(&fiq->lock);
216ae3aad77SStefan Hajnoczi }
217ae3aad77SStefan Hajnoczi
218ae3aad77SStefan Hajnoczi const struct fuse_iqueue_ops fuse_dev_fiq_ops = {
219ae3aad77SStefan Hajnoczi .wake_forget_and_unlock = fuse_dev_wake_and_unlock,
220ae3aad77SStefan Hajnoczi .wake_interrupt_and_unlock = fuse_dev_wake_and_unlock,
221ae3aad77SStefan Hajnoczi .wake_pending_and_unlock = fuse_dev_wake_and_unlock,
222ae3aad77SStefan Hajnoczi };
223ae3aad77SStefan Hajnoczi EXPORT_SYMBOL_GPL(fuse_dev_fiq_ops);
224ae3aad77SStefan Hajnoczi
queue_request_and_unlock(struct fuse_iqueue * fiq,struct fuse_req * req)225ae3aad77SStefan Hajnoczi static void queue_request_and_unlock(struct fuse_iqueue *fiq,
226ae3aad77SStefan Hajnoczi struct fuse_req *req)
227ae3aad77SStefan Hajnoczi __releases(fiq->lock)
228d12def1bSMiklos Szeredi {
229d12def1bSMiklos Szeredi req->in.h.len = sizeof(struct fuse_in_header) +
23014d46d7aSStefan Hajnoczi fuse_len_args(req->args->in_numargs,
231d4993774SMiklos Szeredi (struct fuse_arg *) req->args->in_args);
232f88996a9SMiklos Szeredi list_add_tail(&req->list, &fiq->pending);
233ae3aad77SStefan Hajnoczi fiq->ops->wake_pending_and_unlock(fiq);
234d12def1bSMiklos Szeredi }
235d12def1bSMiklos Szeredi
fuse_queue_forget(struct fuse_conn * fc,struct fuse_forget_link * forget,u64 nodeid,u64 nlookup)23607e77dcaSMiklos Szeredi void fuse_queue_forget(struct fuse_conn *fc, struct fuse_forget_link *forget,
23707e77dcaSMiklos Szeredi u64 nodeid, u64 nlookup)
23807e77dcaSMiklos Szeredi {
239f88996a9SMiklos Szeredi struct fuse_iqueue *fiq = &fc->iq;
240f88996a9SMiklos Szeredi
24102c048b9SMiklos Szeredi forget->forget_one.nodeid = nodeid;
24202c048b9SMiklos Szeredi forget->forget_one.nlookup = nlookup;
24307e77dcaSMiklos Szeredi
24476e43c8cSEric Biggers spin_lock(&fiq->lock);
245e16714d8SMiklos Szeredi if (fiq->connected) {
246f88996a9SMiklos Szeredi fiq->forget_list_tail->next = forget;
247f88996a9SMiklos Szeredi fiq->forget_list_tail = forget;
248ae3aad77SStefan Hajnoczi fiq->ops->wake_forget_and_unlock(fiq);
2495dfcc87fSMiklos Szeredi } else {
2505dfcc87fSMiklos Szeredi kfree(forget);
25176e43c8cSEric Biggers spin_unlock(&fiq->lock);
25207e77dcaSMiklos Szeredi }
253ae3aad77SStefan Hajnoczi }
25407e77dcaSMiklos Szeredi
flush_bg_queue(struct fuse_conn * fc)255d12def1bSMiklos Szeredi static void flush_bg_queue(struct fuse_conn *fc)
256d12def1bSMiklos Szeredi {
257e287179aSKirill Tkhai struct fuse_iqueue *fiq = &fc->iq;
258e287179aSKirill Tkhai
2597a6d3c8bSCsaba Henk while (fc->active_background < fc->max_background &&
260d12def1bSMiklos Szeredi !list_empty(&fc->bg_queue)) {
261d12def1bSMiklos Szeredi struct fuse_req *req;
262d12def1bSMiklos Szeredi
263e287179aSKirill Tkhai req = list_first_entry(&fc->bg_queue, struct fuse_req, list);
264d12def1bSMiklos Szeredi list_del(&req->list);
265d12def1bSMiklos Szeredi fc->active_background++;
26676e43c8cSEric Biggers spin_lock(&fiq->lock);
267f88996a9SMiklos Szeredi req->in.h.unique = fuse_get_unique(fiq);
268ae3aad77SStefan Hajnoczi queue_request_and_unlock(fiq, req);
269d12def1bSMiklos Szeredi }
270d12def1bSMiklos Szeredi }
271d12def1bSMiklos Szeredi
2726dbbcb12SMiklos Szeredi /*
273334f485dSMiklos Szeredi * This function is called when a request is finished. Either a reply
274f9a2842eSMiklos Szeredi * has arrived or it was aborted (and not yet sent) or some error
275f43b155aSMiklos Szeredi * occurred during communication with userspace, or the device file
27651eb01e7SMiklos Szeredi * was closed. The requester thread is woken up (if still waiting),
27751eb01e7SMiklos Szeredi * the 'end' callback is called if given, else the reference to the
27851eb01e7SMiklos Szeredi * request is released
279334f485dSMiklos Szeredi */
fuse_request_end(struct fuse_req * req)2808f622e94SMax Reitz void fuse_request_end(struct fuse_req *req)
281334f485dSMiklos Szeredi {
282fcee216bSMax Reitz struct fuse_mount *fm = req->fm;
283fcee216bSMax Reitz struct fuse_conn *fc = fm->fc;
2844ce60812SMiklos Szeredi struct fuse_iqueue *fiq = &fc->iq;
285365ae710SMiklos Szeredi
286efe2800fSMiklos Szeredi if (test_and_set_bit(FR_FINISHED, &req->flags))
287b8f95e5dSMiklos Szeredi goto put_request;
2882b319d1fSMiklos Szeredi
289217316a6SKirill Tkhai /*
290217316a6SKirill Tkhai * test_and_set_bit() implies smp_mb() between bit
291e1e71c16SMiklos Szeredi * changing and below FR_INTERRUPTED check. Pairs with
292217316a6SKirill Tkhai * smp_mb() from queue_interrupt().
293217316a6SKirill Tkhai */
294e1e71c16SMiklos Szeredi if (test_bit(FR_INTERRUPTED, &req->flags)) {
29576e43c8cSEric Biggers spin_lock(&fiq->lock);
2960d8e84b0SMiklos Szeredi list_del_init(&req->intr_entry);
29776e43c8cSEric Biggers spin_unlock(&fiq->lock);
298217316a6SKirill Tkhai }
29933e14b4dSMiklos Szeredi WARN_ON(test_bit(FR_PENDING, &req->flags));
30033e14b4dSMiklos Szeredi WARN_ON(test_bit(FR_SENT, &req->flags));
301825d6d33SMiklos Szeredi if (test_bit(FR_BACKGROUND, &req->flags)) {
302ae2dffa3SKirill Tkhai spin_lock(&fc->bg_lock);
303825d6d33SMiklos Szeredi clear_bit(FR_BACKGROUND, &req->flags);
304908a572bSMiklos Szeredi if (fc->num_background == fc->max_background) {
30551eb01e7SMiklos Szeredi fc->blocked = 0;
306722d2beaSMaxim Patlasov wake_up(&fc->blocked_waitq);
307908a572bSMiklos Szeredi } else if (!fc->blocked) {
308908a572bSMiklos Szeredi /*
309908a572bSMiklos Szeredi * Wake up next waiter, if any. It's okay to use
310908a572bSMiklos Szeredi * waitqueue_active(), as we've already synced up
311908a572bSMiklos Szeredi * fc->blocked with waiters with the wake_up() call
312908a572bSMiklos Szeredi * above.
313908a572bSMiklos Szeredi */
314908a572bSMiklos Szeredi if (waitqueue_active(&fc->blocked_waitq))
315908a572bSMiklos Szeredi wake_up(&fc->blocked_waitq);
316908a572bSMiklos Szeredi }
317722d2beaSMaxim Patlasov
31851eb01e7SMiklos Szeredi fc->num_background--;
319d12def1bSMiklos Szeredi fc->active_background--;
320d12def1bSMiklos Szeredi flush_bg_queue(fc);
321ae2dffa3SKirill Tkhai spin_unlock(&fc->bg_lock);
3225e0fed71SKirill Tkhai } else {
3235e0fed71SKirill Tkhai /* Wake up waiter sleeping in request_wait_answer() */
32451eb01e7SMiklos Szeredi wake_up(&req->waitq);
3255e0fed71SKirill Tkhai }
3265e0fed71SKirill Tkhai
3273e8cb8b2SMiklos Szeredi if (test_bit(FR_ASYNC, &req->flags))
328fcee216bSMax Reitz req->args->end(fm, req->args, req->out.h.error);
329b8f95e5dSMiklos Szeredi put_request:
3308f622e94SMax Reitz fuse_put_request(req);
331334f485dSMiklos Szeredi }
33204ec5af0SStefan Hajnoczi EXPORT_SYMBOL_GPL(fuse_request_end);
333334f485dSMiklos Szeredi
queue_interrupt(struct fuse_req * req)3348f622e94SMax Reitz static int queue_interrupt(struct fuse_req *req)
335a4d27e75SMiklos Szeredi {
336fcee216bSMax Reitz struct fuse_iqueue *fiq = &req->fm->fc->iq;
3378f622e94SMax Reitz
33876e43c8cSEric Biggers spin_lock(&fiq->lock);
339b782911bSKirill Tkhai /* Check for we've sent request to interrupt this req */
340b782911bSKirill Tkhai if (unlikely(!test_bit(FR_INTERRUPTED, &req->flags))) {
34176e43c8cSEric Biggers spin_unlock(&fiq->lock);
342b782911bSKirill Tkhai return -EINVAL;
343b782911bSKirill Tkhai }
344b782911bSKirill Tkhai
345217316a6SKirill Tkhai if (list_empty(&req->intr_entry)) {
346217316a6SKirill Tkhai list_add_tail(&req->intr_entry, &fiq->interrupts);
347217316a6SKirill Tkhai /*
348217316a6SKirill Tkhai * Pairs with smp_mb() implied by test_and_set_bit()
34975d89258SKirill Tkhai * from fuse_request_end().
350217316a6SKirill Tkhai */
351217316a6SKirill Tkhai smp_mb();
3526ba4d272SSahitya Tummala if (test_bit(FR_FINISHED, &req->flags)) {
353217316a6SKirill Tkhai list_del_init(&req->intr_entry);
35476e43c8cSEric Biggers spin_unlock(&fiq->lock);
355b782911bSKirill Tkhai return 0;
3566ba4d272SSahitya Tummala }
357ae3aad77SStefan Hajnoczi fiq->ops->wake_interrupt_and_unlock(fiq);
358ae3aad77SStefan Hajnoczi } else {
35976e43c8cSEric Biggers spin_unlock(&fiq->lock);
360ae3aad77SStefan Hajnoczi }
361b782911bSKirill Tkhai return 0;
362a4d27e75SMiklos Szeredi }
363a4d27e75SMiklos Szeredi
request_wait_answer(struct fuse_req * req)3648f622e94SMax Reitz static void request_wait_answer(struct fuse_req *req)
365334f485dSMiklos Szeredi {
366fcee216bSMax Reitz struct fuse_conn *fc = req->fm->fc;
3674ce60812SMiklos Szeredi struct fuse_iqueue *fiq = &fc->iq;
368c4775267SMiklos Szeredi int err;
369c4775267SMiklos Szeredi
370a4d27e75SMiklos Szeredi if (!fc->no_interrupt) {
371a4d27e75SMiklos Szeredi /* Any signal may interrupt this */
372c4775267SMiklos Szeredi err = wait_event_interruptible(req->waitq,
37333e14b4dSMiklos Szeredi test_bit(FR_FINISHED, &req->flags));
374c4775267SMiklos Szeredi if (!err)
375334f485dSMiklos Szeredi return;
376334f485dSMiklos Szeredi
377825d6d33SMiklos Szeredi set_bit(FR_INTERRUPTED, &req->flags);
3788f7bb368SMiklos Szeredi /* matches barrier in fuse_dev_do_read() */
3798f7bb368SMiklos Szeredi smp_mb__after_atomic();
38033e14b4dSMiklos Szeredi if (test_bit(FR_SENT, &req->flags))
3818f622e94SMax Reitz queue_interrupt(req);
382a4d27e75SMiklos Szeredi }
383a4d27e75SMiklos Szeredi
384825d6d33SMiklos Szeredi if (!test_bit(FR_FORCE, &req->flags)) {
385a4d27e75SMiklos Szeredi /* Only fatal signals may interrupt this */
3867d3a07fcSAl Viro err = wait_event_killable(req->waitq,
38733e14b4dSMiklos Szeredi test_bit(FR_FINISHED, &req->flags));
388c4775267SMiklos Szeredi if (!err)
389a4d27e75SMiklos Szeredi return;
390a4d27e75SMiklos Szeredi
39176e43c8cSEric Biggers spin_lock(&fiq->lock);
392a131de0aSMiklos Szeredi /* Request is not yet in userspace, bail out */
39333e14b4dSMiklos Szeredi if (test_bit(FR_PENDING, &req->flags)) {
394a131de0aSMiklos Szeredi list_del(&req->list);
39576e43c8cSEric Biggers spin_unlock(&fiq->lock);
396a131de0aSMiklos Szeredi __fuse_put_request(req);
397334f485dSMiklos Szeredi req->out.h.error = -EINTR;
398a131de0aSMiklos Szeredi return;
399a131de0aSMiklos Szeredi }
40076e43c8cSEric Biggers spin_unlock(&fiq->lock);
401a131de0aSMiklos Szeredi }
402a131de0aSMiklos Szeredi
403a131de0aSMiklos Szeredi /*
404a131de0aSMiklos Szeredi * Either request is already in userspace, or it was forced.
405a131de0aSMiklos Szeredi * Wait it out.
406a131de0aSMiklos Szeredi */
40733e14b4dSMiklos Szeredi wait_event(req->waitq, test_bit(FR_FINISHED, &req->flags));
408334f485dSMiklos Szeredi }
409334f485dSMiklos Szeredi
__fuse_request_send(struct fuse_req * req)4108f622e94SMax Reitz static void __fuse_request_send(struct fuse_req *req)
411334f485dSMiklos Szeredi {
412fcee216bSMax Reitz struct fuse_iqueue *fiq = &req->fm->fc->iq;
413e16714d8SMiklos Szeredi
414825d6d33SMiklos Szeredi BUG_ON(test_bit(FR_BACKGROUND, &req->flags));
41576e43c8cSEric Biggers spin_lock(&fiq->lock);
416e16714d8SMiklos Szeredi if (!fiq->connected) {
41776e43c8cSEric Biggers spin_unlock(&fiq->lock);
418334f485dSMiklos Szeredi req->out.h.error = -ENOTCONN;
419c4775267SMiklos Szeredi } else {
420f88996a9SMiklos Szeredi req->in.h.unique = fuse_get_unique(fiq);
421334f485dSMiklos Szeredi /* acquire extra reference, since request is still needed
42204ec5af0SStefan Hajnoczi after fuse_request_end() */
423334f485dSMiklos Szeredi __fuse_get_request(req);
424ae3aad77SStefan Hajnoczi queue_request_and_unlock(fiq, req);
425334f485dSMiklos Szeredi
4268f622e94SMax Reitz request_wait_answer(req);
42704ec5af0SStefan Hajnoczi /* Pairs with smp_wmb() in fuse_request_end() */
428c4775267SMiklos Szeredi smp_rmb();
429334f485dSMiklos Szeredi }
430334f485dSMiklos Szeredi }
4316a4e922cSEric Wong
fuse_adjust_compat(struct fuse_conn * fc,struct fuse_args * args)43221f62174SMiklos Szeredi static void fuse_adjust_compat(struct fuse_conn *fc, struct fuse_args *args)
43321f62174SMiklos Szeredi {
434d5b48543SMiklos Szeredi if (fc->minor < 4 && args->opcode == FUSE_STATFS)
435d5b48543SMiklos Szeredi args->out_args[0].size = FUSE_COMPAT_STATFS_SIZE;
43621f62174SMiklos Szeredi
43721f62174SMiklos Szeredi if (fc->minor < 9) {
438d5b48543SMiklos Szeredi switch (args->opcode) {
43921f62174SMiklos Szeredi case FUSE_LOOKUP:
44021f62174SMiklos Szeredi case FUSE_CREATE:
44121f62174SMiklos Szeredi case FUSE_MKNOD:
44221f62174SMiklos Szeredi case FUSE_MKDIR:
44321f62174SMiklos Szeredi case FUSE_SYMLINK:
44421f62174SMiklos Szeredi case FUSE_LINK:
445d5b48543SMiklos Szeredi args->out_args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
44621f62174SMiklos Szeredi break;
44721f62174SMiklos Szeredi case FUSE_GETATTR:
44821f62174SMiklos Szeredi case FUSE_SETATTR:
449d5b48543SMiklos Szeredi args->out_args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
45021f62174SMiklos Szeredi break;
45121f62174SMiklos Szeredi }
45221f62174SMiklos Szeredi }
45321f62174SMiklos Szeredi if (fc->minor < 12) {
454d5b48543SMiklos Szeredi switch (args->opcode) {
45521f62174SMiklos Szeredi case FUSE_CREATE:
456d5b48543SMiklos Szeredi args->in_args[0].size = sizeof(struct fuse_open_in);
45721f62174SMiklos Szeredi break;
45821f62174SMiklos Szeredi case FUSE_MKNOD:
459d5b48543SMiklos Szeredi args->in_args[0].size = FUSE_COMPAT_MKNOD_IN_SIZE;
46021f62174SMiklos Szeredi break;
46121f62174SMiklos Szeredi }
46221f62174SMiklos Szeredi }
46321f62174SMiklos Szeredi }
46421f62174SMiklos Szeredi
fuse_force_creds(struct fuse_req * req)4658f622e94SMax Reitz static void fuse_force_creds(struct fuse_req *req)
466e413754bSMiklos Szeredi {
467fcee216bSMax Reitz struct fuse_conn *fc = req->fm->fc;
4688f622e94SMax Reitz
469e413754bSMiklos Szeredi req->in.h.uid = from_kuid_munged(fc->user_ns, current_fsuid());
470e413754bSMiklos Szeredi req->in.h.gid = from_kgid_munged(fc->user_ns, current_fsgid());
471e413754bSMiklos Szeredi req->in.h.pid = pid_nr_ns(task_pid(current), fc->pid_ns);
472e413754bSMiklos Szeredi }
473e413754bSMiklos Szeredi
fuse_args_to_req(struct fuse_req * req,struct fuse_args * args)4745addcd5dSYueHaibing static void fuse_args_to_req(struct fuse_req *req, struct fuse_args *args)
47568583165SMiklos Szeredi {
47668583165SMiklos Szeredi req->in.h.opcode = args->opcode;
47768583165SMiklos Szeredi req->in.h.nodeid = args->nodeid;
478d4993774SMiklos Szeredi req->args = args;
47915d937d7SMiklos Szeredi if (args->is_ext)
48015d937d7SMiklos Szeredi req->in.h.total_extlen = args->in_args[args->ext_idx].size / 8;
4813e8cb8b2SMiklos Szeredi if (args->end)
4823e8cb8b2SMiklos Szeredi __set_bit(FR_ASYNC, &req->flags);
48368583165SMiklos Szeredi }
48468583165SMiklos Szeredi
fuse_simple_request(struct fuse_mount * fm,struct fuse_args * args)485fcee216bSMax Reitz ssize_t fuse_simple_request(struct fuse_mount *fm, struct fuse_args *args)
4867078187aSMiklos Szeredi {
487fcee216bSMax Reitz struct fuse_conn *fc = fm->fc;
4887078187aSMiklos Szeredi struct fuse_req *req;
4897078187aSMiklos Szeredi ssize_t ret;
4907078187aSMiklos Szeredi
491c500ebaaSMiklos Szeredi if (args->force) {
492e413754bSMiklos Szeredi atomic_inc(&fc->num_waiting);
493fcee216bSMax Reitz req = fuse_request_alloc(fm, GFP_KERNEL | __GFP_NOFAIL);
494e413754bSMiklos Szeredi
495e413754bSMiklos Szeredi if (!args->nocreds)
4968f622e94SMax Reitz fuse_force_creds(req);
497e413754bSMiklos Szeredi
498e413754bSMiklos Szeredi __set_bit(FR_WAITING, &req->flags);
499c500ebaaSMiklos Szeredi __set_bit(FR_FORCE, &req->flags);
500c500ebaaSMiklos Szeredi } else {
501e413754bSMiklos Szeredi WARN_ON(args->nocreds);
502fcee216bSMax Reitz req = fuse_get_req(fm, false);
5037078187aSMiklos Szeredi if (IS_ERR(req))
5047078187aSMiklos Szeredi return PTR_ERR(req);
505c500ebaaSMiklos Szeredi }
5067078187aSMiklos Szeredi
50721f62174SMiklos Szeredi /* Needs to be done after fuse_get_req() so that fc->minor is valid */
50821f62174SMiklos Szeredi fuse_adjust_compat(fc, args);
50968583165SMiklos Szeredi fuse_args_to_req(req, args);
51021f62174SMiklos Szeredi
511454a7613SMiklos Szeredi if (!args->noreply)
512454a7613SMiklos Szeredi __set_bit(FR_ISREPLY, &req->flags);
5138f622e94SMax Reitz __fuse_request_send(req);
5147078187aSMiklos Szeredi ret = req->out.h.error;
515d5b48543SMiklos Szeredi if (!ret && args->out_argvar) {
516093f38a2SMiklos Szeredi BUG_ON(args->out_numargs == 0);
517d4993774SMiklos Szeredi ret = args->out_args[args->out_numargs - 1].size;
5187078187aSMiklos Szeredi }
5198f622e94SMax Reitz fuse_put_request(req);
5207078187aSMiklos Szeredi
5217078187aSMiklos Szeredi return ret;
5227078187aSMiklos Szeredi }
5237078187aSMiklos Szeredi
fuse_request_queue_background(struct fuse_req * req)5248f622e94SMax Reitz static bool fuse_request_queue_background(struct fuse_req *req)
525334f485dSMiklos Szeredi {
526fcee216bSMax Reitz struct fuse_mount *fm = req->fm;
527fcee216bSMax Reitz struct fuse_conn *fc = fm->fc;
52863825b4eSKirill Tkhai bool queued = false;
52963825b4eSKirill Tkhai
53063825b4eSKirill Tkhai WARN_ON(!test_bit(FR_BACKGROUND, &req->flags));
531825d6d33SMiklos Szeredi if (!test_bit(FR_WAITING, &req->flags)) {
532825d6d33SMiklos Szeredi __set_bit(FR_WAITING, &req->flags);
5335437f241SMiklos Szeredi atomic_inc(&fc->num_waiting);
5345437f241SMiklos Szeredi }
535825d6d33SMiklos Szeredi __set_bit(FR_ISREPLY, &req->flags);
536ae2dffa3SKirill Tkhai spin_lock(&fc->bg_lock);
53763825b4eSKirill Tkhai if (likely(fc->connected)) {
53851eb01e7SMiklos Szeredi fc->num_background++;
5397a6d3c8bSCsaba Henk if (fc->num_background == fc->max_background)
54051eb01e7SMiklos Szeredi fc->blocked = 1;
541d12def1bSMiklos Szeredi list_add_tail(&req->list, &fc->bg_queue);
542d12def1bSMiklos Szeredi flush_bg_queue(fc);
54363825b4eSKirill Tkhai queued = true;
54463825b4eSKirill Tkhai }
545ae2dffa3SKirill Tkhai spin_unlock(&fc->bg_lock);
54663825b4eSKirill Tkhai
54763825b4eSKirill Tkhai return queued;
548d12def1bSMiklos Szeredi }
54951eb01e7SMiklos Szeredi
fuse_simple_background(struct fuse_mount * fm,struct fuse_args * args,gfp_t gfp_flags)550fcee216bSMax Reitz int fuse_simple_background(struct fuse_mount *fm, struct fuse_args *args,
55112597287SMiklos Szeredi gfp_t gfp_flags)
55212597287SMiklos Szeredi {
55312597287SMiklos Szeredi struct fuse_req *req;
55412597287SMiklos Szeredi
55512597287SMiklos Szeredi if (args->force) {
55612597287SMiklos Szeredi WARN_ON(!args->nocreds);
557fcee216bSMax Reitz req = fuse_request_alloc(fm, gfp_flags);
55812597287SMiklos Szeredi if (!req)
55912597287SMiklos Szeredi return -ENOMEM;
56012597287SMiklos Szeredi __set_bit(FR_BACKGROUND, &req->flags);
56112597287SMiklos Szeredi } else {
56212597287SMiklos Szeredi WARN_ON(args->nocreds);
563fcee216bSMax Reitz req = fuse_get_req(fm, true);
56412597287SMiklos Szeredi if (IS_ERR(req))
56512597287SMiklos Szeredi return PTR_ERR(req);
56612597287SMiklos Szeredi }
56712597287SMiklos Szeredi
56812597287SMiklos Szeredi fuse_args_to_req(req, args);
56912597287SMiklos Szeredi
5708f622e94SMax Reitz if (!fuse_request_queue_background(req)) {
5718f622e94SMax Reitz fuse_put_request(req);
57212597287SMiklos Szeredi return -ENOTCONN;
57312597287SMiklos Szeredi }
57412597287SMiklos Szeredi
57512597287SMiklos Szeredi return 0;
57612597287SMiklos Szeredi }
57712597287SMiklos Szeredi EXPORT_SYMBOL_GPL(fuse_simple_background);
57812597287SMiklos Szeredi
fuse_simple_notify_reply(struct fuse_mount * fm,struct fuse_args * args,u64 unique)579fcee216bSMax Reitz static int fuse_simple_notify_reply(struct fuse_mount *fm,
58075b399ddSMiklos Szeredi struct fuse_args *args, u64 unique)
5812d45ba38SMiklos Szeredi {
58275b399ddSMiklos Szeredi struct fuse_req *req;
583fcee216bSMax Reitz struct fuse_iqueue *fiq = &fm->fc->iq;
58475b399ddSMiklos Szeredi int err = 0;
58575b399ddSMiklos Szeredi
586fcee216bSMax Reitz req = fuse_get_req(fm, false);
58775b399ddSMiklos Szeredi if (IS_ERR(req))
58875b399ddSMiklos Szeredi return PTR_ERR(req);
5892d45ba38SMiklos Szeredi
590825d6d33SMiklos Szeredi __clear_bit(FR_ISREPLY, &req->flags);
5912d45ba38SMiklos Szeredi req->in.h.unique = unique;
59275b399ddSMiklos Szeredi
59375b399ddSMiklos Szeredi fuse_args_to_req(req, args);
59475b399ddSMiklos Szeredi
59576e43c8cSEric Biggers spin_lock(&fiq->lock);
596e16714d8SMiklos Szeredi if (fiq->connected) {
597ae3aad77SStefan Hajnoczi queue_request_and_unlock(fiq, req);
59875b399ddSMiklos Szeredi } else {
59975b399ddSMiklos Szeredi err = -ENODEV;
60075b399ddSMiklos Szeredi spin_unlock(&fiq->lock);
6018f622e94SMax Reitz fuse_put_request(req);
6022d45ba38SMiklos Szeredi }
6032d45ba38SMiklos Szeredi
6042d45ba38SMiklos Szeredi return err;
6052d45ba38SMiklos Szeredi }
6062d45ba38SMiklos Szeredi
6073be5a52bSMiklos Szeredi /*
608334f485dSMiklos Szeredi * Lock the request. Up to the next unlock_request() there mustn't be
609334f485dSMiklos Szeredi * anything that could cause a page-fault. If the request was already
610f9a2842eSMiklos Szeredi * aborted bail out.
611334f485dSMiklos Szeredi */
lock_request(struct fuse_req * req)612dc00809aSMiklos Szeredi static int lock_request(struct fuse_req *req)
613334f485dSMiklos Szeredi {
614334f485dSMiklos Szeredi int err = 0;
615334f485dSMiklos Szeredi if (req) {
616dc00809aSMiklos Szeredi spin_lock(&req->waitq.lock);
617825d6d33SMiklos Szeredi if (test_bit(FR_ABORTED, &req->flags))
618334f485dSMiklos Szeredi err = -ENOENT;
619334f485dSMiklos Szeredi else
620825d6d33SMiklos Szeredi set_bit(FR_LOCKED, &req->flags);
621dc00809aSMiklos Szeredi spin_unlock(&req->waitq.lock);
622334f485dSMiklos Szeredi }
623334f485dSMiklos Szeredi return err;
624334f485dSMiklos Szeredi }
625334f485dSMiklos Szeredi
626334f485dSMiklos Szeredi /*
6270d8e84b0SMiklos Szeredi * Unlock request. If it was aborted while locked, caller is responsible
6280d8e84b0SMiklos Szeredi * for unlocking and ending the request.
629334f485dSMiklos Szeredi */
unlock_request(struct fuse_req * req)630dc00809aSMiklos Szeredi static int unlock_request(struct fuse_req *req)
631334f485dSMiklos Szeredi {
6320d8e84b0SMiklos Szeredi int err = 0;
633334f485dSMiklos Szeredi if (req) {
634dc00809aSMiklos Szeredi spin_lock(&req->waitq.lock);
635825d6d33SMiklos Szeredi if (test_bit(FR_ABORTED, &req->flags))
6360d8e84b0SMiklos Szeredi err = -ENOENT;
6370d8e84b0SMiklos Szeredi else
638825d6d33SMiklos Szeredi clear_bit(FR_LOCKED, &req->flags);
639dc00809aSMiklos Szeredi spin_unlock(&req->waitq.lock);
640334f485dSMiklos Szeredi }
6410d8e84b0SMiklos Szeredi return err;
642334f485dSMiklos Szeredi }
643334f485dSMiklos Szeredi
644334f485dSMiklos Szeredi struct fuse_copy_state {
645334f485dSMiklos Szeredi int write;
646334f485dSMiklos Szeredi struct fuse_req *req;
6476c09e94aSAl Viro struct iov_iter *iter;
648dd3bb14fSMiklos Szeredi struct pipe_buffer *pipebufs;
649dd3bb14fSMiklos Szeredi struct pipe_buffer *currbuf;
650dd3bb14fSMiklos Szeredi struct pipe_inode_info *pipe;
651334f485dSMiklos Szeredi unsigned long nr_segs;
652334f485dSMiklos Szeredi struct page *pg;
653334f485dSMiklos Szeredi unsigned len;
654c55a01d3SMiklos Szeredi unsigned offset;
655ce534fb0SMiklos Szeredi unsigned move_pages:1;
656334f485dSMiklos Szeredi };
657334f485dSMiklos Szeredi
fuse_copy_init(struct fuse_copy_state * cs,int write,struct iov_iter * iter)658dc00809aSMiklos Szeredi static void fuse_copy_init(struct fuse_copy_state *cs, int write,
6596c09e94aSAl Viro struct iov_iter *iter)
660334f485dSMiklos Szeredi {
661334f485dSMiklos Szeredi memset(cs, 0, sizeof(*cs));
662334f485dSMiklos Szeredi cs->write = write;
6636c09e94aSAl Viro cs->iter = iter;
664334f485dSMiklos Szeredi }
665334f485dSMiklos Szeredi
666334f485dSMiklos Szeredi /* Unmap and put previous page of userspace buffer */
fuse_copy_finish(struct fuse_copy_state * cs)6678bfc016dSMiklos Szeredi static void fuse_copy_finish(struct fuse_copy_state *cs)
668334f485dSMiklos Szeredi {
669dd3bb14fSMiklos Szeredi if (cs->currbuf) {
670dd3bb14fSMiklos Szeredi struct pipe_buffer *buf = cs->currbuf;
671dd3bb14fSMiklos Szeredi
672c55a01d3SMiklos Szeredi if (cs->write)
673c3021629SMiklos Szeredi buf->len = PAGE_SIZE - cs->len;
674dd3bb14fSMiklos Szeredi cs->currbuf = NULL;
675c55a01d3SMiklos Szeredi } else if (cs->pg) {
676334f485dSMiklos Szeredi if (cs->write) {
677334f485dSMiklos Szeredi flush_dcache_page(cs->pg);
678334f485dSMiklos Szeredi set_page_dirty_lock(cs->pg);
679334f485dSMiklos Szeredi }
680334f485dSMiklos Szeredi put_page(cs->pg);
681334f485dSMiklos Szeredi }
682c55a01d3SMiklos Szeredi cs->pg = NULL;
683334f485dSMiklos Szeredi }
684334f485dSMiklos Szeredi
685334f485dSMiklos Szeredi /*
686334f485dSMiklos Szeredi * Get another pagefull of userspace buffer, and map it to kernel
687334f485dSMiklos Szeredi * address space, and lock request
688334f485dSMiklos Szeredi */
fuse_copy_fill(struct fuse_copy_state * cs)689334f485dSMiklos Szeredi static int fuse_copy_fill(struct fuse_copy_state *cs)
690334f485dSMiklos Szeredi {
691c55a01d3SMiklos Szeredi struct page *page;
692334f485dSMiklos Szeredi int err;
693334f485dSMiklos Szeredi
694dc00809aSMiklos Szeredi err = unlock_request(cs->req);
6950d8e84b0SMiklos Szeredi if (err)
6960d8e84b0SMiklos Szeredi return err;
6970d8e84b0SMiklos Szeredi
698334f485dSMiklos Szeredi fuse_copy_finish(cs);
699dd3bb14fSMiklos Szeredi if (cs->pipebufs) {
700dd3bb14fSMiklos Szeredi struct pipe_buffer *buf = cs->pipebufs;
701dd3bb14fSMiklos Szeredi
702c3021629SMiklos Szeredi if (!cs->write) {
703fba597dbSMiklos Szeredi err = pipe_buf_confirm(cs->pipe, buf);
704dd3bb14fSMiklos Szeredi if (err)
705dd3bb14fSMiklos Szeredi return err;
706dd3bb14fSMiklos Szeredi
707dd3bb14fSMiklos Szeredi BUG_ON(!cs->nr_segs);
708dd3bb14fSMiklos Szeredi cs->currbuf = buf;
709c55a01d3SMiklos Szeredi cs->pg = buf->page;
710c55a01d3SMiklos Szeredi cs->offset = buf->offset;
711dd3bb14fSMiklos Szeredi cs->len = buf->len;
712dd3bb14fSMiklos Szeredi cs->pipebufs++;
713dd3bb14fSMiklos Szeredi cs->nr_segs--;
714dd3bb14fSMiklos Szeredi } else {
7156718b6f8SDavid Howells if (cs->nr_segs >= cs->pipe->max_usage)
716c3021629SMiklos Szeredi return -EIO;
717c3021629SMiklos Szeredi
718c3021629SMiklos Szeredi page = alloc_page(GFP_HIGHUSER);
719c3021629SMiklos Szeredi if (!page)
720c3021629SMiklos Szeredi return -ENOMEM;
721c3021629SMiklos Szeredi
722c3021629SMiklos Szeredi buf->page = page;
723c3021629SMiklos Szeredi buf->offset = 0;
724c3021629SMiklos Szeredi buf->len = 0;
725c3021629SMiklos Szeredi
726c3021629SMiklos Szeredi cs->currbuf = buf;
727c55a01d3SMiklos Szeredi cs->pg = page;
728c55a01d3SMiklos Szeredi cs->offset = 0;
729c3021629SMiklos Szeredi cs->len = PAGE_SIZE;
730c3021629SMiklos Szeredi cs->pipebufs++;
731c3021629SMiklos Szeredi cs->nr_segs++;
732c3021629SMiklos Szeredi }
733c3021629SMiklos Szeredi } else {
7346c09e94aSAl Viro size_t off;
7351ef255e2SAl Viro err = iov_iter_get_pages2(cs->iter, &page, PAGE_SIZE, 1, &off);
736334f485dSMiklos Szeredi if (err < 0)
737334f485dSMiklos Szeredi return err;
7386c09e94aSAl Viro BUG_ON(!err);
7396c09e94aSAl Viro cs->len = err;
7406c09e94aSAl Viro cs->offset = off;
741c55a01d3SMiklos Szeredi cs->pg = page;
742dd3bb14fSMiklos Szeredi }
743334f485dSMiklos Szeredi
744dc00809aSMiklos Szeredi return lock_request(cs->req);
745334f485dSMiklos Szeredi }
746334f485dSMiklos Szeredi
747334f485dSMiklos Szeredi /* Do as much copy to/from userspace buffer as we can */
fuse_copy_do(struct fuse_copy_state * cs,void ** val,unsigned * size)7488bfc016dSMiklos Szeredi static int fuse_copy_do(struct fuse_copy_state *cs, void **val, unsigned *size)
749334f485dSMiklos Szeredi {
750334f485dSMiklos Szeredi unsigned ncpy = min(*size, cs->len);
751334f485dSMiklos Szeredi if (val) {
7525fe0fc9fSPeng Hao void *pgaddr = kmap_local_page(cs->pg);
753c55a01d3SMiklos Szeredi void *buf = pgaddr + cs->offset;
754c55a01d3SMiklos Szeredi
755334f485dSMiklos Szeredi if (cs->write)
756c55a01d3SMiklos Szeredi memcpy(buf, *val, ncpy);
757334f485dSMiklos Szeredi else
758c55a01d3SMiklos Szeredi memcpy(*val, buf, ncpy);
759c55a01d3SMiklos Szeredi
7605fe0fc9fSPeng Hao kunmap_local(pgaddr);
761334f485dSMiklos Szeredi *val += ncpy;
762334f485dSMiklos Szeredi }
763334f485dSMiklos Szeredi *size -= ncpy;
764334f485dSMiklos Szeredi cs->len -= ncpy;
765c55a01d3SMiklos Szeredi cs->offset += ncpy;
766334f485dSMiklos Szeredi return ncpy;
767334f485dSMiklos Szeredi }
768334f485dSMiklos Szeredi
fuse_check_folio(struct folio * folio)769063aaad7SVishal Moola (Oracle) static int fuse_check_folio(struct folio *folio)
770ce534fb0SMiklos Szeredi {
771063aaad7SVishal Moola (Oracle) if (folio_mapped(folio) ||
772063aaad7SVishal Moola (Oracle) folio->mapping != NULL ||
773063aaad7SVishal Moola (Oracle) (folio->flags & PAGE_FLAGS_CHECK_AT_PREP &
774ce534fb0SMiklos Szeredi ~(1 << PG_locked |
775ce534fb0SMiklos Szeredi 1 << PG_referenced |
776ce534fb0SMiklos Szeredi 1 << PG_uptodate |
777ce534fb0SMiklos Szeredi 1 << PG_lru |
778ce534fb0SMiklos Szeredi 1 << PG_active |
779b89ecd60SMiklos Szeredi 1 << PG_workingset |
780a5005c3cSMiklos Szeredi 1 << PG_reclaim |
781ec1c86b2SYu Zhao 1 << PG_waiters |
782ec1c86b2SYu Zhao LRU_GEN_MASK | LRU_REFS_MASK))) {
783063aaad7SVishal Moola (Oracle) dump_page(&folio->page, "fuse: trying to steal weird page");
784ce534fb0SMiklos Szeredi return 1;
785ce534fb0SMiklos Szeredi }
786ce534fb0SMiklos Szeredi return 0;
787ce534fb0SMiklos Szeredi }
788ce534fb0SMiklos Szeredi
fuse_try_move_page(struct fuse_copy_state * cs,struct page ** pagep)789ce534fb0SMiklos Szeredi static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep)
790ce534fb0SMiklos Szeredi {
791ce534fb0SMiklos Szeredi int err;
792063aaad7SVishal Moola (Oracle) struct folio *oldfolio = page_folio(*pagep);
793063aaad7SVishal Moola (Oracle) struct folio *newfolio;
794ce534fb0SMiklos Szeredi struct pipe_buffer *buf = cs->pipebufs;
795ce534fb0SMiklos Szeredi
796063aaad7SVishal Moola (Oracle) folio_get(oldfolio);
797dc00809aSMiklos Szeredi err = unlock_request(cs->req);
7980d8e84b0SMiklos Szeredi if (err)
799d78092e4SMiklos Szeredi goto out_put_old;
8000d8e84b0SMiklos Szeredi
801ce534fb0SMiklos Szeredi fuse_copy_finish(cs);
802ce534fb0SMiklos Szeredi
803fba597dbSMiklos Szeredi err = pipe_buf_confirm(cs->pipe, buf);
804ce534fb0SMiklos Szeredi if (err)
805d78092e4SMiklos Szeredi goto out_put_old;
806ce534fb0SMiklos Szeredi
807ce534fb0SMiklos Szeredi BUG_ON(!cs->nr_segs);
808ce534fb0SMiklos Szeredi cs->currbuf = buf;
809ce534fb0SMiklos Szeredi cs->len = buf->len;
810ce534fb0SMiklos Szeredi cs->pipebufs++;
811ce534fb0SMiklos Szeredi cs->nr_segs--;
812ce534fb0SMiklos Szeredi
813ce534fb0SMiklos Szeredi if (cs->len != PAGE_SIZE)
814ce534fb0SMiklos Szeredi goto out_fallback;
815ce534fb0SMiklos Szeredi
816c928f642SChristoph Hellwig if (!pipe_buf_try_steal(cs->pipe, buf))
817ce534fb0SMiklos Szeredi goto out_fallback;
818ce534fb0SMiklos Szeredi
819063aaad7SVishal Moola (Oracle) newfolio = page_folio(buf->page);
820ce534fb0SMiklos Szeredi
821063aaad7SVishal Moola (Oracle) if (!folio_test_uptodate(newfolio))
822063aaad7SVishal Moola (Oracle) folio_mark_uptodate(newfolio);
823ce534fb0SMiklos Szeredi
824063aaad7SVishal Moola (Oracle) folio_clear_mappedtodisk(newfolio);
825ce534fb0SMiklos Szeredi
826063aaad7SVishal Moola (Oracle) if (fuse_check_folio(newfolio) != 0)
827ce534fb0SMiklos Szeredi goto out_fallback_unlock;
828ce534fb0SMiklos Szeredi
829ce534fb0SMiklos Szeredi /*
830ce534fb0SMiklos Szeredi * This is a new and locked page, it shouldn't be mapped or
831ce534fb0SMiklos Szeredi * have any special flags on it
832ce534fb0SMiklos Szeredi */
833063aaad7SVishal Moola (Oracle) if (WARN_ON(folio_mapped(oldfolio)))
834ce534fb0SMiklos Szeredi goto out_fallback_unlock;
835063aaad7SVishal Moola (Oracle) if (WARN_ON(folio_has_private(oldfolio)))
836ce534fb0SMiklos Szeredi goto out_fallback_unlock;
837063aaad7SVishal Moola (Oracle) if (WARN_ON(folio_test_dirty(oldfolio) ||
838063aaad7SVishal Moola (Oracle) folio_test_writeback(oldfolio)))
839ce534fb0SMiklos Szeredi goto out_fallback_unlock;
840063aaad7SVishal Moola (Oracle) if (WARN_ON(folio_test_mlocked(oldfolio)))
841ce534fb0SMiklos Szeredi goto out_fallback_unlock;
842ce534fb0SMiklos Szeredi
843063aaad7SVishal Moola (Oracle) replace_page_cache_folio(oldfolio, newfolio);
844ef6a3c63SMiklos Szeredi
845063aaad7SVishal Moola (Oracle) folio_get(newfolio);
84647344172SMiklos Szeredi
84747344172SMiklos Szeredi if (!(buf->flags & PIPE_BUF_FLAG_LRU))
848063aaad7SVishal Moola (Oracle) folio_add_lru(newfolio);
84947344172SMiklos Szeredi
850712a9510SMiklos Szeredi /*
851712a9510SMiklos Szeredi * Release while we have extra ref on stolen page. Otherwise
852712a9510SMiklos Szeredi * anon_pipe_buf_release() might think the page can be reused.
853712a9510SMiklos Szeredi */
854712a9510SMiklos Szeredi pipe_buf_release(cs->pipe, buf);
855712a9510SMiklos Szeredi
856ce534fb0SMiklos Szeredi err = 0;
857dc00809aSMiklos Szeredi spin_lock(&cs->req->waitq.lock);
858825d6d33SMiklos Szeredi if (test_bit(FR_ABORTED, &cs->req->flags))
859ce534fb0SMiklos Szeredi err = -ENOENT;
860ce534fb0SMiklos Szeredi else
861063aaad7SVishal Moola (Oracle) *pagep = &newfolio->page;
862dc00809aSMiklos Szeredi spin_unlock(&cs->req->waitq.lock);
863ce534fb0SMiklos Szeredi
864ce534fb0SMiklos Szeredi if (err) {
865063aaad7SVishal Moola (Oracle) folio_unlock(newfolio);
866063aaad7SVishal Moola (Oracle) folio_put(newfolio);
867d78092e4SMiklos Szeredi goto out_put_old;
868ce534fb0SMiklos Szeredi }
869ce534fb0SMiklos Szeredi
870063aaad7SVishal Moola (Oracle) folio_unlock(oldfolio);
871d78092e4SMiklos Szeredi /* Drop ref for ap->pages[] array */
872063aaad7SVishal Moola (Oracle) folio_put(oldfolio);
873ce534fb0SMiklos Szeredi cs->len = 0;
874ce534fb0SMiklos Szeredi
875d78092e4SMiklos Szeredi err = 0;
876d78092e4SMiklos Szeredi out_put_old:
877d78092e4SMiklos Szeredi /* Drop ref obtained in this function */
878063aaad7SVishal Moola (Oracle) folio_put(oldfolio);
879d78092e4SMiklos Szeredi return err;
880ce534fb0SMiklos Szeredi
881ce534fb0SMiklos Szeredi out_fallback_unlock:
882063aaad7SVishal Moola (Oracle) folio_unlock(newfolio);
883ce534fb0SMiklos Szeredi out_fallback:
884c55a01d3SMiklos Szeredi cs->pg = buf->page;
885c55a01d3SMiklos Szeredi cs->offset = buf->offset;
886ce534fb0SMiklos Szeredi
887dc00809aSMiklos Szeredi err = lock_request(cs->req);
888d78092e4SMiklos Szeredi if (!err)
889d78092e4SMiklos Szeredi err = 1;
890ce534fb0SMiklos Szeredi
891d78092e4SMiklos Szeredi goto out_put_old;
892ce534fb0SMiklos Szeredi }
893ce534fb0SMiklos Szeredi
fuse_ref_page(struct fuse_copy_state * cs,struct page * page,unsigned offset,unsigned count)894c3021629SMiklos Szeredi static int fuse_ref_page(struct fuse_copy_state *cs, struct page *page,
895c3021629SMiklos Szeredi unsigned offset, unsigned count)
896c3021629SMiklos Szeredi {
897c3021629SMiklos Szeredi struct pipe_buffer *buf;
8980d8e84b0SMiklos Szeredi int err;
899c3021629SMiklos Szeredi
9006718b6f8SDavid Howells if (cs->nr_segs >= cs->pipe->max_usage)
901c3021629SMiklos Szeredi return -EIO;
902c3021629SMiklos Szeredi
903d78092e4SMiklos Szeredi get_page(page);
904dc00809aSMiklos Szeredi err = unlock_request(cs->req);
905d78092e4SMiklos Szeredi if (err) {
906d78092e4SMiklos Szeredi put_page(page);
9070d8e84b0SMiklos Szeredi return err;
908d78092e4SMiklos Szeredi }
9090d8e84b0SMiklos Szeredi
910c3021629SMiklos Szeredi fuse_copy_finish(cs);
911c3021629SMiklos Szeredi
912c3021629SMiklos Szeredi buf = cs->pipebufs;
913c3021629SMiklos Szeredi buf->page = page;
914c3021629SMiklos Szeredi buf->offset = offset;
915c3021629SMiklos Szeredi buf->len = count;
916c3021629SMiklos Szeredi
917c3021629SMiklos Szeredi cs->pipebufs++;
918c3021629SMiklos Szeredi cs->nr_segs++;
919c3021629SMiklos Szeredi cs->len = 0;
920c3021629SMiklos Szeredi
921c3021629SMiklos Szeredi return 0;
922c3021629SMiklos Szeredi }
923c3021629SMiklos Szeredi
924334f485dSMiklos Szeredi /*
925334f485dSMiklos Szeredi * Copy a page in the request to/from the userspace buffer. Must be
926334f485dSMiklos Szeredi * done atomically
927334f485dSMiklos Szeredi */
fuse_copy_page(struct fuse_copy_state * cs,struct page ** pagep,unsigned offset,unsigned count,int zeroing)928ce534fb0SMiklos Szeredi static int fuse_copy_page(struct fuse_copy_state *cs, struct page **pagep,
929334f485dSMiklos Szeredi unsigned offset, unsigned count, int zeroing)
930334f485dSMiklos Szeredi {
931ce534fb0SMiklos Szeredi int err;
932ce534fb0SMiklos Szeredi struct page *page = *pagep;
933ce534fb0SMiklos Szeredi
934b6777c40SMiklos Szeredi if (page && zeroing && count < PAGE_SIZE)
935b6777c40SMiklos Szeredi clear_highpage(page);
936b6777c40SMiklos Szeredi
937334f485dSMiklos Szeredi while (count) {
938c3021629SMiklos Szeredi if (cs->write && cs->pipebufs && page) {
9390c4bcfdeSMiklos Szeredi /*
9400c4bcfdeSMiklos Szeredi * Can't control lifetime of pipe buffers, so always
9410c4bcfdeSMiklos Szeredi * copy user pages.
9420c4bcfdeSMiklos Szeredi */
9430c4bcfdeSMiklos Szeredi if (cs->req->args->user_pages) {
9440c4bcfdeSMiklos Szeredi err = fuse_copy_fill(cs);
9450c4bcfdeSMiklos Szeredi if (err)
9460c4bcfdeSMiklos Szeredi return err;
9470c4bcfdeSMiklos Szeredi } else {
948c3021629SMiklos Szeredi return fuse_ref_page(cs, page, offset, count);
9490c4bcfdeSMiklos Szeredi }
950c3021629SMiklos Szeredi } else if (!cs->len) {
951ce534fb0SMiklos Szeredi if (cs->move_pages && page &&
952ce534fb0SMiklos Szeredi offset == 0 && count == PAGE_SIZE) {
953ce534fb0SMiklos Szeredi err = fuse_try_move_page(cs, pagep);
954ce534fb0SMiklos Szeredi if (err <= 0)
955ce534fb0SMiklos Szeredi return err;
956ce534fb0SMiklos Szeredi } else {
957ce534fb0SMiklos Szeredi err = fuse_copy_fill(cs);
9581729a16cSMiklos Szeredi if (err)
959334f485dSMiklos Szeredi return err;
9601729a16cSMiklos Szeredi }
961ce534fb0SMiklos Szeredi }
962334f485dSMiklos Szeredi if (page) {
9635fe0fc9fSPeng Hao void *mapaddr = kmap_local_page(page);
964334f485dSMiklos Szeredi void *buf = mapaddr + offset;
965334f485dSMiklos Szeredi offset += fuse_copy_do(cs, &buf, &count);
9665fe0fc9fSPeng Hao kunmap_local(mapaddr);
967334f485dSMiklos Szeredi } else
968334f485dSMiklos Szeredi offset += fuse_copy_do(cs, NULL, &count);
969334f485dSMiklos Szeredi }
970334f485dSMiklos Szeredi if (page && !cs->write)
971334f485dSMiklos Szeredi flush_dcache_page(page);
972334f485dSMiklos Szeredi return 0;
973334f485dSMiklos Szeredi }
974334f485dSMiklos Szeredi
975334f485dSMiklos Szeredi /* Copy pages in the request to/from userspace buffer */
fuse_copy_pages(struct fuse_copy_state * cs,unsigned nbytes,int zeroing)976334f485dSMiklos Szeredi static int fuse_copy_pages(struct fuse_copy_state *cs, unsigned nbytes,
977334f485dSMiklos Szeredi int zeroing)
978334f485dSMiklos Szeredi {
979334f485dSMiklos Szeredi unsigned i;
980334f485dSMiklos Szeredi struct fuse_req *req = cs->req;
98105ea48ccSMiklos Szeredi struct fuse_args_pages *ap = container_of(req->args, typeof(*ap), args);
982334f485dSMiklos Szeredi
98305ea48ccSMiklos Szeredi
98405ea48ccSMiklos Szeredi for (i = 0; i < ap->num_pages && (nbytes || zeroing); i++) {
985ce534fb0SMiklos Szeredi int err;
98605ea48ccSMiklos Szeredi unsigned int offset = ap->descs[i].offset;
98705ea48ccSMiklos Szeredi unsigned int count = min(nbytes, ap->descs[i].length);
988ce534fb0SMiklos Szeredi
98905ea48ccSMiklos Szeredi err = fuse_copy_page(cs, &ap->pages[i], offset, count, zeroing);
990334f485dSMiklos Szeredi if (err)
991334f485dSMiklos Szeredi return err;
992334f485dSMiklos Szeredi
993334f485dSMiklos Szeredi nbytes -= count;
994334f485dSMiklos Szeredi }
995334f485dSMiklos Szeredi return 0;
996334f485dSMiklos Szeredi }
997334f485dSMiklos Szeredi
998334f485dSMiklos Szeredi /* Copy a single argument in the request to/from userspace buffer */
fuse_copy_one(struct fuse_copy_state * cs,void * val,unsigned size)999334f485dSMiklos Szeredi static int fuse_copy_one(struct fuse_copy_state *cs, void *val, unsigned size)
1000334f485dSMiklos Szeredi {
1001334f485dSMiklos Szeredi while (size) {
10021729a16cSMiklos Szeredi if (!cs->len) {
10031729a16cSMiklos Szeredi int err = fuse_copy_fill(cs);
10041729a16cSMiklos Szeredi if (err)
1005334f485dSMiklos Szeredi return err;
10061729a16cSMiklos Szeredi }
1007334f485dSMiklos Szeredi fuse_copy_do(cs, &val, &size);
1008334f485dSMiklos Szeredi }
1009334f485dSMiklos Szeredi return 0;
1010334f485dSMiklos Szeredi }
1011334f485dSMiklos Szeredi
1012334f485dSMiklos Szeredi /* Copy request arguments to/from userspace buffer */
fuse_copy_args(struct fuse_copy_state * cs,unsigned numargs,unsigned argpages,struct fuse_arg * args,int zeroing)1013334f485dSMiklos Szeredi static int fuse_copy_args(struct fuse_copy_state *cs, unsigned numargs,
1014334f485dSMiklos Szeredi unsigned argpages, struct fuse_arg *args,
1015334f485dSMiklos Szeredi int zeroing)
1016334f485dSMiklos Szeredi {
1017334f485dSMiklos Szeredi int err = 0;
1018334f485dSMiklos Szeredi unsigned i;
1019334f485dSMiklos Szeredi
1020334f485dSMiklos Szeredi for (i = 0; !err && i < numargs; i++) {
1021334f485dSMiklos Szeredi struct fuse_arg *arg = &args[i];
1022334f485dSMiklos Szeredi if (i == numargs - 1 && argpages)
1023334f485dSMiklos Szeredi err = fuse_copy_pages(cs, arg->size, zeroing);
1024334f485dSMiklos Szeredi else
1025334f485dSMiklos Szeredi err = fuse_copy_one(cs, arg->value, arg->size);
1026334f485dSMiklos Szeredi }
1027334f485dSMiklos Szeredi return err;
1028334f485dSMiklos Szeredi }
1029334f485dSMiklos Szeredi
forget_pending(struct fuse_iqueue * fiq)1030f88996a9SMiklos Szeredi static int forget_pending(struct fuse_iqueue *fiq)
103107e77dcaSMiklos Szeredi {
1032f88996a9SMiklos Szeredi return fiq->forget_list_head.next != NULL;
103307e77dcaSMiklos Szeredi }
103407e77dcaSMiklos Szeredi
request_pending(struct fuse_iqueue * fiq)1035f88996a9SMiklos Szeredi static int request_pending(struct fuse_iqueue *fiq)
1036a4d27e75SMiklos Szeredi {
1037f88996a9SMiklos Szeredi return !list_empty(&fiq->pending) || !list_empty(&fiq->interrupts) ||
1038f88996a9SMiklos Szeredi forget_pending(fiq);
1039a4d27e75SMiklos Szeredi }
1040a4d27e75SMiklos Szeredi
1041334f485dSMiklos Szeredi /*
1042a4d27e75SMiklos Szeredi * Transfer an interrupt request to userspace
1043a4d27e75SMiklos Szeredi *
1044a4d27e75SMiklos Szeredi * Unlike other requests this is assembled on demand, without a need
1045a4d27e75SMiklos Szeredi * to allocate a separate fuse_req structure.
1046a4d27e75SMiklos Szeredi *
104776e43c8cSEric Biggers * Called with fiq->lock held, releases it
1048a4d27e75SMiklos Szeredi */
fuse_read_interrupt(struct fuse_iqueue * fiq,struct fuse_copy_state * cs,size_t nbytes,struct fuse_req * req)1049fd22d62eSMiklos Szeredi static int fuse_read_interrupt(struct fuse_iqueue *fiq,
1050fd22d62eSMiklos Szeredi struct fuse_copy_state *cs,
1051c3021629SMiklos Szeredi size_t nbytes, struct fuse_req *req)
105276e43c8cSEric Biggers __releases(fiq->lock)
1053a4d27e75SMiklos Szeredi {
1054a4d27e75SMiklos Szeredi struct fuse_in_header ih;
1055a4d27e75SMiklos Szeredi struct fuse_interrupt_in arg;
1056a4d27e75SMiklos Szeredi unsigned reqsize = sizeof(ih) + sizeof(arg);
1057a4d27e75SMiklos Szeredi int err;
1058a4d27e75SMiklos Szeredi
1059a4d27e75SMiklos Szeredi list_del_init(&req->intr_entry);
1060a4d27e75SMiklos Szeredi memset(&ih, 0, sizeof(ih));
1061a4d27e75SMiklos Szeredi memset(&arg, 0, sizeof(arg));
1062a4d27e75SMiklos Szeredi ih.len = reqsize;
1063a4d27e75SMiklos Szeredi ih.opcode = FUSE_INTERRUPT;
10643a5358d1SKirill Tkhai ih.unique = (req->in.h.unique | FUSE_INT_REQ_BIT);
1065a4d27e75SMiklos Szeredi arg.unique = req->in.h.unique;
1066a4d27e75SMiklos Szeredi
106776e43c8cSEric Biggers spin_unlock(&fiq->lock);
1068c3021629SMiklos Szeredi if (nbytes < reqsize)
1069a4d27e75SMiklos Szeredi return -EINVAL;
1070a4d27e75SMiklos Szeredi
1071c3021629SMiklos Szeredi err = fuse_copy_one(cs, &ih, sizeof(ih));
1072a4d27e75SMiklos Szeredi if (!err)
1073c3021629SMiklos Szeredi err = fuse_copy_one(cs, &arg, sizeof(arg));
1074c3021629SMiklos Szeredi fuse_copy_finish(cs);
1075a4d27e75SMiklos Szeredi
1076a4d27e75SMiklos Szeredi return err ? err : reqsize;
1077a4d27e75SMiklos Szeredi }
1078a4d27e75SMiklos Szeredi
fuse_dequeue_forget(struct fuse_iqueue * fiq,unsigned int max,unsigned int * countp)10794388c5aaSVivek Goyal struct fuse_forget_link *fuse_dequeue_forget(struct fuse_iqueue *fiq,
10804388c5aaSVivek Goyal unsigned int max,
10814388c5aaSVivek Goyal unsigned int *countp)
108207e77dcaSMiklos Szeredi {
1083f88996a9SMiklos Szeredi struct fuse_forget_link *head = fiq->forget_list_head.next;
108402c048b9SMiklos Szeredi struct fuse_forget_link **newhead = &head;
108502c048b9SMiklos Szeredi unsigned count;
108607e77dcaSMiklos Szeredi
108702c048b9SMiklos Szeredi for (count = 0; *newhead != NULL && count < max; count++)
108802c048b9SMiklos Szeredi newhead = &(*newhead)->next;
108902c048b9SMiklos Szeredi
1090f88996a9SMiklos Szeredi fiq->forget_list_head.next = *newhead;
109102c048b9SMiklos Szeredi *newhead = NULL;
1092f88996a9SMiklos Szeredi if (fiq->forget_list_head.next == NULL)
1093f88996a9SMiklos Szeredi fiq->forget_list_tail = &fiq->forget_list_head;
109407e77dcaSMiklos Szeredi
109502c048b9SMiklos Szeredi if (countp != NULL)
109602c048b9SMiklos Szeredi *countp = count;
109702c048b9SMiklos Szeredi
109802c048b9SMiklos Szeredi return head;
109907e77dcaSMiklos Szeredi }
11004388c5aaSVivek Goyal EXPORT_SYMBOL(fuse_dequeue_forget);
110107e77dcaSMiklos Szeredi
fuse_read_single_forget(struct fuse_iqueue * fiq,struct fuse_copy_state * cs,size_t nbytes)1102fd22d62eSMiklos Szeredi static int fuse_read_single_forget(struct fuse_iqueue *fiq,
110307e77dcaSMiklos Szeredi struct fuse_copy_state *cs,
110407e77dcaSMiklos Szeredi size_t nbytes)
110576e43c8cSEric Biggers __releases(fiq->lock)
110607e77dcaSMiklos Szeredi {
110707e77dcaSMiklos Szeredi int err;
11084388c5aaSVivek Goyal struct fuse_forget_link *forget = fuse_dequeue_forget(fiq, 1, NULL);
110907e77dcaSMiklos Szeredi struct fuse_forget_in arg = {
111002c048b9SMiklos Szeredi .nlookup = forget->forget_one.nlookup,
111107e77dcaSMiklos Szeredi };
111207e77dcaSMiklos Szeredi struct fuse_in_header ih = {
111307e77dcaSMiklos Szeredi .opcode = FUSE_FORGET,
111402c048b9SMiklos Szeredi .nodeid = forget->forget_one.nodeid,
1115f88996a9SMiklos Szeredi .unique = fuse_get_unique(fiq),
111607e77dcaSMiklos Szeredi .len = sizeof(ih) + sizeof(arg),
111707e77dcaSMiklos Szeredi };
111807e77dcaSMiklos Szeredi
111976e43c8cSEric Biggers spin_unlock(&fiq->lock);
112007e77dcaSMiklos Szeredi kfree(forget);
112107e77dcaSMiklos Szeredi if (nbytes < ih.len)
112207e77dcaSMiklos Szeredi return -EINVAL;
112307e77dcaSMiklos Szeredi
112407e77dcaSMiklos Szeredi err = fuse_copy_one(cs, &ih, sizeof(ih));
112507e77dcaSMiklos Szeredi if (!err)
112607e77dcaSMiklos Szeredi err = fuse_copy_one(cs, &arg, sizeof(arg));
112707e77dcaSMiklos Szeredi fuse_copy_finish(cs);
112807e77dcaSMiklos Szeredi
112907e77dcaSMiklos Szeredi if (err)
113007e77dcaSMiklos Szeredi return err;
113107e77dcaSMiklos Szeredi
113207e77dcaSMiklos Szeredi return ih.len;
113307e77dcaSMiklos Szeredi }
113407e77dcaSMiklos Szeredi
fuse_read_batch_forget(struct fuse_iqueue * fiq,struct fuse_copy_state * cs,size_t nbytes)1135fd22d62eSMiklos Szeredi static int fuse_read_batch_forget(struct fuse_iqueue *fiq,
113602c048b9SMiklos Szeredi struct fuse_copy_state *cs, size_t nbytes)
113776e43c8cSEric Biggers __releases(fiq->lock)
113802c048b9SMiklos Szeredi {
113902c048b9SMiklos Szeredi int err;
114002c048b9SMiklos Szeredi unsigned max_forgets;
114102c048b9SMiklos Szeredi unsigned count;
114202c048b9SMiklos Szeredi struct fuse_forget_link *head;
114302c048b9SMiklos Szeredi struct fuse_batch_forget_in arg = { .count = 0 };
114402c048b9SMiklos Szeredi struct fuse_in_header ih = {
114502c048b9SMiklos Szeredi .opcode = FUSE_BATCH_FORGET,
1146f88996a9SMiklos Szeredi .unique = fuse_get_unique(fiq),
114702c048b9SMiklos Szeredi .len = sizeof(ih) + sizeof(arg),
114802c048b9SMiklos Szeredi };
114902c048b9SMiklos Szeredi
115002c048b9SMiklos Szeredi if (nbytes < ih.len) {
115176e43c8cSEric Biggers spin_unlock(&fiq->lock);
115202c048b9SMiklos Szeredi return -EINVAL;
115302c048b9SMiklos Szeredi }
115402c048b9SMiklos Szeredi
115502c048b9SMiklos Szeredi max_forgets = (nbytes - ih.len) / sizeof(struct fuse_forget_one);
11564388c5aaSVivek Goyal head = fuse_dequeue_forget(fiq, max_forgets, &count);
115776e43c8cSEric Biggers spin_unlock(&fiq->lock);
115802c048b9SMiklos Szeredi
115902c048b9SMiklos Szeredi arg.count = count;
116002c048b9SMiklos Szeredi ih.len += count * sizeof(struct fuse_forget_one);
116102c048b9SMiklos Szeredi err = fuse_copy_one(cs, &ih, sizeof(ih));
116202c048b9SMiklos Szeredi if (!err)
116302c048b9SMiklos Szeredi err = fuse_copy_one(cs, &arg, sizeof(arg));
116402c048b9SMiklos Szeredi
116502c048b9SMiklos Szeredi while (head) {
116602c048b9SMiklos Szeredi struct fuse_forget_link *forget = head;
116702c048b9SMiklos Szeredi
116802c048b9SMiklos Szeredi if (!err) {
116902c048b9SMiklos Szeredi err = fuse_copy_one(cs, &forget->forget_one,
117002c048b9SMiklos Szeredi sizeof(forget->forget_one));
117102c048b9SMiklos Szeredi }
117202c048b9SMiklos Szeredi head = forget->next;
117302c048b9SMiklos Szeredi kfree(forget);
117402c048b9SMiklos Szeredi }
117502c048b9SMiklos Szeredi
117602c048b9SMiklos Szeredi fuse_copy_finish(cs);
117702c048b9SMiklos Szeredi
117802c048b9SMiklos Szeredi if (err)
117902c048b9SMiklos Szeredi return err;
118002c048b9SMiklos Szeredi
118102c048b9SMiklos Szeredi return ih.len;
118202c048b9SMiklos Szeredi }
118302c048b9SMiklos Szeredi
fuse_read_forget(struct fuse_conn * fc,struct fuse_iqueue * fiq,struct fuse_copy_state * cs,size_t nbytes)1184fd22d62eSMiklos Szeredi static int fuse_read_forget(struct fuse_conn *fc, struct fuse_iqueue *fiq,
1185fd22d62eSMiklos Szeredi struct fuse_copy_state *cs,
118602c048b9SMiklos Szeredi size_t nbytes)
118776e43c8cSEric Biggers __releases(fiq->lock)
118802c048b9SMiklos Szeredi {
1189f88996a9SMiklos Szeredi if (fc->minor < 16 || fiq->forget_list_head.next->next == NULL)
1190fd22d62eSMiklos Szeredi return fuse_read_single_forget(fiq, cs, nbytes);
119102c048b9SMiklos Szeredi else
1192fd22d62eSMiklos Szeredi return fuse_read_batch_forget(fiq, cs, nbytes);
119302c048b9SMiklos Szeredi }
119402c048b9SMiklos Szeredi
1195a4d27e75SMiklos Szeredi /*
1196334f485dSMiklos Szeredi * Read a single request into the userspace filesystem's buffer. This
1197334f485dSMiklos Szeredi * function waits until a request is available, then removes it from
1198334f485dSMiklos Szeredi * the pending list and copies request data to userspace buffer. If
1199f9a2842eSMiklos Szeredi * no reply is needed (FORGET) or request has been aborted or there
1200f9a2842eSMiklos Szeredi * was an error during the copying then it's finished by calling
120104ec5af0SStefan Hajnoczi * fuse_request_end(). Otherwise add it to the processing list, and set
1202334f485dSMiklos Szeredi * the 'sent' flag.
1203334f485dSMiklos Szeredi */
fuse_dev_do_read(struct fuse_dev * fud,struct file * file,struct fuse_copy_state * cs,size_t nbytes)1204c3696046SMiklos Szeredi static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
1205c3021629SMiklos Szeredi struct fuse_copy_state *cs, size_t nbytes)
1206334f485dSMiklos Szeredi {
120782cbdcd3SMiklos Szeredi ssize_t err;
1208c3696046SMiklos Szeredi struct fuse_conn *fc = fud->fc;
1209f88996a9SMiklos Szeredi struct fuse_iqueue *fiq = &fc->iq;
1210c3696046SMiklos Szeredi struct fuse_pqueue *fpq = &fud->pq;
1211334f485dSMiklos Szeredi struct fuse_req *req;
1212d4993774SMiklos Szeredi struct fuse_args *args;
1213334f485dSMiklos Szeredi unsigned reqsize;
1214be2ff42cSKirill Tkhai unsigned int hash;
1215334f485dSMiklos Szeredi
12161fb027d7SKirill Smelkov /*
12171fb027d7SKirill Smelkov * Require sane minimum read buffer - that has capacity for fixed part
12181fb027d7SKirill Smelkov * of any request header + negotiated max_write room for data.
12191fb027d7SKirill Smelkov *
12201fb027d7SKirill Smelkov * Historically libfuse reserves 4K for fixed header room, but e.g.
12211fb027d7SKirill Smelkov * GlusterFS reserves only 80 bytes
12221fb027d7SKirill Smelkov *
12231fb027d7SKirill Smelkov * = `sizeof(fuse_in_header) + sizeof(fuse_write_in)`
12241fb027d7SKirill Smelkov *
12251fb027d7SKirill Smelkov * which is the absolute minimum any sane filesystem should be using
12261fb027d7SKirill Smelkov * for header room.
12271fb027d7SKirill Smelkov */
12281fb027d7SKirill Smelkov if (nbytes < max_t(size_t, FUSE_MIN_READ_BUFFER,
12291fb027d7SKirill Smelkov sizeof(struct fuse_in_header) +
12301fb027d7SKirill Smelkov sizeof(struct fuse_write_in) +
12311fb027d7SKirill Smelkov fc->max_write))
12321fb027d7SKirill Smelkov return -EINVAL;
12331fb027d7SKirill Smelkov
12341d3d752bSMiklos Szeredi restart:
123576e43c8cSEric Biggers for (;;) {
123676e43c8cSEric Biggers spin_lock(&fiq->lock);
123776e43c8cSEric Biggers if (!fiq->connected || request_pending(fiq))
123876e43c8cSEric Biggers break;
123976e43c8cSEric Biggers spin_unlock(&fiq->lock);
1240e5ac1d1eSJeff Dike
124176e43c8cSEric Biggers if (file->f_flags & O_NONBLOCK)
124276e43c8cSEric Biggers return -EAGAIN;
124376e43c8cSEric Biggers err = wait_event_interruptible_exclusive(fiq->waitq,
12445250921bSMiklos Szeredi !fiq->connected || request_pending(fiq));
12455250921bSMiklos Szeredi if (err)
124676e43c8cSEric Biggers return err;
124776e43c8cSEric Biggers }
12485250921bSMiklos Szeredi
12493b7008b2SSzymon Lukasz if (!fiq->connected) {
1250eb98e3bdSMiklos Szeredi err = fc->aborted ? -ECONNABORTED : -ENODEV;
1251334f485dSMiklos Szeredi goto err_unlock;
12523b7008b2SSzymon Lukasz }
1253334f485dSMiklos Szeredi
1254f88996a9SMiklos Szeredi if (!list_empty(&fiq->interrupts)) {
1255f88996a9SMiklos Szeredi req = list_entry(fiq->interrupts.next, struct fuse_req,
1256a4d27e75SMiklos Szeredi intr_entry);
1257fd22d62eSMiklos Szeredi return fuse_read_interrupt(fiq, cs, nbytes, req);
1258a4d27e75SMiklos Szeredi }
1259a4d27e75SMiklos Szeredi
1260f88996a9SMiklos Szeredi if (forget_pending(fiq)) {
1261f88996a9SMiklos Szeredi if (list_empty(&fiq->pending) || fiq->forget_batch-- > 0)
1262fd22d62eSMiklos Szeredi return fuse_read_forget(fc, fiq, cs, nbytes);
126307e77dcaSMiklos Szeredi
1264f88996a9SMiklos Szeredi if (fiq->forget_batch <= -8)
1265f88996a9SMiklos Szeredi fiq->forget_batch = 16;
126607e77dcaSMiklos Szeredi }
126707e77dcaSMiklos Szeredi
1268f88996a9SMiklos Szeredi req = list_entry(fiq->pending.next, struct fuse_req, list);
126933e14b4dSMiklos Szeredi clear_bit(FR_PENDING, &req->flags);
1270ef759258SMiklos Szeredi list_del_init(&req->list);
127176e43c8cSEric Biggers spin_unlock(&fiq->lock);
12724ce60812SMiklos Szeredi
1273d4993774SMiklos Szeredi args = req->args;
1274d4993774SMiklos Szeredi reqsize = req->in.h.len;
12755d6d3a30SMiklos Szeredi
12761d3d752bSMiklos Szeredi /* If request is too large, reply with an error and restart the read */
1277c3021629SMiklos Szeredi if (nbytes < reqsize) {
12781d3d752bSMiklos Szeredi req->out.h.error = -EIO;
12791d3d752bSMiklos Szeredi /* SETXATTR is special, since it may contain too large data */
1280d4993774SMiklos Szeredi if (args->opcode == FUSE_SETXATTR)
12811d3d752bSMiklos Szeredi req->out.h.error = -E2BIG;
12828f622e94SMax Reitz fuse_request_end(req);
12831d3d752bSMiklos Szeredi goto restart;
12841d3d752bSMiklos Szeredi }
128545a91cb1SMiklos Szeredi spin_lock(&fpq->lock);
128680ef0867SMiklos Szeredi /*
128780ef0867SMiklos Szeredi * Must not put request on fpq->io queue after having been shut down by
128880ef0867SMiklos Szeredi * fuse_abort_conn()
128980ef0867SMiklos Szeredi */
129080ef0867SMiklos Szeredi if (!fpq->connected) {
129180ef0867SMiklos Szeredi req->out.h.error = err = -ECONNABORTED;
129280ef0867SMiklos Szeredi goto out_end;
129380ef0867SMiklos Szeredi
129480ef0867SMiklos Szeredi }
129582cbdcd3SMiklos Szeredi list_add(&req->list, &fpq->io);
129645a91cb1SMiklos Szeredi spin_unlock(&fpq->lock);
1297c3021629SMiklos Szeredi cs->req = req;
1298d4993774SMiklos Szeredi err = fuse_copy_one(cs, &req->in.h, sizeof(req->in.h));
1299334f485dSMiklos Szeredi if (!err)
1300d4993774SMiklos Szeredi err = fuse_copy_args(cs, args->in_numargs, args->in_pages,
1301d4993774SMiklos Szeredi (struct fuse_arg *) args->in_args, 0);
1302c3021629SMiklos Szeredi fuse_copy_finish(cs);
130345a91cb1SMiklos Szeredi spin_lock(&fpq->lock);
1304825d6d33SMiklos Szeredi clear_bit(FR_LOCKED, &req->flags);
1305e96edd94SMiklos Szeredi if (!fpq->connected) {
1306eb98e3bdSMiklos Szeredi err = fc->aborted ? -ECONNABORTED : -ENODEV;
130782cbdcd3SMiklos Szeredi goto out_end;
1308c9c9d7dfSMiklos Szeredi }
1309334f485dSMiklos Szeredi if (err) {
1310334f485dSMiklos Szeredi req->out.h.error = -EIO;
131182cbdcd3SMiklos Szeredi goto out_end;
1312334f485dSMiklos Szeredi }
1313825d6d33SMiklos Szeredi if (!test_bit(FR_ISREPLY, &req->flags)) {
131482cbdcd3SMiklos Szeredi err = reqsize;
131582cbdcd3SMiklos Szeredi goto out_end;
131682cbdcd3SMiklos Szeredi }
1317be2ff42cSKirill Tkhai hash = fuse_req_hash(req->in.h.unique);
1318be2ff42cSKirill Tkhai list_move_tail(&req->list, &fpq->processing[hash]);
1319bc78abbdSKirill Tkhai __fuse_get_request(req);
13208f7bb368SMiklos Szeredi set_bit(FR_SENT, &req->flags);
13214c316f2fSMiklos Szeredi spin_unlock(&fpq->lock);
13228f7bb368SMiklos Szeredi /* matches barrier in request_wait_answer() */
13238f7bb368SMiklos Szeredi smp_mb__after_atomic();
1324825d6d33SMiklos Szeredi if (test_bit(FR_INTERRUPTED, &req->flags))
13258f622e94SMax Reitz queue_interrupt(req);
13268f622e94SMax Reitz fuse_put_request(req);
132782cbdcd3SMiklos Szeredi
1328334f485dSMiklos Szeredi return reqsize;
1329334f485dSMiklos Szeredi
133082cbdcd3SMiklos Szeredi out_end:
133177cd9d48SMiklos Szeredi if (!test_bit(FR_PRIVATE, &req->flags))
133282cbdcd3SMiklos Szeredi list_del_init(&req->list);
133345a91cb1SMiklos Szeredi spin_unlock(&fpq->lock);
13348f622e94SMax Reitz fuse_request_end(req);
133582cbdcd3SMiklos Szeredi return err;
133682cbdcd3SMiklos Szeredi
1337334f485dSMiklos Szeredi err_unlock:
133876e43c8cSEric Biggers spin_unlock(&fiq->lock);
1339334f485dSMiklos Szeredi return err;
1340334f485dSMiklos Szeredi }
1341334f485dSMiklos Szeredi
fuse_dev_open(struct inode * inode,struct file * file)134294e4fe2cSTom Van Braeckel static int fuse_dev_open(struct inode *inode, struct file *file)
134394e4fe2cSTom Van Braeckel {
134494e4fe2cSTom Van Braeckel /*
134594e4fe2cSTom Van Braeckel * The fuse device's file's private_data is used to hold
134694e4fe2cSTom Van Braeckel * the fuse_conn(ection) when it is mounted, and is used to
134794e4fe2cSTom Van Braeckel * keep track of whether the file has been mounted already.
134894e4fe2cSTom Van Braeckel */
134994e4fe2cSTom Van Braeckel file->private_data = NULL;
135094e4fe2cSTom Van Braeckel return 0;
135194e4fe2cSTom Van Braeckel }
135294e4fe2cSTom Van Braeckel
fuse_dev_read(struct kiocb * iocb,struct iov_iter * to)1353fbdbaccaSAl Viro static ssize_t fuse_dev_read(struct kiocb *iocb, struct iov_iter *to)
1354c3021629SMiklos Szeredi {
1355c3021629SMiklos Szeredi struct fuse_copy_state cs;
1356c3021629SMiklos Szeredi struct file *file = iocb->ki_filp;
1357cc080e9eSMiklos Szeredi struct fuse_dev *fud = fuse_get_dev(file);
1358cc080e9eSMiklos Szeredi
1359cc080e9eSMiklos Szeredi if (!fud)
1360c3021629SMiklos Szeredi return -EPERM;
1361c3021629SMiklos Szeredi
1362fcb14cb1SAl Viro if (!user_backed_iter(to))
1363fbdbaccaSAl Viro return -EINVAL;
1364c3021629SMiklos Szeredi
1365dc00809aSMiklos Szeredi fuse_copy_init(&cs, 1, to);
1366fbdbaccaSAl Viro
1367c3696046SMiklos Szeredi return fuse_dev_do_read(fud, file, &cs, iov_iter_count(to));
1368c3021629SMiklos Szeredi }
1369c3021629SMiklos Szeredi
fuse_dev_splice_read(struct file * in,loff_t * ppos,struct pipe_inode_info * pipe,size_t len,unsigned int flags)1370c3021629SMiklos Szeredi static ssize_t fuse_dev_splice_read(struct file *in, loff_t *ppos,
1371c3021629SMiklos Szeredi struct pipe_inode_info *pipe,
1372c3021629SMiklos Szeredi size_t len, unsigned int flags)
1373c3021629SMiklos Szeredi {
1374d82718e3SAl Viro int total, ret;
1375c3021629SMiklos Szeredi int page_nr = 0;
1376c3021629SMiklos Szeredi struct pipe_buffer *bufs;
1377c3021629SMiklos Szeredi struct fuse_copy_state cs;
1378cc080e9eSMiklos Szeredi struct fuse_dev *fud = fuse_get_dev(in);
1379cc080e9eSMiklos Szeredi
1380cc080e9eSMiklos Szeredi if (!fud)
1381c3021629SMiklos Szeredi return -EPERM;
1382c3021629SMiklos Szeredi
13836718b6f8SDavid Howells bufs = kvmalloc_array(pipe->max_usage, sizeof(struct pipe_buffer),
13846da2ec56SKees Cook GFP_KERNEL);
1385c3021629SMiklos Szeredi if (!bufs)
1386c3021629SMiklos Szeredi return -ENOMEM;
1387c3021629SMiklos Szeredi
1388dc00809aSMiklos Szeredi fuse_copy_init(&cs, 1, NULL);
1389c3021629SMiklos Szeredi cs.pipebufs = bufs;
1390c3021629SMiklos Szeredi cs.pipe = pipe;
1391c3696046SMiklos Szeredi ret = fuse_dev_do_read(fud, in, &cs, len);
1392c3021629SMiklos Szeredi if (ret < 0)
1393c3021629SMiklos Szeredi goto out;
1394c3021629SMiklos Szeredi
13956718b6f8SDavid Howells if (pipe_occupancy(pipe->head, pipe->tail) + cs.nr_segs > pipe->max_usage) {
1396c3021629SMiklos Szeredi ret = -EIO;
1397d82718e3SAl Viro goto out;
1398c3021629SMiklos Szeredi }
1399c3021629SMiklos Szeredi
1400d82718e3SAl Viro for (ret = total = 0; page_nr < cs.nr_segs; total += ret) {
140128a625cbSMiklos Szeredi /*
140228a625cbSMiklos Szeredi * Need to be careful about this. Having buf->ops in module
140328a625cbSMiklos Szeredi * code can Oops if the buffer persists after module unload.
140428a625cbSMiklos Szeredi */
1405d82718e3SAl Viro bufs[page_nr].ops = &nosteal_pipe_buf_ops;
140684588a93SMiklos Szeredi bufs[page_nr].flags = 0;
1407d82718e3SAl Viro ret = add_to_pipe(pipe, &bufs[page_nr++]);
1408d82718e3SAl Viro if (unlikely(ret < 0))
1409d82718e3SAl Viro break;
1410c3021629SMiklos Szeredi }
1411d82718e3SAl Viro if (total)
1412d82718e3SAl Viro ret = total;
1413c3021629SMiklos Szeredi out:
1414c3021629SMiklos Szeredi for (; page_nr < cs.nr_segs; page_nr++)
141509cbfeafSKirill A. Shutemov put_page(bufs[page_nr].page);
1416c3021629SMiklos Szeredi
1417d6d931adSAndrey Ryabinin kvfree(bufs);
1418c3021629SMiklos Szeredi return ret;
1419c3021629SMiklos Szeredi }
1420c3021629SMiklos Szeredi
fuse_notify_poll(struct fuse_conn * fc,unsigned int size,struct fuse_copy_state * cs)142195668a69STejun Heo static int fuse_notify_poll(struct fuse_conn *fc, unsigned int size,
142295668a69STejun Heo struct fuse_copy_state *cs)
142395668a69STejun Heo {
142495668a69STejun Heo struct fuse_notify_poll_wakeup_out outarg;
1425f6d47a17SMiklos Szeredi int err = -EINVAL;
142695668a69STejun Heo
142795668a69STejun Heo if (size != sizeof(outarg))
1428f6d47a17SMiklos Szeredi goto err;
142995668a69STejun Heo
143095668a69STejun Heo err = fuse_copy_one(cs, &outarg, sizeof(outarg));
143195668a69STejun Heo if (err)
1432f6d47a17SMiklos Szeredi goto err;
143395668a69STejun Heo
1434f6d47a17SMiklos Szeredi fuse_copy_finish(cs);
143595668a69STejun Heo return fuse_notify_poll_wakeup(fc, &outarg);
1436f6d47a17SMiklos Szeredi
1437f6d47a17SMiklos Szeredi err:
1438f6d47a17SMiklos Szeredi fuse_copy_finish(cs);
1439f6d47a17SMiklos Szeredi return err;
144095668a69STejun Heo }
144195668a69STejun Heo
fuse_notify_inval_inode(struct fuse_conn * fc,unsigned int size,struct fuse_copy_state * cs)14423b463ae0SJohn Muir static int fuse_notify_inval_inode(struct fuse_conn *fc, unsigned int size,
14433b463ae0SJohn Muir struct fuse_copy_state *cs)
14443b463ae0SJohn Muir {
14453b463ae0SJohn Muir struct fuse_notify_inval_inode_out outarg;
14463b463ae0SJohn Muir int err = -EINVAL;
14473b463ae0SJohn Muir
14483b463ae0SJohn Muir if (size != sizeof(outarg))
14493b463ae0SJohn Muir goto err;
14503b463ae0SJohn Muir
14513b463ae0SJohn Muir err = fuse_copy_one(cs, &outarg, sizeof(outarg));
14523b463ae0SJohn Muir if (err)
14533b463ae0SJohn Muir goto err;
14543b463ae0SJohn Muir fuse_copy_finish(cs);
14553b463ae0SJohn Muir
14563b463ae0SJohn Muir down_read(&fc->killsb);
1457fcee216bSMax Reitz err = fuse_reverse_inval_inode(fc, outarg.ino,
14583b463ae0SJohn Muir outarg.off, outarg.len);
14593b463ae0SJohn Muir up_read(&fc->killsb);
14603b463ae0SJohn Muir return err;
14613b463ae0SJohn Muir
14623b463ae0SJohn Muir err:
14633b463ae0SJohn Muir fuse_copy_finish(cs);
14643b463ae0SJohn Muir return err;
14653b463ae0SJohn Muir }
14663b463ae0SJohn Muir
fuse_notify_inval_entry(struct fuse_conn * fc,unsigned int size,struct fuse_copy_state * cs)14673b463ae0SJohn Muir static int fuse_notify_inval_entry(struct fuse_conn *fc, unsigned int size,
14683b463ae0SJohn Muir struct fuse_copy_state *cs)
14693b463ae0SJohn Muir {
14703b463ae0SJohn Muir struct fuse_notify_inval_entry_out outarg;
1471b2d82ee3SFang Wenqi int err = -ENOMEM;
1472b2d82ee3SFang Wenqi char *buf;
14733b463ae0SJohn Muir struct qstr name;
14743b463ae0SJohn Muir
1475b2d82ee3SFang Wenqi buf = kzalloc(FUSE_NAME_MAX + 1, GFP_KERNEL);
1476b2d82ee3SFang Wenqi if (!buf)
1477b2d82ee3SFang Wenqi goto err;
1478b2d82ee3SFang Wenqi
1479b2d82ee3SFang Wenqi err = -EINVAL;
14803b463ae0SJohn Muir if (size < sizeof(outarg))
14813b463ae0SJohn Muir goto err;
14823b463ae0SJohn Muir
14833b463ae0SJohn Muir err = fuse_copy_one(cs, &outarg, sizeof(outarg));
14843b463ae0SJohn Muir if (err)
14853b463ae0SJohn Muir goto err;
14863b463ae0SJohn Muir
14873b463ae0SJohn Muir err = -ENAMETOOLONG;
14883b463ae0SJohn Muir if (outarg.namelen > FUSE_NAME_MAX)
14893b463ae0SJohn Muir goto err;
14903b463ae0SJohn Muir
1491c2183d1eSMiklos Szeredi err = -EINVAL;
1492c2183d1eSMiklos Szeredi if (size != sizeof(outarg) + outarg.namelen + 1)
1493c2183d1eSMiklos Szeredi goto err;
1494c2183d1eSMiklos Szeredi
14953b463ae0SJohn Muir name.name = buf;
14963b463ae0SJohn Muir name.len = outarg.namelen;
14973b463ae0SJohn Muir err = fuse_copy_one(cs, buf, outarg.namelen + 1);
14983b463ae0SJohn Muir if (err)
14993b463ae0SJohn Muir goto err;
15003b463ae0SJohn Muir fuse_copy_finish(cs);
15013b463ae0SJohn Muir buf[outarg.namelen] = 0;
15023b463ae0SJohn Muir
15033b463ae0SJohn Muir down_read(&fc->killsb);
15044f8d3702SMiklos Szeredi err = fuse_reverse_inval_entry(fc, outarg.parent, 0, &name, outarg.flags);
1505451d0f59SJohn Muir up_read(&fc->killsb);
1506451d0f59SJohn Muir kfree(buf);
1507451d0f59SJohn Muir return err;
1508451d0f59SJohn Muir
1509451d0f59SJohn Muir err:
1510451d0f59SJohn Muir kfree(buf);
1511451d0f59SJohn Muir fuse_copy_finish(cs);
1512451d0f59SJohn Muir return err;
1513451d0f59SJohn Muir }
1514451d0f59SJohn Muir
fuse_notify_delete(struct fuse_conn * fc,unsigned int size,struct fuse_copy_state * cs)1515451d0f59SJohn Muir static int fuse_notify_delete(struct fuse_conn *fc, unsigned int size,
1516451d0f59SJohn Muir struct fuse_copy_state *cs)
1517451d0f59SJohn Muir {
1518451d0f59SJohn Muir struct fuse_notify_delete_out outarg;
1519451d0f59SJohn Muir int err = -ENOMEM;
1520451d0f59SJohn Muir char *buf;
1521451d0f59SJohn Muir struct qstr name;
1522451d0f59SJohn Muir
1523451d0f59SJohn Muir buf = kzalloc(FUSE_NAME_MAX + 1, GFP_KERNEL);
1524451d0f59SJohn Muir if (!buf)
1525451d0f59SJohn Muir goto err;
1526451d0f59SJohn Muir
1527451d0f59SJohn Muir err = -EINVAL;
1528451d0f59SJohn Muir if (size < sizeof(outarg))
1529451d0f59SJohn Muir goto err;
1530451d0f59SJohn Muir
1531451d0f59SJohn Muir err = fuse_copy_one(cs, &outarg, sizeof(outarg));
1532451d0f59SJohn Muir if (err)
1533451d0f59SJohn Muir goto err;
1534451d0f59SJohn Muir
1535451d0f59SJohn Muir err = -ENAMETOOLONG;
1536451d0f59SJohn Muir if (outarg.namelen > FUSE_NAME_MAX)
1537451d0f59SJohn Muir goto err;
1538451d0f59SJohn Muir
1539451d0f59SJohn Muir err = -EINVAL;
1540451d0f59SJohn Muir if (size != sizeof(outarg) + outarg.namelen + 1)
1541451d0f59SJohn Muir goto err;
1542451d0f59SJohn Muir
1543451d0f59SJohn Muir name.name = buf;
1544451d0f59SJohn Muir name.len = outarg.namelen;
1545451d0f59SJohn Muir err = fuse_copy_one(cs, buf, outarg.namelen + 1);
1546451d0f59SJohn Muir if (err)
1547451d0f59SJohn Muir goto err;
1548451d0f59SJohn Muir fuse_copy_finish(cs);
1549451d0f59SJohn Muir buf[outarg.namelen] = 0;
1550451d0f59SJohn Muir
1551451d0f59SJohn Muir down_read(&fc->killsb);
15524f8d3702SMiklos Szeredi err = fuse_reverse_inval_entry(fc, outarg.parent, outarg.child, &name, 0);
15533b463ae0SJohn Muir up_read(&fc->killsb);
1554b2d82ee3SFang Wenqi kfree(buf);
15553b463ae0SJohn Muir return err;
15563b463ae0SJohn Muir
15573b463ae0SJohn Muir err:
1558b2d82ee3SFang Wenqi kfree(buf);
15593b463ae0SJohn Muir fuse_copy_finish(cs);
15603b463ae0SJohn Muir return err;
15613b463ae0SJohn Muir }
15623b463ae0SJohn Muir
fuse_notify_store(struct fuse_conn * fc,unsigned int size,struct fuse_copy_state * cs)1563a1d75f25SMiklos Szeredi static int fuse_notify_store(struct fuse_conn *fc, unsigned int size,
1564a1d75f25SMiklos Szeredi struct fuse_copy_state *cs)
1565a1d75f25SMiklos Szeredi {
1566a1d75f25SMiklos Szeredi struct fuse_notify_store_out outarg;
1567a1d75f25SMiklos Szeredi struct inode *inode;
1568a1d75f25SMiklos Szeredi struct address_space *mapping;
1569a1d75f25SMiklos Szeredi u64 nodeid;
1570a1d75f25SMiklos Szeredi int err;
1571a1d75f25SMiklos Szeredi pgoff_t index;
1572a1d75f25SMiklos Szeredi unsigned int offset;
1573a1d75f25SMiklos Szeredi unsigned int num;
1574a1d75f25SMiklos Szeredi loff_t file_size;
1575a1d75f25SMiklos Szeredi loff_t end;
1576a1d75f25SMiklos Szeredi
1577a1d75f25SMiklos Szeredi err = -EINVAL;
1578a1d75f25SMiklos Szeredi if (size < sizeof(outarg))
1579a1d75f25SMiklos Szeredi goto out_finish;
1580a1d75f25SMiklos Szeredi
1581a1d75f25SMiklos Szeredi err = fuse_copy_one(cs, &outarg, sizeof(outarg));
1582a1d75f25SMiklos Szeredi if (err)
1583a1d75f25SMiklos Szeredi goto out_finish;
1584a1d75f25SMiklos Szeredi
1585a1d75f25SMiklos Szeredi err = -EINVAL;
1586a1d75f25SMiklos Szeredi if (size - sizeof(outarg) != outarg.size)
1587a1d75f25SMiklos Szeredi goto out_finish;
1588a1d75f25SMiklos Szeredi
1589a1d75f25SMiklos Szeredi nodeid = outarg.nodeid;
1590a1d75f25SMiklos Szeredi
1591a1d75f25SMiklos Szeredi down_read(&fc->killsb);
1592a1d75f25SMiklos Szeredi
1593a1d75f25SMiklos Szeredi err = -ENOENT;
1594fcee216bSMax Reitz inode = fuse_ilookup(fc, nodeid, NULL);
1595a1d75f25SMiklos Szeredi if (!inode)
1596a1d75f25SMiklos Szeredi goto out_up_killsb;
1597a1d75f25SMiklos Szeredi
1598a1d75f25SMiklos Szeredi mapping = inode->i_mapping;
159909cbfeafSKirill A. Shutemov index = outarg.offset >> PAGE_SHIFT;
160009cbfeafSKirill A. Shutemov offset = outarg.offset & ~PAGE_MASK;
1601a1d75f25SMiklos Szeredi file_size = i_size_read(inode);
1602a1d75f25SMiklos Szeredi end = outarg.offset + outarg.size;
1603a1d75f25SMiklos Szeredi if (end > file_size) {
1604a1d75f25SMiklos Szeredi file_size = end;
1605d347739aSMiklos Szeredi fuse_write_update_attr(inode, file_size, outarg.size);
1606a1d75f25SMiklos Szeredi }
1607a1d75f25SMiklos Szeredi
1608a1d75f25SMiklos Szeredi num = outarg.size;
1609a1d75f25SMiklos Szeredi while (num) {
1610a1d75f25SMiklos Szeredi struct page *page;
1611a1d75f25SMiklos Szeredi unsigned int this_num;
1612a1d75f25SMiklos Szeredi
1613a1d75f25SMiklos Szeredi err = -ENOMEM;
1614a1d75f25SMiklos Szeredi page = find_or_create_page(mapping, index,
1615a1d75f25SMiklos Szeredi mapping_gfp_mask(mapping));
1616a1d75f25SMiklos Szeredi if (!page)
1617a1d75f25SMiklos Szeredi goto out_iput;
1618a1d75f25SMiklos Szeredi
161909cbfeafSKirill A. Shutemov this_num = min_t(unsigned, num, PAGE_SIZE - offset);
1620a1d75f25SMiklos Szeredi err = fuse_copy_page(cs, &page, offset, this_num, 0);
1621*ac42e0f0SJann Horn if (!PageUptodate(page) && !err && offset == 0 &&
1622*ac42e0f0SJann Horn (this_num == PAGE_SIZE || file_size == end)) {
1623*ac42e0f0SJann Horn zero_user_segment(page, this_num, PAGE_SIZE);
1624a1d75f25SMiklos Szeredi SetPageUptodate(page);
1625*ac42e0f0SJann Horn }
1626a1d75f25SMiklos Szeredi unlock_page(page);
162709cbfeafSKirill A. Shutemov put_page(page);
1628a1d75f25SMiklos Szeredi
1629a1d75f25SMiklos Szeredi if (err)
1630a1d75f25SMiklos Szeredi goto out_iput;
1631a1d75f25SMiklos Szeredi
1632a1d75f25SMiklos Szeredi num -= this_num;
1633a1d75f25SMiklos Szeredi offset = 0;
1634a1d75f25SMiklos Szeredi index++;
1635a1d75f25SMiklos Szeredi }
1636a1d75f25SMiklos Szeredi
1637a1d75f25SMiklos Szeredi err = 0;
1638a1d75f25SMiklos Szeredi
1639a1d75f25SMiklos Szeredi out_iput:
1640a1d75f25SMiklos Szeredi iput(inode);
1641a1d75f25SMiklos Szeredi out_up_killsb:
1642a1d75f25SMiklos Szeredi up_read(&fc->killsb);
1643a1d75f25SMiklos Szeredi out_finish:
1644a1d75f25SMiklos Szeredi fuse_copy_finish(cs);
1645a1d75f25SMiklos Szeredi return err;
1646a1d75f25SMiklos Szeredi }
1647a1d75f25SMiklos Szeredi
164875b399ddSMiklos Szeredi struct fuse_retrieve_args {
164975b399ddSMiklos Szeredi struct fuse_args_pages ap;
165075b399ddSMiklos Szeredi struct fuse_notify_retrieve_in inarg;
165175b399ddSMiklos Szeredi };
165275b399ddSMiklos Szeredi
fuse_retrieve_end(struct fuse_mount * fm,struct fuse_args * args,int error)1653fcee216bSMax Reitz static void fuse_retrieve_end(struct fuse_mount *fm, struct fuse_args *args,
165475b399ddSMiklos Szeredi int error)
16552d45ba38SMiklos Szeredi {
165675b399ddSMiklos Szeredi struct fuse_retrieve_args *ra =
165775b399ddSMiklos Szeredi container_of(args, typeof(*ra), ap.args);
165875b399ddSMiklos Szeredi
165975b399ddSMiklos Szeredi release_pages(ra->ap.pages, ra->ap.num_pages);
166075b399ddSMiklos Szeredi kfree(ra);
16612d45ba38SMiklos Szeredi }
16622d45ba38SMiklos Szeredi
fuse_retrieve(struct fuse_mount * fm,struct inode * inode,struct fuse_notify_retrieve_out * outarg)1663fcee216bSMax Reitz static int fuse_retrieve(struct fuse_mount *fm, struct inode *inode,
16642d45ba38SMiklos Szeredi struct fuse_notify_retrieve_out *outarg)
16652d45ba38SMiklos Szeredi {
16662d45ba38SMiklos Szeredi int err;
16672d45ba38SMiklos Szeredi struct address_space *mapping = inode->i_mapping;
16682d45ba38SMiklos Szeredi pgoff_t index;
16692d45ba38SMiklos Szeredi loff_t file_size;
16702d45ba38SMiklos Szeredi unsigned int num;
16712d45ba38SMiklos Szeredi unsigned int offset;
16720157443cSGeert Uytterhoeven size_t total_len = 0;
16735da784ccSConstantine Shulyupin unsigned int num_pages;
1674fcee216bSMax Reitz struct fuse_conn *fc = fm->fc;
167575b399ddSMiklos Szeredi struct fuse_retrieve_args *ra;
167675b399ddSMiklos Szeredi size_t args_size = sizeof(*ra);
167775b399ddSMiklos Szeredi struct fuse_args_pages *ap;
167875b399ddSMiklos Szeredi struct fuse_args *args;
16792d45ba38SMiklos Szeredi
168009cbfeafSKirill A. Shutemov offset = outarg->offset & ~PAGE_MASK;
16814d53dc99SMaxim Patlasov file_size = i_size_read(inode);
16824d53dc99SMaxim Patlasov
16837640682eSKirill Smelkov num = min(outarg->size, fc->max_write);
16844d53dc99SMaxim Patlasov if (outarg->offset > file_size)
16854d53dc99SMaxim Patlasov num = 0;
16864d53dc99SMaxim Patlasov else if (outarg->offset + num > file_size)
16874d53dc99SMaxim Patlasov num = file_size - outarg->offset;
16884d53dc99SMaxim Patlasov
16894d53dc99SMaxim Patlasov num_pages = (num + offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
16905da784ccSConstantine Shulyupin num_pages = min(num_pages, fc->max_pages);
16914d53dc99SMaxim Patlasov
169275b399ddSMiklos Szeredi args_size += num_pages * (sizeof(ap->pages[0]) + sizeof(ap->descs[0]));
16932d45ba38SMiklos Szeredi
169475b399ddSMiklos Szeredi ra = kzalloc(args_size, GFP_KERNEL);
169575b399ddSMiklos Szeredi if (!ra)
169675b399ddSMiklos Szeredi return -ENOMEM;
169775b399ddSMiklos Szeredi
169875b399ddSMiklos Szeredi ap = &ra->ap;
169975b399ddSMiklos Szeredi ap->pages = (void *) (ra + 1);
170075b399ddSMiklos Szeredi ap->descs = (void *) (ap->pages + num_pages);
170175b399ddSMiklos Szeredi
170275b399ddSMiklos Szeredi args = &ap->args;
170375b399ddSMiklos Szeredi args->nodeid = outarg->nodeid;
170475b399ddSMiklos Szeredi args->opcode = FUSE_NOTIFY_REPLY;
170575b399ddSMiklos Szeredi args->in_numargs = 2;
170675b399ddSMiklos Szeredi args->in_pages = true;
170775b399ddSMiklos Szeredi args->end = fuse_retrieve_end;
17082d45ba38SMiklos Szeredi
170909cbfeafSKirill A. Shutemov index = outarg->offset >> PAGE_SHIFT;
17102d45ba38SMiklos Szeredi
171175b399ddSMiklos Szeredi while (num && ap->num_pages < num_pages) {
17122d45ba38SMiklos Szeredi struct page *page;
17132d45ba38SMiklos Szeredi unsigned int this_num;
17142d45ba38SMiklos Szeredi
17152d45ba38SMiklos Szeredi page = find_get_page(mapping, index);
17162d45ba38SMiklos Szeredi if (!page)
17172d45ba38SMiklos Szeredi break;
17182d45ba38SMiklos Szeredi
171909cbfeafSKirill A. Shutemov this_num = min_t(unsigned, num, PAGE_SIZE - offset);
172075b399ddSMiklos Szeredi ap->pages[ap->num_pages] = page;
172175b399ddSMiklos Szeredi ap->descs[ap->num_pages].offset = offset;
172275b399ddSMiklos Szeredi ap->descs[ap->num_pages].length = this_num;
172375b399ddSMiklos Szeredi ap->num_pages++;
17242d45ba38SMiklos Szeredi
1725c9e67d48SMiklos Szeredi offset = 0;
17262d45ba38SMiklos Szeredi num -= this_num;
17272d45ba38SMiklos Szeredi total_len += this_num;
172848706d0aSMiklos Szeredi index++;
17292d45ba38SMiklos Szeredi }
173075b399ddSMiklos Szeredi ra->inarg.offset = outarg->offset;
173175b399ddSMiklos Szeredi ra->inarg.size = total_len;
173275b399ddSMiklos Szeredi args->in_args[0].size = sizeof(ra->inarg);
173375b399ddSMiklos Szeredi args->in_args[0].value = &ra->inarg;
173475b399ddSMiklos Szeredi args->in_args[1].size = total_len;
17352d45ba38SMiklos Szeredi
1736fcee216bSMax Reitz err = fuse_simple_notify_reply(fm, args, outarg->notify_unique);
173775b399ddSMiklos Szeredi if (err)
1738fcee216bSMax Reitz fuse_retrieve_end(fm, args, err);
17392d45ba38SMiklos Szeredi
17402d45ba38SMiklos Szeredi return err;
17412d45ba38SMiklos Szeredi }
17422d45ba38SMiklos Szeredi
fuse_notify_retrieve(struct fuse_conn * fc,unsigned int size,struct fuse_copy_state * cs)17432d45ba38SMiklos Szeredi static int fuse_notify_retrieve(struct fuse_conn *fc, unsigned int size,
17442d45ba38SMiklos Szeredi struct fuse_copy_state *cs)
17452d45ba38SMiklos Szeredi {
17462d45ba38SMiklos Szeredi struct fuse_notify_retrieve_out outarg;
1747fcee216bSMax Reitz struct fuse_mount *fm;
17482d45ba38SMiklos Szeredi struct inode *inode;
1749fcee216bSMax Reitz u64 nodeid;
17502d45ba38SMiklos Szeredi int err;
17512d45ba38SMiklos Szeredi
17522d45ba38SMiklos Szeredi err = -EINVAL;
17532d45ba38SMiklos Szeredi if (size != sizeof(outarg))
17542d45ba38SMiklos Szeredi goto copy_finish;
17552d45ba38SMiklos Szeredi
17562d45ba38SMiklos Szeredi err = fuse_copy_one(cs, &outarg, sizeof(outarg));
17572d45ba38SMiklos Szeredi if (err)
17582d45ba38SMiklos Szeredi goto copy_finish;
17592d45ba38SMiklos Szeredi
17602d45ba38SMiklos Szeredi fuse_copy_finish(cs);
17612d45ba38SMiklos Szeredi
17622d45ba38SMiklos Szeredi down_read(&fc->killsb);
17632d45ba38SMiklos Szeredi err = -ENOENT;
1764fcee216bSMax Reitz nodeid = outarg.nodeid;
17652d45ba38SMiklos Szeredi
1766fcee216bSMax Reitz inode = fuse_ilookup(fc, nodeid, &fm);
17672d45ba38SMiklos Szeredi if (inode) {
1768fcee216bSMax Reitz err = fuse_retrieve(fm, inode, &outarg);
17692d45ba38SMiklos Szeredi iput(inode);
17702d45ba38SMiklos Szeredi }
17712d45ba38SMiklos Szeredi up_read(&fc->killsb);
17722d45ba38SMiklos Szeredi
17732d45ba38SMiklos Szeredi return err;
17742d45ba38SMiklos Szeredi
17752d45ba38SMiklos Szeredi copy_finish:
17762d45ba38SMiklos Szeredi fuse_copy_finish(cs);
17772d45ba38SMiklos Szeredi return err;
17782d45ba38SMiklos Szeredi }
17792d45ba38SMiklos Szeredi
fuse_notify(struct fuse_conn * fc,enum fuse_notify_code code,unsigned int size,struct fuse_copy_state * cs)17808599396bSTejun Heo static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code,
17818599396bSTejun Heo unsigned int size, struct fuse_copy_state *cs)
17828599396bSTejun Heo {
17830d278362SMiklos Szeredi /* Don't try to move pages (yet) */
17840d278362SMiklos Szeredi cs->move_pages = 0;
17850d278362SMiklos Szeredi
17868599396bSTejun Heo switch (code) {
178795668a69STejun Heo case FUSE_NOTIFY_POLL:
178895668a69STejun Heo return fuse_notify_poll(fc, size, cs);
178995668a69STejun Heo
17903b463ae0SJohn Muir case FUSE_NOTIFY_INVAL_INODE:
17913b463ae0SJohn Muir return fuse_notify_inval_inode(fc, size, cs);
17923b463ae0SJohn Muir
17933b463ae0SJohn Muir case FUSE_NOTIFY_INVAL_ENTRY:
17943b463ae0SJohn Muir return fuse_notify_inval_entry(fc, size, cs);
17953b463ae0SJohn Muir
1796a1d75f25SMiklos Szeredi case FUSE_NOTIFY_STORE:
1797a1d75f25SMiklos Szeredi return fuse_notify_store(fc, size, cs);
1798a1d75f25SMiklos Szeredi
17992d45ba38SMiklos Szeredi case FUSE_NOTIFY_RETRIEVE:
18002d45ba38SMiklos Szeredi return fuse_notify_retrieve(fc, size, cs);
18012d45ba38SMiklos Szeredi
1802451d0f59SJohn Muir case FUSE_NOTIFY_DELETE:
1803451d0f59SJohn Muir return fuse_notify_delete(fc, size, cs);
1804451d0f59SJohn Muir
18058599396bSTejun Heo default:
1806f6d47a17SMiklos Szeredi fuse_copy_finish(cs);
18078599396bSTejun Heo return -EINVAL;
18088599396bSTejun Heo }
18098599396bSTejun Heo }
18108599396bSTejun Heo
1811334f485dSMiklos Szeredi /* Look up request on processing list by unique ID */
request_find(struct fuse_pqueue * fpq,u64 unique)18123a2b5b9cSMiklos Szeredi static struct fuse_req *request_find(struct fuse_pqueue *fpq, u64 unique)
1813334f485dSMiklos Szeredi {
1814be2ff42cSKirill Tkhai unsigned int hash = fuse_req_hash(unique);
1815334f485dSMiklos Szeredi struct fuse_req *req;
181605726acaSDong Fang
1817be2ff42cSKirill Tkhai list_for_each_entry(req, &fpq->processing[hash], list) {
18183a5358d1SKirill Tkhai if (req->in.h.unique == unique)
1819334f485dSMiklos Szeredi return req;
1820334f485dSMiklos Szeredi }
1821334f485dSMiklos Szeredi return NULL;
1822334f485dSMiklos Szeredi }
1823334f485dSMiklos Szeredi
copy_out_args(struct fuse_copy_state * cs,struct fuse_args * args,unsigned nbytes)1824d4993774SMiklos Szeredi static int copy_out_args(struct fuse_copy_state *cs, struct fuse_args *args,
1825334f485dSMiklos Szeredi unsigned nbytes)
1826334f485dSMiklos Szeredi {
1827334f485dSMiklos Szeredi unsigned reqsize = sizeof(struct fuse_out_header);
1828334f485dSMiklos Szeredi
182914d46d7aSStefan Hajnoczi reqsize += fuse_len_args(args->out_numargs, args->out_args);
1830334f485dSMiklos Szeredi
1831d4993774SMiklos Szeredi if (reqsize < nbytes || (reqsize > nbytes && !args->out_argvar))
1832334f485dSMiklos Szeredi return -EINVAL;
1833334f485dSMiklos Szeredi else if (reqsize > nbytes) {
1834d4993774SMiklos Szeredi struct fuse_arg *lastarg = &args->out_args[args->out_numargs-1];
1835334f485dSMiklos Szeredi unsigned diffsize = reqsize - nbytes;
1836d4993774SMiklos Szeredi
1837334f485dSMiklos Szeredi if (diffsize > lastarg->size)
1838334f485dSMiklos Szeredi return -EINVAL;
1839334f485dSMiklos Szeredi lastarg->size -= diffsize;
1840334f485dSMiklos Szeredi }
1841d4993774SMiklos Szeredi return fuse_copy_args(cs, args->out_numargs, args->out_pages,
1842d4993774SMiklos Szeredi args->out_args, args->page_zeroing);
1843334f485dSMiklos Szeredi }
1844334f485dSMiklos Szeredi
1845334f485dSMiklos Szeredi /*
1846334f485dSMiklos Szeredi * Write a single reply to a request. First the header is copied from
1847334f485dSMiklos Szeredi * the write buffer. The request is then searched on the processing
1848334f485dSMiklos Szeredi * list by the unique ID found in the header. If found, then remove
1849334f485dSMiklos Szeredi * it from the list and copy the rest of the buffer to the request.
185004ec5af0SStefan Hajnoczi * The request is finished by calling fuse_request_end().
1851334f485dSMiklos Szeredi */
fuse_dev_do_write(struct fuse_dev * fud,struct fuse_copy_state * cs,size_t nbytes)1852c3696046SMiklos Szeredi static ssize_t fuse_dev_do_write(struct fuse_dev *fud,
1853dd3bb14fSMiklos Szeredi struct fuse_copy_state *cs, size_t nbytes)
1854334f485dSMiklos Szeredi {
1855334f485dSMiklos Szeredi int err;
1856c3696046SMiklos Szeredi struct fuse_conn *fc = fud->fc;
1857c3696046SMiklos Szeredi struct fuse_pqueue *fpq = &fud->pq;
1858334f485dSMiklos Szeredi struct fuse_req *req;
1859334f485dSMiklos Szeredi struct fuse_out_header oh;
1860334f485dSMiklos Szeredi
18617407a10dSKirill Tkhai err = -EINVAL;
1862334f485dSMiklos Szeredi if (nbytes < sizeof(struct fuse_out_header))
18637407a10dSKirill Tkhai goto out;
1864334f485dSMiklos Szeredi
1865dd3bb14fSMiklos Szeredi err = fuse_copy_one(cs, &oh, sizeof(oh));
1866334f485dSMiklos Szeredi if (err)
18677407a10dSKirill Tkhai goto copy_finish;
18688599396bSTejun Heo
1869334f485dSMiklos Szeredi err = -EINVAL;
18708599396bSTejun Heo if (oh.len != nbytes)
18717407a10dSKirill Tkhai goto copy_finish;
18728599396bSTejun Heo
18738599396bSTejun Heo /*
18748599396bSTejun Heo * Zero oh.unique indicates unsolicited notification message
18758599396bSTejun Heo * and error contains notification code.
18768599396bSTejun Heo */
18778599396bSTejun Heo if (!oh.unique) {
1878dd3bb14fSMiklos Szeredi err = fuse_notify(fc, oh.error, nbytes - sizeof(oh), cs);
18797407a10dSKirill Tkhai goto out;
18808599396bSTejun Heo }
18818599396bSTejun Heo
18828599396bSTejun Heo err = -EINVAL;
188349221cf8SMiklos Szeredi if (oh.error <= -512 || oh.error > 0)
18847407a10dSKirill Tkhai goto copy_finish;
1885334f485dSMiklos Szeredi
188645a91cb1SMiklos Szeredi spin_lock(&fpq->lock);
18877407a10dSKirill Tkhai req = NULL;
18887407a10dSKirill Tkhai if (fpq->connected)
18893a5358d1SKirill Tkhai req = request_find(fpq, oh.unique & ~FUSE_INT_REQ_BIT);
18907407a10dSKirill Tkhai
18917407a10dSKirill Tkhai err = -ENOENT;
18927407a10dSKirill Tkhai if (!req) {
18937407a10dSKirill Tkhai spin_unlock(&fpq->lock);
18947407a10dSKirill Tkhai goto copy_finish;
18957407a10dSKirill Tkhai }
1896334f485dSMiklos Szeredi
18973a5358d1SKirill Tkhai /* Is it an interrupt reply ID? */
18983a5358d1SKirill Tkhai if (oh.unique & FUSE_INT_REQ_BIT) {
1899d2d2d4fbSKirill Tkhai __fuse_get_request(req);
190045a91cb1SMiklos Szeredi spin_unlock(&fpq->lock);
190145a91cb1SMiklos Szeredi
19027407a10dSKirill Tkhai err = 0;
19037407a10dSKirill Tkhai if (nbytes != sizeof(struct fuse_out_header))
1904a4d27e75SMiklos Szeredi err = -EINVAL;
19057407a10dSKirill Tkhai else if (oh.error == -ENOSYS)
1906a4d27e75SMiklos Szeredi fc->no_interrupt = 1;
1907a4d27e75SMiklos Szeredi else if (oh.error == -EAGAIN)
19088f622e94SMax Reitz err = queue_interrupt(req);
19097407a10dSKirill Tkhai
19108f622e94SMax Reitz fuse_put_request(req);
1911a4d27e75SMiklos Szeredi
19127407a10dSKirill Tkhai goto copy_finish;
1913a4d27e75SMiklos Szeredi }
1914a4d27e75SMiklos Szeredi
191533e14b4dSMiklos Szeredi clear_bit(FR_SENT, &req->flags);
19163a2b5b9cSMiklos Szeredi list_move(&req->list, &fpq->io);
1917334f485dSMiklos Szeredi req->out.h = oh;
1918825d6d33SMiklos Szeredi set_bit(FR_LOCKED, &req->flags);
191945a91cb1SMiklos Szeredi spin_unlock(&fpq->lock);
1920dd3bb14fSMiklos Szeredi cs->req = req;
1921d4993774SMiklos Szeredi if (!req->args->page_replace)
1922ce534fb0SMiklos Szeredi cs->move_pages = 0;
1923334f485dSMiklos Szeredi
1924d4993774SMiklos Szeredi if (oh.error)
1925d4993774SMiklos Szeredi err = nbytes != sizeof(oh) ? -EINVAL : 0;
1926d4993774SMiklos Szeredi else
1927d4993774SMiklos Szeredi err = copy_out_args(cs, req->args, nbytes);
1928dd3bb14fSMiklos Szeredi fuse_copy_finish(cs);
1929334f485dSMiklos Szeredi
193045a91cb1SMiklos Szeredi spin_lock(&fpq->lock);
1931825d6d33SMiklos Szeredi clear_bit(FR_LOCKED, &req->flags);
1932e96edd94SMiklos Szeredi if (!fpq->connected)
1933334f485dSMiklos Szeredi err = -ENOENT;
19340d8e84b0SMiklos Szeredi else if (err)
1935334f485dSMiklos Szeredi req->out.h.error = -EIO;
193677cd9d48SMiklos Szeredi if (!test_bit(FR_PRIVATE, &req->flags))
1937f377cb79SMiklos Szeredi list_del_init(&req->list);
193845a91cb1SMiklos Szeredi spin_unlock(&fpq->lock);
193946c34a34SMiklos Szeredi
19408f622e94SMax Reitz fuse_request_end(req);
19417407a10dSKirill Tkhai out:
1942334f485dSMiklos Szeredi return err ? err : nbytes;
1943334f485dSMiklos Szeredi
19447407a10dSKirill Tkhai copy_finish:
1945dd3bb14fSMiklos Szeredi fuse_copy_finish(cs);
19467407a10dSKirill Tkhai goto out;
1947334f485dSMiklos Szeredi }
1948334f485dSMiklos Szeredi
fuse_dev_write(struct kiocb * iocb,struct iov_iter * from)1949fbdbaccaSAl Viro static ssize_t fuse_dev_write(struct kiocb *iocb, struct iov_iter *from)
1950dd3bb14fSMiklos Szeredi {
1951dd3bb14fSMiklos Szeredi struct fuse_copy_state cs;
1952cc080e9eSMiklos Szeredi struct fuse_dev *fud = fuse_get_dev(iocb->ki_filp);
1953cc080e9eSMiklos Szeredi
1954cc080e9eSMiklos Szeredi if (!fud)
1955dd3bb14fSMiklos Szeredi return -EPERM;
1956dd3bb14fSMiklos Szeredi
1957fcb14cb1SAl Viro if (!user_backed_iter(from))
1958fbdbaccaSAl Viro return -EINVAL;
1959dd3bb14fSMiklos Szeredi
1960dc00809aSMiklos Szeredi fuse_copy_init(&cs, 0, from);
1961fbdbaccaSAl Viro
1962c3696046SMiklos Szeredi return fuse_dev_do_write(fud, &cs, iov_iter_count(from));
1963dd3bb14fSMiklos Szeredi }
1964dd3bb14fSMiklos Szeredi
fuse_dev_splice_write(struct pipe_inode_info * pipe,struct file * out,loff_t * ppos,size_t len,unsigned int flags)1965dd3bb14fSMiklos Szeredi static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
1966dd3bb14fSMiklos Szeredi struct file *out, loff_t *ppos,
1967dd3bb14fSMiklos Szeredi size_t len, unsigned int flags)
1968dd3bb14fSMiklos Szeredi {
19698cefc107SDavid Howells unsigned int head, tail, mask, count;
1970dd3bb14fSMiklos Szeredi unsigned nbuf;
1971dd3bb14fSMiklos Szeredi unsigned idx;
1972dd3bb14fSMiklos Szeredi struct pipe_buffer *bufs;
1973dd3bb14fSMiklos Szeredi struct fuse_copy_state cs;
1974cc080e9eSMiklos Szeredi struct fuse_dev *fud;
1975dd3bb14fSMiklos Szeredi size_t rem;
1976dd3bb14fSMiklos Szeredi ssize_t ret;
1977dd3bb14fSMiklos Szeredi
1978cc080e9eSMiklos Szeredi fud = fuse_get_dev(out);
1979cc080e9eSMiklos Szeredi if (!fud)
1980dd3bb14fSMiklos Szeredi return -EPERM;
1981dd3bb14fSMiklos Szeredi
1982a2477b0eSAndrey Ryabinin pipe_lock(pipe);
1983a2477b0eSAndrey Ryabinin
19848cefc107SDavid Howells head = pipe->head;
19858cefc107SDavid Howells tail = pipe->tail;
19868cefc107SDavid Howells mask = pipe->ring_size - 1;
19878cefc107SDavid Howells count = head - tail;
19888cefc107SDavid Howells
19898cefc107SDavid Howells bufs = kvmalloc_array(count, sizeof(struct pipe_buffer), GFP_KERNEL);
1990a2477b0eSAndrey Ryabinin if (!bufs) {
1991a2477b0eSAndrey Ryabinin pipe_unlock(pipe);
1992dd3bb14fSMiklos Szeredi return -ENOMEM;
1993a2477b0eSAndrey Ryabinin }
1994dd3bb14fSMiklos Szeredi
1995dd3bb14fSMiklos Szeredi nbuf = 0;
1996dd3bb14fSMiklos Szeredi rem = 0;
199776f6777cSDavid Howells for (idx = tail; idx != head && rem < len; idx++)
19988cefc107SDavid Howells rem += pipe->bufs[idx & mask].len;
1999dd3bb14fSMiklos Szeredi
2000dd3bb14fSMiklos Szeredi ret = -EINVAL;
200115fab63eSMatthew Wilcox if (rem < len)
200215fab63eSMatthew Wilcox goto out_free;
2003dd3bb14fSMiklos Szeredi
2004dd3bb14fSMiklos Szeredi rem = len;
2005dd3bb14fSMiklos Szeredi while (rem) {
2006dd3bb14fSMiklos Szeredi struct pipe_buffer *ibuf;
2007dd3bb14fSMiklos Szeredi struct pipe_buffer *obuf;
2008dd3bb14fSMiklos Szeredi
20090e9fb6f1SVasily Averin if (WARN_ON(nbuf >= count || tail == head))
20100e9fb6f1SVasily Averin goto out_free;
20110e9fb6f1SVasily Averin
20128cefc107SDavid Howells ibuf = &pipe->bufs[tail & mask];
2013dd3bb14fSMiklos Szeredi obuf = &bufs[nbuf];
2014dd3bb14fSMiklos Szeredi
2015dd3bb14fSMiklos Szeredi if (rem >= ibuf->len) {
2016dd3bb14fSMiklos Szeredi *obuf = *ibuf;
2017dd3bb14fSMiklos Szeredi ibuf->ops = NULL;
20188cefc107SDavid Howells tail++;
20198cefc107SDavid Howells pipe->tail = tail;
2020dd3bb14fSMiklos Szeredi } else {
202115fab63eSMatthew Wilcox if (!pipe_buf_get(pipe, ibuf))
202215fab63eSMatthew Wilcox goto out_free;
202315fab63eSMatthew Wilcox
2024dd3bb14fSMiklos Szeredi *obuf = *ibuf;
2025dd3bb14fSMiklos Szeredi obuf->flags &= ~PIPE_BUF_FLAG_GIFT;
2026dd3bb14fSMiklos Szeredi obuf->len = rem;
2027dd3bb14fSMiklos Szeredi ibuf->offset += obuf->len;
2028dd3bb14fSMiklos Szeredi ibuf->len -= obuf->len;
2029dd3bb14fSMiklos Szeredi }
2030dd3bb14fSMiklos Szeredi nbuf++;
2031dd3bb14fSMiklos Szeredi rem -= obuf->len;
2032dd3bb14fSMiklos Szeredi }
2033dd3bb14fSMiklos Szeredi pipe_unlock(pipe);
2034dd3bb14fSMiklos Szeredi
2035dc00809aSMiklos Szeredi fuse_copy_init(&cs, 0, NULL);
2036dd3bb14fSMiklos Szeredi cs.pipebufs = bufs;
20376c09e94aSAl Viro cs.nr_segs = nbuf;
2038dd3bb14fSMiklos Szeredi cs.pipe = pipe;
2039dd3bb14fSMiklos Szeredi
2040ce534fb0SMiklos Szeredi if (flags & SPLICE_F_MOVE)
2041ce534fb0SMiklos Szeredi cs.move_pages = 1;
2042ce534fb0SMiklos Szeredi
2043c3696046SMiklos Szeredi ret = fuse_dev_do_write(fud, &cs, len);
2044dd3bb14fSMiklos Szeredi
20459509941eSJann Horn pipe_lock(pipe);
204615fab63eSMatthew Wilcox out_free:
2047712a9510SMiklos Szeredi for (idx = 0; idx < nbuf; idx++) {
2048712a9510SMiklos Szeredi struct pipe_buffer *buf = &bufs[idx];
2049712a9510SMiklos Szeredi
2050712a9510SMiklos Szeredi if (buf->ops)
2051712a9510SMiklos Szeredi pipe_buf_release(pipe, buf);
2052712a9510SMiklos Szeredi }
20539509941eSJann Horn pipe_unlock(pipe);
2054a779638cSMiklos Szeredi
2055d6d931adSAndrey Ryabinin kvfree(bufs);
2056dd3bb14fSMiklos Szeredi return ret;
2057dd3bb14fSMiklos Szeredi }
2058dd3bb14fSMiklos Szeredi
fuse_dev_poll(struct file * file,poll_table * wait)2059076ccb76SAl Viro static __poll_t fuse_dev_poll(struct file *file, poll_table *wait)
2060334f485dSMiklos Szeredi {
2061a9a08845SLinus Torvalds __poll_t mask = EPOLLOUT | EPOLLWRNORM;
2062f88996a9SMiklos Szeredi struct fuse_iqueue *fiq;
2063cc080e9eSMiklos Szeredi struct fuse_dev *fud = fuse_get_dev(file);
2064cc080e9eSMiklos Szeredi
2065cc080e9eSMiklos Szeredi if (!fud)
2066a9a08845SLinus Torvalds return EPOLLERR;
2067334f485dSMiklos Szeredi
2068cc080e9eSMiklos Szeredi fiq = &fud->fc->iq;
2069f88996a9SMiklos Szeredi poll_wait(file, &fiq->waitq, wait);
2070334f485dSMiklos Szeredi
207176e43c8cSEric Biggers spin_lock(&fiq->lock);
2072e16714d8SMiklos Szeredi if (!fiq->connected)
2073a9a08845SLinus Torvalds mask = EPOLLERR;
2074f88996a9SMiklos Szeredi else if (request_pending(fiq))
2075a9a08845SLinus Torvalds mask |= EPOLLIN | EPOLLRDNORM;
207676e43c8cSEric Biggers spin_unlock(&fiq->lock);
2077334f485dSMiklos Szeredi
2078334f485dSMiklos Szeredi return mask;
2079334f485dSMiklos Szeredi }
2080334f485dSMiklos Szeredi
208134061750SKirill Tkhai /* Abort all requests on the given list (pending or processing) */
end_requests(struct list_head * head)20828f622e94SMax Reitz static void end_requests(struct list_head *head)
2083334f485dSMiklos Szeredi {
2084334f485dSMiklos Szeredi while (!list_empty(head)) {
2085334f485dSMiklos Szeredi struct fuse_req *req;
2086334f485dSMiklos Szeredi req = list_entry(head->next, struct fuse_req, list);
2087334f485dSMiklos Szeredi req->out.h.error = -ECONNABORTED;
208833e14b4dSMiklos Szeredi clear_bit(FR_SENT, &req->flags);
2089f377cb79SMiklos Szeredi list_del_init(&req->list);
20908f622e94SMax Reitz fuse_request_end(req);
2091334f485dSMiklos Szeredi }
2092334f485dSMiklos Szeredi }
2093334f485dSMiklos Szeredi
end_polls(struct fuse_conn * fc)2094357ccf2bSBryan Green static void end_polls(struct fuse_conn *fc)
2095357ccf2bSBryan Green {
2096357ccf2bSBryan Green struct rb_node *p;
2097357ccf2bSBryan Green
2098357ccf2bSBryan Green p = rb_first(&fc->polled_files);
2099357ccf2bSBryan Green
2100357ccf2bSBryan Green while (p) {
2101357ccf2bSBryan Green struct fuse_file *ff;
2102357ccf2bSBryan Green ff = rb_entry(p, struct fuse_file, polled_node);
2103357ccf2bSBryan Green wake_up_interruptible_all(&ff->poll_wait);
2104357ccf2bSBryan Green
2105357ccf2bSBryan Green p = rb_next(p);
2106357ccf2bSBryan Green }
2107357ccf2bSBryan Green }
2108357ccf2bSBryan Green
210969a53bf2SMiklos Szeredi /*
211069a53bf2SMiklos Szeredi * Abort all requests.
211169a53bf2SMiklos Szeredi *
2112b716d425SMiklos Szeredi * Emergency exit in case of a malicious or accidental deadlock, or just a hung
2113b716d425SMiklos Szeredi * filesystem.
211469a53bf2SMiklos Szeredi *
2115b716d425SMiklos Szeredi * The same effect is usually achievable through killing the filesystem daemon
2116b716d425SMiklos Szeredi * and all users of the filesystem. The exception is the combination of an
2117b716d425SMiklos Szeredi * asynchronous request and the tricky deadlock (see
211872ef5e52SMauro Carvalho Chehab * Documentation/filesystems/fuse.rst).
211969a53bf2SMiklos Szeredi *
2120b716d425SMiklos Szeredi * Aborting requests under I/O goes as follows: 1: Separate out unlocked
2121b716d425SMiklos Szeredi * requests, they should be finished off immediately. Locked requests will be
2122b716d425SMiklos Szeredi * finished after unlock; see unlock_request(). 2: Finish off the unlocked
2123b716d425SMiklos Szeredi * requests. It is possible that some request will finish before we can. This
2124b716d425SMiklos Szeredi * is OK, the request will in that case be removed from the list before we touch
2125b716d425SMiklos Szeredi * it.
212669a53bf2SMiklos Szeredi */
fuse_abort_conn(struct fuse_conn * fc)2127eb98e3bdSMiklos Szeredi void fuse_abort_conn(struct fuse_conn *fc)
212869a53bf2SMiklos Szeredi {
2129f88996a9SMiklos Szeredi struct fuse_iqueue *fiq = &fc->iq;
2130f88996a9SMiklos Szeredi
2131d7133114SMiklos Szeredi spin_lock(&fc->lock);
213269a53bf2SMiklos Szeredi if (fc->connected) {
2133c3696046SMiklos Szeredi struct fuse_dev *fud;
2134b716d425SMiklos Szeredi struct fuse_req *req, *next;
213575f3ee4cSMiklos Szeredi LIST_HEAD(to_end);
2136be2ff42cSKirill Tkhai unsigned int i;
2137b716d425SMiklos Szeredi
213863825b4eSKirill Tkhai /* Background queuing checks fc->connected under bg_lock */
213963825b4eSKirill Tkhai spin_lock(&fc->bg_lock);
214069a53bf2SMiklos Szeredi fc->connected = 0;
214163825b4eSKirill Tkhai spin_unlock(&fc->bg_lock);
214263825b4eSKirill Tkhai
21439759bd51SMiklos Szeredi fuse_set_initialized(fc);
2144c3696046SMiklos Szeredi list_for_each_entry(fud, &fc->devices, entry) {
2145c3696046SMiklos Szeredi struct fuse_pqueue *fpq = &fud->pq;
2146c3696046SMiklos Szeredi
214745a91cb1SMiklos Szeredi spin_lock(&fpq->lock);
2148e96edd94SMiklos Szeredi fpq->connected = 0;
21493a2b5b9cSMiklos Szeredi list_for_each_entry_safe(req, next, &fpq->io, list) {
2150b716d425SMiklos Szeredi req->out.h.error = -ECONNABORTED;
2151b716d425SMiklos Szeredi spin_lock(&req->waitq.lock);
2152b716d425SMiklos Szeredi set_bit(FR_ABORTED, &req->flags);
215377cd9d48SMiklos Szeredi if (!test_bit(FR_LOCKED, &req->flags)) {
215477cd9d48SMiklos Szeredi set_bit(FR_PRIVATE, &req->flags);
215587114373SMiklos Szeredi __fuse_get_request(req);
215675f3ee4cSMiklos Szeredi list_move(&req->list, &to_end);
215777cd9d48SMiklos Szeredi }
2158b716d425SMiklos Szeredi spin_unlock(&req->waitq.lock);
2159b716d425SMiklos Szeredi }
2160be2ff42cSKirill Tkhai for (i = 0; i < FUSE_PQ_HASH_SIZE; i++)
2161be2ff42cSKirill Tkhai list_splice_tail_init(&fpq->processing[i],
2162be2ff42cSKirill Tkhai &to_end);
216345a91cb1SMiklos Szeredi spin_unlock(&fpq->lock);
2164c3696046SMiklos Szeredi }
2165ae2dffa3SKirill Tkhai spin_lock(&fc->bg_lock);
2166ae2dffa3SKirill Tkhai fc->blocked = 0;
216741f98274SMiklos Szeredi fc->max_background = UINT_MAX;
216841f98274SMiklos Szeredi flush_bg_queue(fc);
2169ae2dffa3SKirill Tkhai spin_unlock(&fc->bg_lock);
21708c91189aSMiklos Szeredi
217176e43c8cSEric Biggers spin_lock(&fiq->lock);
21728c91189aSMiklos Szeredi fiq->connected = 0;
217375f3ee4cSMiklos Szeredi list_for_each_entry(req, &fiq->pending, list)
2174a8a86d78STahsin Erdogan clear_bit(FR_PENDING, &req->flags);
217575f3ee4cSMiklos Szeredi list_splice_tail_init(&fiq->pending, &to_end);
21768c91189aSMiklos Szeredi while (forget_pending(fiq))
21774388c5aaSVivek Goyal kfree(fuse_dequeue_forget(fiq, 1, NULL));
217876e43c8cSEric Biggers wake_up_all(&fiq->waitq);
217976e43c8cSEric Biggers spin_unlock(&fiq->lock);
21808c91189aSMiklos Szeredi kill_fasync(&fiq->fasync, SIGIO, POLL_IN);
2181ee314a87SMiklos Szeredi end_polls(fc);
2182ee314a87SMiklos Szeredi wake_up_all(&fc->blocked_waitq);
2183ee314a87SMiklos Szeredi spin_unlock(&fc->lock);
21848c91189aSMiklos Szeredi
21858f622e94SMax Reitz end_requests(&to_end);
2186ee314a87SMiklos Szeredi } else {
2187d7133114SMiklos Szeredi spin_unlock(&fc->lock);
218869a53bf2SMiklos Szeredi }
2189ee314a87SMiklos Szeredi }
219008cbf542STejun Heo EXPORT_SYMBOL_GPL(fuse_abort_conn);
219169a53bf2SMiklos Szeredi
fuse_wait_aborted(struct fuse_conn * fc)2192b8f95e5dSMiklos Szeredi void fuse_wait_aborted(struct fuse_conn *fc)
2193b8f95e5dSMiklos Szeredi {
21942d84a2d1SMiklos Szeredi /* matches implicit memory barrier in fuse_drop_waiting() */
21952d84a2d1SMiklos Szeredi smp_mb();
2196b8f95e5dSMiklos Szeredi wait_event(fc->blocked_waitq, atomic_read(&fc->num_waiting) == 0);
2197b8f95e5dSMiklos Szeredi }
2198b8f95e5dSMiklos Szeredi
fuse_dev_release(struct inode * inode,struct file * file)219908cbf542STejun Heo int fuse_dev_release(struct inode *inode, struct file *file)
2200334f485dSMiklos Szeredi {
2201cc080e9eSMiklos Szeredi struct fuse_dev *fud = fuse_get_dev(file);
2202cc080e9eSMiklos Szeredi
2203cc080e9eSMiklos Szeredi if (fud) {
2204cc080e9eSMiklos Szeredi struct fuse_conn *fc = fud->fc;
2205c3696046SMiklos Szeredi struct fuse_pqueue *fpq = &fud->pq;
220645ff350bSMiklos Szeredi LIST_HEAD(to_end);
2207be2ff42cSKirill Tkhai unsigned int i;
2208cc080e9eSMiklos Szeredi
220945ff350bSMiklos Szeredi spin_lock(&fpq->lock);
2210c3696046SMiklos Szeredi WARN_ON(!list_empty(&fpq->io));
2211be2ff42cSKirill Tkhai for (i = 0; i < FUSE_PQ_HASH_SIZE; i++)
2212be2ff42cSKirill Tkhai list_splice_init(&fpq->processing[i], &to_end);
221345ff350bSMiklos Szeredi spin_unlock(&fpq->lock);
221445ff350bSMiklos Szeredi
22158f622e94SMax Reitz end_requests(&to_end);
221645ff350bSMiklos Szeredi
2217c3696046SMiklos Szeredi /* Are we the last open device? */
2218c3696046SMiklos Szeredi if (atomic_dec_and_test(&fc->dev_count)) {
2219f88996a9SMiklos Szeredi WARN_ON(fc->iq.fasync != NULL);
2220eb98e3bdSMiklos Szeredi fuse_abort_conn(fc);
2221c3696046SMiklos Szeredi }
2222cc080e9eSMiklos Szeredi fuse_dev_free(fud);
2223385a17bfSJeff Dike }
2224334f485dSMiklos Szeredi return 0;
2225334f485dSMiklos Szeredi }
222608cbf542STejun Heo EXPORT_SYMBOL_GPL(fuse_dev_release);
2227334f485dSMiklos Szeredi
fuse_dev_fasync(int fd,struct file * file,int on)2228385a17bfSJeff Dike static int fuse_dev_fasync(int fd, struct file *file, int on)
2229385a17bfSJeff Dike {
2230cc080e9eSMiklos Szeredi struct fuse_dev *fud = fuse_get_dev(file);
2231cc080e9eSMiklos Szeredi
2232cc080e9eSMiklos Szeredi if (!fud)
2233a87046d8SMiklos Szeredi return -EPERM;
2234385a17bfSJeff Dike
2235385a17bfSJeff Dike /* No locking - fasync_helper does its own locking */
2236cc080e9eSMiklos Szeredi return fasync_helper(fd, file, on, &fud->fc->iq.fasync);
2237385a17bfSJeff Dike }
2238385a17bfSJeff Dike
fuse_device_clone(struct fuse_conn * fc,struct file * new)223900c570f4SMiklos Szeredi static int fuse_device_clone(struct fuse_conn *fc, struct file *new)
224000c570f4SMiklos Szeredi {
2241cc080e9eSMiklos Szeredi struct fuse_dev *fud;
2242cc080e9eSMiklos Szeredi
224300c570f4SMiklos Szeredi if (new->private_data)
224400c570f4SMiklos Szeredi return -EINVAL;
224500c570f4SMiklos Szeredi
22460cd1eb9aSVivek Goyal fud = fuse_dev_alloc_install(fc);
2247cc080e9eSMiklos Szeredi if (!fud)
2248cc080e9eSMiklos Szeredi return -ENOMEM;
2249cc080e9eSMiklos Szeredi
2250cc080e9eSMiklos Szeredi new->private_data = fud;
2251c3696046SMiklos Szeredi atomic_inc(&fc->dev_count);
225200c570f4SMiklos Szeredi
225300c570f4SMiklos Szeredi return 0;
225400c570f4SMiklos Szeredi }
225500c570f4SMiklos Szeredi
fuse_dev_ioctl(struct file * file,unsigned int cmd,unsigned long arg)225600c570f4SMiklos Szeredi static long fuse_dev_ioctl(struct file *file, unsigned int cmd,
225700c570f4SMiklos Szeredi unsigned long arg)
225800c570f4SMiklos Szeredi {
2259f8425c93SAlessio Balsini int res;
226000c570f4SMiklos Szeredi int oldfd;
2261f8425c93SAlessio Balsini struct fuse_dev *fud = NULL;
22624a892c0fSAl Viro struct fd f;
226300c570f4SMiklos Szeredi
22646076f5f3SAlessio Balsini switch (cmd) {
22656076f5f3SAlessio Balsini case FUSE_DEV_IOC_CLONE:
22664a892c0fSAl Viro if (get_user(oldfd, (__u32 __user *)arg))
22674a892c0fSAl Viro return -EFAULT;
226800c570f4SMiklos Szeredi
22694a892c0fSAl Viro f = fdget(oldfd);
22704a892c0fSAl Viro if (!f.file)
22714a892c0fSAl Viro return -EINVAL;
22724a892c0fSAl Viro
22738ed1f0e2SJann Horn /*
22748ed1f0e2SJann Horn * Check against file->f_op because CUSE
22758ed1f0e2SJann Horn * uses the same ioctl handler.
22768ed1f0e2SJann Horn */
22774a892c0fSAl Viro if (f.file->f_op == file->f_op)
22784a892c0fSAl Viro fud = fuse_get_dev(f.file);
227900c570f4SMiklos Szeredi
22804a892c0fSAl Viro res = -EINVAL;
2281cc080e9eSMiklos Szeredi if (fud) {
228200c570f4SMiklos Szeredi mutex_lock(&fuse_mutex);
2283f8425c93SAlessio Balsini res = fuse_device_clone(fud->fc, file);
228400c570f4SMiklos Szeredi mutex_unlock(&fuse_mutex);
228500c570f4SMiklos Szeredi }
22864a892c0fSAl Viro fdput(f);
2287f8425c93SAlessio Balsini break;
2288f8425c93SAlessio Balsini default:
2289f8425c93SAlessio Balsini res = -ENOTTY;
2290f8425c93SAlessio Balsini break;
229100c570f4SMiklos Szeredi }
2292f8425c93SAlessio Balsini return res;
229300c570f4SMiklos Szeredi }
229400c570f4SMiklos Szeredi
22954b6f5d20SArjan van de Ven const struct file_operations fuse_dev_operations = {
2296334f485dSMiklos Szeredi .owner = THIS_MODULE,
229794e4fe2cSTom Van Braeckel .open = fuse_dev_open,
2298334f485dSMiklos Szeredi .llseek = no_llseek,
2299fbdbaccaSAl Viro .read_iter = fuse_dev_read,
2300c3021629SMiklos Szeredi .splice_read = fuse_dev_splice_read,
2301fbdbaccaSAl Viro .write_iter = fuse_dev_write,
2302dd3bb14fSMiklos Szeredi .splice_write = fuse_dev_splice_write,
2303334f485dSMiklos Szeredi .poll = fuse_dev_poll,
2304334f485dSMiklos Szeredi .release = fuse_dev_release,
2305385a17bfSJeff Dike .fasync = fuse_dev_fasync,
230600c570f4SMiklos Szeredi .unlocked_ioctl = fuse_dev_ioctl,
23071832f2d8SArnd Bergmann .compat_ioctl = compat_ptr_ioctl,
2308334f485dSMiklos Szeredi };
230908cbf542STejun Heo EXPORT_SYMBOL_GPL(fuse_dev_operations);
2310334f485dSMiklos Szeredi
2311334f485dSMiklos Szeredi static struct miscdevice fuse_miscdevice = {
2312334f485dSMiklos Szeredi .minor = FUSE_MINOR,
2313334f485dSMiklos Szeredi .name = "fuse",
2314334f485dSMiklos Szeredi .fops = &fuse_dev_operations,
2315334f485dSMiklos Szeredi };
2316334f485dSMiklos Szeredi
fuse_dev_init(void)2317334f485dSMiklos Szeredi int __init fuse_dev_init(void)
2318334f485dSMiklos Szeredi {
2319334f485dSMiklos Szeredi int err = -ENOMEM;
2320334f485dSMiklos Szeredi fuse_req_cachep = kmem_cache_create("fuse_request",
2321334f485dSMiklos Szeredi sizeof(struct fuse_req),
232220c2df83SPaul Mundt 0, 0, NULL);
2323334f485dSMiklos Szeredi if (!fuse_req_cachep)
2324334f485dSMiklos Szeredi goto out;
2325334f485dSMiklos Szeredi
2326334f485dSMiklos Szeredi err = misc_register(&fuse_miscdevice);
2327334f485dSMiklos Szeredi if (err)
2328334f485dSMiklos Szeredi goto out_cache_clean;
2329334f485dSMiklos Szeredi
2330334f485dSMiklos Szeredi return 0;
2331334f485dSMiklos Szeredi
2332334f485dSMiklos Szeredi out_cache_clean:
2333334f485dSMiklos Szeredi kmem_cache_destroy(fuse_req_cachep);
2334334f485dSMiklos Szeredi out:
2335334f485dSMiklos Szeredi return err;
2336334f485dSMiklos Szeredi }
2337334f485dSMiklos Szeredi
fuse_dev_cleanup(void)2338334f485dSMiklos Szeredi void fuse_dev_cleanup(void)
2339334f485dSMiklos Szeredi {
2340334f485dSMiklos Szeredi misc_deregister(&fuse_miscdevice);
2341334f485dSMiklos Szeredi kmem_cache_destroy(fuse_req_cachep);
2342334f485dSMiklos Szeredi }
2343