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 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 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 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 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 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 */ 73334f485dSMiklos Szeredi static void __fuse_put_request(struct fuse_req *req) 74334f485dSMiklos Szeredi { 75ec99f6d3SElena Reshetova refcount_dec(&req->count); 76334f485dSMiklos Szeredi } 77334f485dSMiklos Szeredi 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 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 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 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 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 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 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 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 207ae3aad77SStefan Hajnoczi /** 208ae3aad77SStefan Hajnoczi * A new request is available, wake fiq->waitq 209ae3aad77SStefan Hajnoczi */ 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 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 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 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 */ 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 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 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 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 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 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 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; 4793e8cb8b2SMiklos Szeredi if (args->end) 4803e8cb8b2SMiklos Szeredi __set_bit(FR_ASYNC, &req->flags); 48168583165SMiklos Szeredi } 48268583165SMiklos Szeredi 483fcee216bSMax Reitz ssize_t fuse_simple_request(struct fuse_mount *fm, struct fuse_args *args) 4847078187aSMiklos Szeredi { 485fcee216bSMax Reitz struct fuse_conn *fc = fm->fc; 4867078187aSMiklos Szeredi struct fuse_req *req; 4877078187aSMiklos Szeredi ssize_t ret; 4887078187aSMiklos Szeredi 489c500ebaaSMiklos Szeredi if (args->force) { 490e413754bSMiklos Szeredi atomic_inc(&fc->num_waiting); 491fcee216bSMax Reitz req = fuse_request_alloc(fm, GFP_KERNEL | __GFP_NOFAIL); 492e413754bSMiklos Szeredi 493e413754bSMiklos Szeredi if (!args->nocreds) 4948f622e94SMax Reitz fuse_force_creds(req); 495e413754bSMiklos Szeredi 496e413754bSMiklos Szeredi __set_bit(FR_WAITING, &req->flags); 497c500ebaaSMiklos Szeredi __set_bit(FR_FORCE, &req->flags); 498c500ebaaSMiklos Szeredi } else { 499e413754bSMiklos Szeredi WARN_ON(args->nocreds); 500fcee216bSMax Reitz req = fuse_get_req(fm, false); 5017078187aSMiklos Szeredi if (IS_ERR(req)) 5027078187aSMiklos Szeredi return PTR_ERR(req); 503c500ebaaSMiklos Szeredi } 5047078187aSMiklos Szeredi 50521f62174SMiklos Szeredi /* Needs to be done after fuse_get_req() so that fc->minor is valid */ 50621f62174SMiklos Szeredi fuse_adjust_compat(fc, args); 50768583165SMiklos Szeredi fuse_args_to_req(req, args); 50821f62174SMiklos Szeredi 509454a7613SMiklos Szeredi if (!args->noreply) 510454a7613SMiklos Szeredi __set_bit(FR_ISREPLY, &req->flags); 5118f622e94SMax Reitz __fuse_request_send(req); 5127078187aSMiklos Szeredi ret = req->out.h.error; 513d5b48543SMiklos Szeredi if (!ret && args->out_argvar) { 514093f38a2SMiklos Szeredi BUG_ON(args->out_numargs == 0); 515d4993774SMiklos Szeredi ret = args->out_args[args->out_numargs - 1].size; 5167078187aSMiklos Szeredi } 5178f622e94SMax Reitz fuse_put_request(req); 5187078187aSMiklos Szeredi 5197078187aSMiklos Szeredi return ret; 5207078187aSMiklos Szeredi } 5217078187aSMiklos Szeredi 5228f622e94SMax Reitz static bool fuse_request_queue_background(struct fuse_req *req) 523334f485dSMiklos Szeredi { 524fcee216bSMax Reitz struct fuse_mount *fm = req->fm; 525fcee216bSMax Reitz struct fuse_conn *fc = fm->fc; 52663825b4eSKirill Tkhai bool queued = false; 52763825b4eSKirill Tkhai 52863825b4eSKirill Tkhai WARN_ON(!test_bit(FR_BACKGROUND, &req->flags)); 529825d6d33SMiklos Szeredi if (!test_bit(FR_WAITING, &req->flags)) { 530825d6d33SMiklos Szeredi __set_bit(FR_WAITING, &req->flags); 5315437f241SMiklos Szeredi atomic_inc(&fc->num_waiting); 5325437f241SMiklos Szeredi } 533825d6d33SMiklos Szeredi __set_bit(FR_ISREPLY, &req->flags); 534ae2dffa3SKirill Tkhai spin_lock(&fc->bg_lock); 53563825b4eSKirill Tkhai if (likely(fc->connected)) { 53651eb01e7SMiklos Szeredi fc->num_background++; 5377a6d3c8bSCsaba Henk if (fc->num_background == fc->max_background) 53851eb01e7SMiklos Szeredi fc->blocked = 1; 539d12def1bSMiklos Szeredi list_add_tail(&req->list, &fc->bg_queue); 540d12def1bSMiklos Szeredi flush_bg_queue(fc); 54163825b4eSKirill Tkhai queued = true; 54263825b4eSKirill Tkhai } 543ae2dffa3SKirill Tkhai spin_unlock(&fc->bg_lock); 54463825b4eSKirill Tkhai 54563825b4eSKirill Tkhai return queued; 546d12def1bSMiklos Szeredi } 54751eb01e7SMiklos Szeredi 548fcee216bSMax Reitz int fuse_simple_background(struct fuse_mount *fm, struct fuse_args *args, 54912597287SMiklos Szeredi gfp_t gfp_flags) 55012597287SMiklos Szeredi { 55112597287SMiklos Szeredi struct fuse_req *req; 55212597287SMiklos Szeredi 55312597287SMiklos Szeredi if (args->force) { 55412597287SMiklos Szeredi WARN_ON(!args->nocreds); 555fcee216bSMax Reitz req = fuse_request_alloc(fm, gfp_flags); 55612597287SMiklos Szeredi if (!req) 55712597287SMiklos Szeredi return -ENOMEM; 55812597287SMiklos Szeredi __set_bit(FR_BACKGROUND, &req->flags); 55912597287SMiklos Szeredi } else { 56012597287SMiklos Szeredi WARN_ON(args->nocreds); 561fcee216bSMax Reitz req = fuse_get_req(fm, true); 56212597287SMiklos Szeredi if (IS_ERR(req)) 56312597287SMiklos Szeredi return PTR_ERR(req); 56412597287SMiklos Szeredi } 56512597287SMiklos Szeredi 56612597287SMiklos Szeredi fuse_args_to_req(req, args); 56712597287SMiklos Szeredi 5688f622e94SMax Reitz if (!fuse_request_queue_background(req)) { 5698f622e94SMax Reitz fuse_put_request(req); 57012597287SMiklos Szeredi return -ENOTCONN; 57112597287SMiklos Szeredi } 57212597287SMiklos Szeredi 57312597287SMiklos Szeredi return 0; 57412597287SMiklos Szeredi } 57512597287SMiklos Szeredi EXPORT_SYMBOL_GPL(fuse_simple_background); 57612597287SMiklos Szeredi 577fcee216bSMax Reitz static int fuse_simple_notify_reply(struct fuse_mount *fm, 57875b399ddSMiklos Szeredi struct fuse_args *args, u64 unique) 5792d45ba38SMiklos Szeredi { 58075b399ddSMiklos Szeredi struct fuse_req *req; 581fcee216bSMax Reitz struct fuse_iqueue *fiq = &fm->fc->iq; 58275b399ddSMiklos Szeredi int err = 0; 58375b399ddSMiklos Szeredi 584fcee216bSMax Reitz req = fuse_get_req(fm, false); 58575b399ddSMiklos Szeredi if (IS_ERR(req)) 58675b399ddSMiklos Szeredi return PTR_ERR(req); 5872d45ba38SMiklos Szeredi 588825d6d33SMiklos Szeredi __clear_bit(FR_ISREPLY, &req->flags); 5892d45ba38SMiklos Szeredi req->in.h.unique = unique; 59075b399ddSMiklos Szeredi 59175b399ddSMiklos Szeredi fuse_args_to_req(req, args); 59275b399ddSMiklos Szeredi 59376e43c8cSEric Biggers spin_lock(&fiq->lock); 594e16714d8SMiklos Szeredi if (fiq->connected) { 595ae3aad77SStefan Hajnoczi queue_request_and_unlock(fiq, req); 59675b399ddSMiklos Szeredi } else { 59775b399ddSMiklos Szeredi err = -ENODEV; 59875b399ddSMiklos Szeredi spin_unlock(&fiq->lock); 5998f622e94SMax Reitz fuse_put_request(req); 6002d45ba38SMiklos Szeredi } 6012d45ba38SMiklos Szeredi 6022d45ba38SMiklos Szeredi return err; 6032d45ba38SMiklos Szeredi } 6042d45ba38SMiklos Szeredi 6053be5a52bSMiklos Szeredi /* 606334f485dSMiklos Szeredi * Lock the request. Up to the next unlock_request() there mustn't be 607334f485dSMiklos Szeredi * anything that could cause a page-fault. If the request was already 608f9a2842eSMiklos Szeredi * aborted bail out. 609334f485dSMiklos Szeredi */ 610dc00809aSMiklos Szeredi static int lock_request(struct fuse_req *req) 611334f485dSMiklos Szeredi { 612334f485dSMiklos Szeredi int err = 0; 613334f485dSMiklos Szeredi if (req) { 614dc00809aSMiklos Szeredi spin_lock(&req->waitq.lock); 615825d6d33SMiklos Szeredi if (test_bit(FR_ABORTED, &req->flags)) 616334f485dSMiklos Szeredi err = -ENOENT; 617334f485dSMiklos Szeredi else 618825d6d33SMiklos Szeredi set_bit(FR_LOCKED, &req->flags); 619dc00809aSMiklos Szeredi spin_unlock(&req->waitq.lock); 620334f485dSMiklos Szeredi } 621334f485dSMiklos Szeredi return err; 622334f485dSMiklos Szeredi } 623334f485dSMiklos Szeredi 624334f485dSMiklos Szeredi /* 6250d8e84b0SMiklos Szeredi * Unlock request. If it was aborted while locked, caller is responsible 6260d8e84b0SMiklos Szeredi * for unlocking and ending the request. 627334f485dSMiklos Szeredi */ 628dc00809aSMiklos Szeredi static int unlock_request(struct fuse_req *req) 629334f485dSMiklos Szeredi { 6300d8e84b0SMiklos Szeredi int err = 0; 631334f485dSMiklos Szeredi if (req) { 632dc00809aSMiklos Szeredi spin_lock(&req->waitq.lock); 633825d6d33SMiklos Szeredi if (test_bit(FR_ABORTED, &req->flags)) 6340d8e84b0SMiklos Szeredi err = -ENOENT; 6350d8e84b0SMiklos Szeredi else 636825d6d33SMiklos Szeredi clear_bit(FR_LOCKED, &req->flags); 637dc00809aSMiklos Szeredi spin_unlock(&req->waitq.lock); 638334f485dSMiklos Szeredi } 6390d8e84b0SMiklos Szeredi return err; 640334f485dSMiklos Szeredi } 641334f485dSMiklos Szeredi 642334f485dSMiklos Szeredi struct fuse_copy_state { 643334f485dSMiklos Szeredi int write; 644334f485dSMiklos Szeredi struct fuse_req *req; 6456c09e94aSAl Viro struct iov_iter *iter; 646dd3bb14fSMiklos Szeredi struct pipe_buffer *pipebufs; 647dd3bb14fSMiklos Szeredi struct pipe_buffer *currbuf; 648dd3bb14fSMiklos Szeredi struct pipe_inode_info *pipe; 649334f485dSMiklos Szeredi unsigned long nr_segs; 650334f485dSMiklos Szeredi struct page *pg; 651334f485dSMiklos Szeredi unsigned len; 652c55a01d3SMiklos Szeredi unsigned offset; 653ce534fb0SMiklos Szeredi unsigned move_pages:1; 654334f485dSMiklos Szeredi }; 655334f485dSMiklos Szeredi 656dc00809aSMiklos Szeredi static void fuse_copy_init(struct fuse_copy_state *cs, int write, 6576c09e94aSAl Viro struct iov_iter *iter) 658334f485dSMiklos Szeredi { 659334f485dSMiklos Szeredi memset(cs, 0, sizeof(*cs)); 660334f485dSMiklos Szeredi cs->write = write; 6616c09e94aSAl Viro cs->iter = iter; 662334f485dSMiklos Szeredi } 663334f485dSMiklos Szeredi 664334f485dSMiklos Szeredi /* Unmap and put previous page of userspace buffer */ 6658bfc016dSMiklos Szeredi static void fuse_copy_finish(struct fuse_copy_state *cs) 666334f485dSMiklos Szeredi { 667dd3bb14fSMiklos Szeredi if (cs->currbuf) { 668dd3bb14fSMiklos Szeredi struct pipe_buffer *buf = cs->currbuf; 669dd3bb14fSMiklos Szeredi 670c55a01d3SMiklos Szeredi if (cs->write) 671c3021629SMiklos Szeredi buf->len = PAGE_SIZE - cs->len; 672dd3bb14fSMiklos Szeredi cs->currbuf = NULL; 673c55a01d3SMiklos Szeredi } else if (cs->pg) { 674334f485dSMiklos Szeredi if (cs->write) { 675334f485dSMiklos Szeredi flush_dcache_page(cs->pg); 676334f485dSMiklos Szeredi set_page_dirty_lock(cs->pg); 677334f485dSMiklos Szeredi } 678334f485dSMiklos Szeredi put_page(cs->pg); 679334f485dSMiklos Szeredi } 680c55a01d3SMiklos Szeredi cs->pg = NULL; 681334f485dSMiklos Szeredi } 682334f485dSMiklos Szeredi 683334f485dSMiklos Szeredi /* 684334f485dSMiklos Szeredi * Get another pagefull of userspace buffer, and map it to kernel 685334f485dSMiklos Szeredi * address space, and lock request 686334f485dSMiklos Szeredi */ 687334f485dSMiklos Szeredi static int fuse_copy_fill(struct fuse_copy_state *cs) 688334f485dSMiklos Szeredi { 689c55a01d3SMiklos Szeredi struct page *page; 690334f485dSMiklos Szeredi int err; 691334f485dSMiklos Szeredi 692dc00809aSMiklos Szeredi err = unlock_request(cs->req); 6930d8e84b0SMiklos Szeredi if (err) 6940d8e84b0SMiklos Szeredi return err; 6950d8e84b0SMiklos Szeredi 696334f485dSMiklos Szeredi fuse_copy_finish(cs); 697dd3bb14fSMiklos Szeredi if (cs->pipebufs) { 698dd3bb14fSMiklos Szeredi struct pipe_buffer *buf = cs->pipebufs; 699dd3bb14fSMiklos Szeredi 700c3021629SMiklos Szeredi if (!cs->write) { 701fba597dbSMiklos Szeredi err = pipe_buf_confirm(cs->pipe, buf); 702dd3bb14fSMiklos Szeredi if (err) 703dd3bb14fSMiklos Szeredi return err; 704dd3bb14fSMiklos Szeredi 705dd3bb14fSMiklos Szeredi BUG_ON(!cs->nr_segs); 706dd3bb14fSMiklos Szeredi cs->currbuf = buf; 707c55a01d3SMiklos Szeredi cs->pg = buf->page; 708c55a01d3SMiklos Szeredi cs->offset = buf->offset; 709dd3bb14fSMiklos Szeredi cs->len = buf->len; 710dd3bb14fSMiklos Szeredi cs->pipebufs++; 711dd3bb14fSMiklos Szeredi cs->nr_segs--; 712dd3bb14fSMiklos Szeredi } else { 7136718b6f8SDavid Howells if (cs->nr_segs >= cs->pipe->max_usage) 714c3021629SMiklos Szeredi return -EIO; 715c3021629SMiklos Szeredi 716c3021629SMiklos Szeredi page = alloc_page(GFP_HIGHUSER); 717c3021629SMiklos Szeredi if (!page) 718c3021629SMiklos Szeredi return -ENOMEM; 719c3021629SMiklos Szeredi 720c3021629SMiklos Szeredi buf->page = page; 721c3021629SMiklos Szeredi buf->offset = 0; 722c3021629SMiklos Szeredi buf->len = 0; 723c3021629SMiklos Szeredi 724c3021629SMiklos Szeredi cs->currbuf = buf; 725c55a01d3SMiklos Szeredi cs->pg = page; 726c55a01d3SMiklos Szeredi cs->offset = 0; 727c3021629SMiklos Szeredi cs->len = PAGE_SIZE; 728c3021629SMiklos Szeredi cs->pipebufs++; 729c3021629SMiklos Szeredi cs->nr_segs++; 730c3021629SMiklos Szeredi } 731c3021629SMiklos Szeredi } else { 7326c09e94aSAl Viro size_t off; 7336c09e94aSAl Viro err = iov_iter_get_pages(cs->iter, &page, PAGE_SIZE, 1, &off); 734334f485dSMiklos Szeredi if (err < 0) 735334f485dSMiklos Szeredi return err; 7366c09e94aSAl Viro BUG_ON(!err); 7376c09e94aSAl Viro cs->len = err; 7386c09e94aSAl Viro cs->offset = off; 739c55a01d3SMiklos Szeredi cs->pg = page; 7406c09e94aSAl Viro iov_iter_advance(cs->iter, err); 741dd3bb14fSMiklos Szeredi } 742334f485dSMiklos Szeredi 743dc00809aSMiklos Szeredi return lock_request(cs->req); 744334f485dSMiklos Szeredi } 745334f485dSMiklos Szeredi 746334f485dSMiklos Szeredi /* Do as much copy to/from userspace buffer as we can */ 7478bfc016dSMiklos Szeredi static int fuse_copy_do(struct fuse_copy_state *cs, void **val, unsigned *size) 748334f485dSMiklos Szeredi { 749334f485dSMiklos Szeredi unsigned ncpy = min(*size, cs->len); 750334f485dSMiklos Szeredi if (val) { 7515fe0fc9fSPeng Hao void *pgaddr = kmap_local_page(cs->pg); 752c55a01d3SMiklos Szeredi void *buf = pgaddr + cs->offset; 753c55a01d3SMiklos Szeredi 754334f485dSMiklos Szeredi if (cs->write) 755c55a01d3SMiklos Szeredi memcpy(buf, *val, ncpy); 756334f485dSMiklos Szeredi else 757c55a01d3SMiklos Szeredi memcpy(*val, buf, ncpy); 758c55a01d3SMiklos Szeredi 7595fe0fc9fSPeng Hao kunmap_local(pgaddr); 760334f485dSMiklos Szeredi *val += ncpy; 761334f485dSMiklos Szeredi } 762334f485dSMiklos Szeredi *size -= ncpy; 763334f485dSMiklos Szeredi cs->len -= ncpy; 764c55a01d3SMiklos Szeredi cs->offset += ncpy; 765334f485dSMiklos Szeredi return ncpy; 766334f485dSMiklos Szeredi } 767334f485dSMiklos Szeredi 768ce534fb0SMiklos Szeredi static int fuse_check_page(struct page *page) 769ce534fb0SMiklos Szeredi { 770ce534fb0SMiklos Szeredi if (page_mapcount(page) || 771ce534fb0SMiklos Szeredi page->mapping != NULL || 772ce534fb0SMiklos Szeredi (page->flags & PAGE_FLAGS_CHECK_AT_PREP & 773ce534fb0SMiklos Szeredi ~(1 << PG_locked | 774ce534fb0SMiklos Szeredi 1 << PG_referenced | 775ce534fb0SMiklos Szeredi 1 << PG_uptodate | 776ce534fb0SMiklos Szeredi 1 << PG_lru | 777ce534fb0SMiklos Szeredi 1 << PG_active | 778b89ecd60SMiklos Szeredi 1 << PG_workingset | 779a5005c3cSMiklos Szeredi 1 << PG_reclaim | 780a5005c3cSMiklos Szeredi 1 << PG_waiters))) { 78100589386SMiklos Szeredi dump_page(page, "fuse: trying to steal weird page"); 782ce534fb0SMiklos Szeredi return 1; 783ce534fb0SMiklos Szeredi } 784ce534fb0SMiklos Szeredi return 0; 785ce534fb0SMiklos Szeredi } 786ce534fb0SMiklos Szeredi 787ce534fb0SMiklos Szeredi static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep) 788ce534fb0SMiklos Szeredi { 789ce534fb0SMiklos Szeredi int err; 790ce534fb0SMiklos Szeredi struct page *oldpage = *pagep; 791ce534fb0SMiklos Szeredi struct page *newpage; 792ce534fb0SMiklos Szeredi struct pipe_buffer *buf = cs->pipebufs; 793ce534fb0SMiklos Szeredi 794d78092e4SMiklos Szeredi get_page(oldpage); 795dc00809aSMiklos Szeredi err = unlock_request(cs->req); 7960d8e84b0SMiklos Szeredi if (err) 797d78092e4SMiklos Szeredi goto out_put_old; 7980d8e84b0SMiklos Szeredi 799ce534fb0SMiklos Szeredi fuse_copy_finish(cs); 800ce534fb0SMiklos Szeredi 801fba597dbSMiklos Szeredi err = pipe_buf_confirm(cs->pipe, buf); 802ce534fb0SMiklos Szeredi if (err) 803d78092e4SMiklos Szeredi goto out_put_old; 804ce534fb0SMiklos Szeredi 805ce534fb0SMiklos Szeredi BUG_ON(!cs->nr_segs); 806ce534fb0SMiklos Szeredi cs->currbuf = buf; 807ce534fb0SMiklos Szeredi cs->len = buf->len; 808ce534fb0SMiklos Szeredi cs->pipebufs++; 809ce534fb0SMiklos Szeredi cs->nr_segs--; 810ce534fb0SMiklos Szeredi 811ce534fb0SMiklos Szeredi if (cs->len != PAGE_SIZE) 812ce534fb0SMiklos Szeredi goto out_fallback; 813ce534fb0SMiklos Szeredi 814c928f642SChristoph Hellwig if (!pipe_buf_try_steal(cs->pipe, buf)) 815ce534fb0SMiklos Szeredi goto out_fallback; 816ce534fb0SMiklos Szeredi 817ce534fb0SMiklos Szeredi newpage = buf->page; 818ce534fb0SMiklos Szeredi 819aa991b3bSMiklos Szeredi if (!PageUptodate(newpage)) 820aa991b3bSMiklos Szeredi SetPageUptodate(newpage); 821ce534fb0SMiklos Szeredi 822ce534fb0SMiklos Szeredi ClearPageMappedToDisk(newpage); 823ce534fb0SMiklos Szeredi 824ce534fb0SMiklos Szeredi if (fuse_check_page(newpage) != 0) 825ce534fb0SMiklos Szeredi goto out_fallback_unlock; 826ce534fb0SMiklos Szeredi 827ce534fb0SMiklos Szeredi /* 828ce534fb0SMiklos Szeredi * This is a new and locked page, it shouldn't be mapped or 829ce534fb0SMiklos Szeredi * have any special flags on it 830ce534fb0SMiklos Szeredi */ 831ce534fb0SMiklos Szeredi if (WARN_ON(page_mapped(oldpage))) 832ce534fb0SMiklos Szeredi goto out_fallback_unlock; 833ce534fb0SMiklos Szeredi if (WARN_ON(page_has_private(oldpage))) 834ce534fb0SMiklos Szeredi goto out_fallback_unlock; 835ce534fb0SMiklos Szeredi if (WARN_ON(PageDirty(oldpage) || PageWriteback(oldpage))) 836ce534fb0SMiklos Szeredi goto out_fallback_unlock; 837ce534fb0SMiklos Szeredi if (WARN_ON(PageMlocked(oldpage))) 838ce534fb0SMiklos Szeredi goto out_fallback_unlock; 839ce534fb0SMiklos Szeredi 8401f7ef657SBaolin Wang replace_page_cache_page(oldpage, newpage); 841ef6a3c63SMiklos Szeredi 84247344172SMiklos Szeredi get_page(newpage); 84347344172SMiklos Szeredi 84447344172SMiklos Szeredi if (!(buf->flags & PIPE_BUF_FLAG_LRU)) 84547344172SMiklos Szeredi lru_cache_add(newpage); 84647344172SMiklos Szeredi 847712a9510SMiklos Szeredi /* 848712a9510SMiklos Szeredi * Release while we have extra ref on stolen page. Otherwise 849712a9510SMiklos Szeredi * anon_pipe_buf_release() might think the page can be reused. 850712a9510SMiklos Szeredi */ 851712a9510SMiklos Szeredi pipe_buf_release(cs->pipe, buf); 852712a9510SMiklos Szeredi 853ce534fb0SMiklos Szeredi err = 0; 854dc00809aSMiklos Szeredi spin_lock(&cs->req->waitq.lock); 855825d6d33SMiklos Szeredi if (test_bit(FR_ABORTED, &cs->req->flags)) 856ce534fb0SMiklos Szeredi err = -ENOENT; 857ce534fb0SMiklos Szeredi else 858ce534fb0SMiklos Szeredi *pagep = newpage; 859dc00809aSMiklos Szeredi spin_unlock(&cs->req->waitq.lock); 860ce534fb0SMiklos Szeredi 861ce534fb0SMiklos Szeredi if (err) { 862ce534fb0SMiklos Szeredi unlock_page(newpage); 86309cbfeafSKirill A. Shutemov put_page(newpage); 864d78092e4SMiklos Szeredi goto out_put_old; 865ce534fb0SMiklos Szeredi } 866ce534fb0SMiklos Szeredi 867ce534fb0SMiklos Szeredi unlock_page(oldpage); 868d78092e4SMiklos Szeredi /* Drop ref for ap->pages[] array */ 86909cbfeafSKirill A. Shutemov put_page(oldpage); 870ce534fb0SMiklos Szeredi cs->len = 0; 871ce534fb0SMiklos Szeredi 872d78092e4SMiklos Szeredi err = 0; 873d78092e4SMiklos Szeredi out_put_old: 874d78092e4SMiklos Szeredi /* Drop ref obtained in this function */ 875d78092e4SMiklos Szeredi put_page(oldpage); 876d78092e4SMiklos Szeredi return err; 877ce534fb0SMiklos Szeredi 878ce534fb0SMiklos Szeredi out_fallback_unlock: 879ce534fb0SMiklos Szeredi unlock_page(newpage); 880ce534fb0SMiklos Szeredi out_fallback: 881c55a01d3SMiklos Szeredi cs->pg = buf->page; 882c55a01d3SMiklos Szeredi cs->offset = buf->offset; 883ce534fb0SMiklos Szeredi 884dc00809aSMiklos Szeredi err = lock_request(cs->req); 885d78092e4SMiklos Szeredi if (!err) 886d78092e4SMiklos Szeredi err = 1; 887ce534fb0SMiklos Szeredi 888d78092e4SMiklos Szeredi goto out_put_old; 889ce534fb0SMiklos Szeredi } 890ce534fb0SMiklos Szeredi 891c3021629SMiklos Szeredi static int fuse_ref_page(struct fuse_copy_state *cs, struct page *page, 892c3021629SMiklos Szeredi unsigned offset, unsigned count) 893c3021629SMiklos Szeredi { 894c3021629SMiklos Szeredi struct pipe_buffer *buf; 8950d8e84b0SMiklos Szeredi int err; 896c3021629SMiklos Szeredi 8976718b6f8SDavid Howells if (cs->nr_segs >= cs->pipe->max_usage) 898c3021629SMiklos Szeredi return -EIO; 899c3021629SMiklos Szeredi 900d78092e4SMiklos Szeredi get_page(page); 901dc00809aSMiklos Szeredi err = unlock_request(cs->req); 902d78092e4SMiklos Szeredi if (err) { 903d78092e4SMiklos Szeredi put_page(page); 9040d8e84b0SMiklos Szeredi return err; 905d78092e4SMiklos Szeredi } 9060d8e84b0SMiklos Szeredi 907c3021629SMiklos Szeredi fuse_copy_finish(cs); 908c3021629SMiklos Szeredi 909c3021629SMiklos Szeredi buf = cs->pipebufs; 910c3021629SMiklos Szeredi buf->page = page; 911c3021629SMiklos Szeredi buf->offset = offset; 912c3021629SMiklos Szeredi buf->len = count; 913c3021629SMiklos Szeredi 914c3021629SMiklos Szeredi cs->pipebufs++; 915c3021629SMiklos Szeredi cs->nr_segs++; 916c3021629SMiklos Szeredi cs->len = 0; 917c3021629SMiklos Szeredi 918c3021629SMiklos Szeredi return 0; 919c3021629SMiklos Szeredi } 920c3021629SMiklos Szeredi 921334f485dSMiklos Szeredi /* 922334f485dSMiklos Szeredi * Copy a page in the request to/from the userspace buffer. Must be 923334f485dSMiklos Szeredi * done atomically 924334f485dSMiklos Szeredi */ 925ce534fb0SMiklos Szeredi static int fuse_copy_page(struct fuse_copy_state *cs, struct page **pagep, 926334f485dSMiklos Szeredi unsigned offset, unsigned count, int zeroing) 927334f485dSMiklos Szeredi { 928ce534fb0SMiklos Szeredi int err; 929ce534fb0SMiklos Szeredi struct page *page = *pagep; 930ce534fb0SMiklos Szeredi 931b6777c40SMiklos Szeredi if (page && zeroing && count < PAGE_SIZE) 932b6777c40SMiklos Szeredi clear_highpage(page); 933b6777c40SMiklos Szeredi 934334f485dSMiklos Szeredi while (count) { 935c3021629SMiklos Szeredi if (cs->write && cs->pipebufs && page) { 9360c4bcfdeSMiklos Szeredi /* 9370c4bcfdeSMiklos Szeredi * Can't control lifetime of pipe buffers, so always 9380c4bcfdeSMiklos Szeredi * copy user pages. 9390c4bcfdeSMiklos Szeredi */ 9400c4bcfdeSMiklos Szeredi if (cs->req->args->user_pages) { 9410c4bcfdeSMiklos Szeredi err = fuse_copy_fill(cs); 9420c4bcfdeSMiklos Szeredi if (err) 9430c4bcfdeSMiklos Szeredi return err; 9440c4bcfdeSMiklos Szeredi } else { 945c3021629SMiklos Szeredi return fuse_ref_page(cs, page, offset, count); 9460c4bcfdeSMiklos Szeredi } 947c3021629SMiklos Szeredi } else if (!cs->len) { 948ce534fb0SMiklos Szeredi if (cs->move_pages && page && 949ce534fb0SMiklos Szeredi offset == 0 && count == PAGE_SIZE) { 950ce534fb0SMiklos Szeredi err = fuse_try_move_page(cs, pagep); 951ce534fb0SMiklos Szeredi if (err <= 0) 952ce534fb0SMiklos Szeredi return err; 953ce534fb0SMiklos Szeredi } else { 954ce534fb0SMiklos Szeredi err = fuse_copy_fill(cs); 9551729a16cSMiklos Szeredi if (err) 956334f485dSMiklos Szeredi return err; 9571729a16cSMiklos Szeredi } 958ce534fb0SMiklos Szeredi } 959334f485dSMiklos Szeredi if (page) { 9605fe0fc9fSPeng Hao void *mapaddr = kmap_local_page(page); 961334f485dSMiklos Szeredi void *buf = mapaddr + offset; 962334f485dSMiklos Szeredi offset += fuse_copy_do(cs, &buf, &count); 9635fe0fc9fSPeng Hao kunmap_local(mapaddr); 964334f485dSMiklos Szeredi } else 965334f485dSMiklos Szeredi offset += fuse_copy_do(cs, NULL, &count); 966334f485dSMiklos Szeredi } 967334f485dSMiklos Szeredi if (page && !cs->write) 968334f485dSMiklos Szeredi flush_dcache_page(page); 969334f485dSMiklos Szeredi return 0; 970334f485dSMiklos Szeredi } 971334f485dSMiklos Szeredi 972334f485dSMiklos Szeredi /* Copy pages in the request to/from userspace buffer */ 973334f485dSMiklos Szeredi static int fuse_copy_pages(struct fuse_copy_state *cs, unsigned nbytes, 974334f485dSMiklos Szeredi int zeroing) 975334f485dSMiklos Szeredi { 976334f485dSMiklos Szeredi unsigned i; 977334f485dSMiklos Szeredi struct fuse_req *req = cs->req; 97805ea48ccSMiklos Szeredi struct fuse_args_pages *ap = container_of(req->args, typeof(*ap), args); 979334f485dSMiklos Szeredi 98005ea48ccSMiklos Szeredi 98105ea48ccSMiklos Szeredi for (i = 0; i < ap->num_pages && (nbytes || zeroing); i++) { 982ce534fb0SMiklos Szeredi int err; 98305ea48ccSMiklos Szeredi unsigned int offset = ap->descs[i].offset; 98405ea48ccSMiklos Szeredi unsigned int count = min(nbytes, ap->descs[i].length); 985ce534fb0SMiklos Szeredi 98605ea48ccSMiklos Szeredi err = fuse_copy_page(cs, &ap->pages[i], offset, count, zeroing); 987334f485dSMiklos Szeredi if (err) 988334f485dSMiklos Szeredi return err; 989334f485dSMiklos Szeredi 990334f485dSMiklos Szeredi nbytes -= count; 991334f485dSMiklos Szeredi } 992334f485dSMiklos Szeredi return 0; 993334f485dSMiklos Szeredi } 994334f485dSMiklos Szeredi 995334f485dSMiklos Szeredi /* Copy a single argument in the request to/from userspace buffer */ 996334f485dSMiklos Szeredi static int fuse_copy_one(struct fuse_copy_state *cs, void *val, unsigned size) 997334f485dSMiklos Szeredi { 998334f485dSMiklos Szeredi while (size) { 9991729a16cSMiklos Szeredi if (!cs->len) { 10001729a16cSMiklos Szeredi int err = fuse_copy_fill(cs); 10011729a16cSMiklos Szeredi if (err) 1002334f485dSMiklos Szeredi return err; 10031729a16cSMiklos Szeredi } 1004334f485dSMiklos Szeredi fuse_copy_do(cs, &val, &size); 1005334f485dSMiklos Szeredi } 1006334f485dSMiklos Szeredi return 0; 1007334f485dSMiklos Szeredi } 1008334f485dSMiklos Szeredi 1009334f485dSMiklos Szeredi /* Copy request arguments to/from userspace buffer */ 1010334f485dSMiklos Szeredi static int fuse_copy_args(struct fuse_copy_state *cs, unsigned numargs, 1011334f485dSMiklos Szeredi unsigned argpages, struct fuse_arg *args, 1012334f485dSMiklos Szeredi int zeroing) 1013334f485dSMiklos Szeredi { 1014334f485dSMiklos Szeredi int err = 0; 1015334f485dSMiklos Szeredi unsigned i; 1016334f485dSMiklos Szeredi 1017334f485dSMiklos Szeredi for (i = 0; !err && i < numargs; i++) { 1018334f485dSMiklos Szeredi struct fuse_arg *arg = &args[i]; 1019334f485dSMiklos Szeredi if (i == numargs - 1 && argpages) 1020334f485dSMiklos Szeredi err = fuse_copy_pages(cs, arg->size, zeroing); 1021334f485dSMiklos Szeredi else 1022334f485dSMiklos Szeredi err = fuse_copy_one(cs, arg->value, arg->size); 1023334f485dSMiklos Szeredi } 1024334f485dSMiklos Szeredi return err; 1025334f485dSMiklos Szeredi } 1026334f485dSMiklos Szeredi 1027f88996a9SMiklos Szeredi static int forget_pending(struct fuse_iqueue *fiq) 102807e77dcaSMiklos Szeredi { 1029f88996a9SMiklos Szeredi return fiq->forget_list_head.next != NULL; 103007e77dcaSMiklos Szeredi } 103107e77dcaSMiklos Szeredi 1032f88996a9SMiklos Szeredi static int request_pending(struct fuse_iqueue *fiq) 1033a4d27e75SMiklos Szeredi { 1034f88996a9SMiklos Szeredi return !list_empty(&fiq->pending) || !list_empty(&fiq->interrupts) || 1035f88996a9SMiklos Szeredi forget_pending(fiq); 1036a4d27e75SMiklos Szeredi } 1037a4d27e75SMiklos Szeredi 1038334f485dSMiklos Szeredi /* 1039a4d27e75SMiklos Szeredi * Transfer an interrupt request to userspace 1040a4d27e75SMiklos Szeredi * 1041a4d27e75SMiklos Szeredi * Unlike other requests this is assembled on demand, without a need 1042a4d27e75SMiklos Szeredi * to allocate a separate fuse_req structure. 1043a4d27e75SMiklos Szeredi * 104476e43c8cSEric Biggers * Called with fiq->lock held, releases it 1045a4d27e75SMiklos Szeredi */ 1046fd22d62eSMiklos Szeredi static int fuse_read_interrupt(struct fuse_iqueue *fiq, 1047fd22d62eSMiklos Szeredi struct fuse_copy_state *cs, 1048c3021629SMiklos Szeredi size_t nbytes, struct fuse_req *req) 104976e43c8cSEric Biggers __releases(fiq->lock) 1050a4d27e75SMiklos Szeredi { 1051a4d27e75SMiklos Szeredi struct fuse_in_header ih; 1052a4d27e75SMiklos Szeredi struct fuse_interrupt_in arg; 1053a4d27e75SMiklos Szeredi unsigned reqsize = sizeof(ih) + sizeof(arg); 1054a4d27e75SMiklos Szeredi int err; 1055a4d27e75SMiklos Szeredi 1056a4d27e75SMiklos Szeredi list_del_init(&req->intr_entry); 1057a4d27e75SMiklos Szeredi memset(&ih, 0, sizeof(ih)); 1058a4d27e75SMiklos Szeredi memset(&arg, 0, sizeof(arg)); 1059a4d27e75SMiklos Szeredi ih.len = reqsize; 1060a4d27e75SMiklos Szeredi ih.opcode = FUSE_INTERRUPT; 10613a5358d1SKirill Tkhai ih.unique = (req->in.h.unique | FUSE_INT_REQ_BIT); 1062a4d27e75SMiklos Szeredi arg.unique = req->in.h.unique; 1063a4d27e75SMiklos Szeredi 106476e43c8cSEric Biggers spin_unlock(&fiq->lock); 1065c3021629SMiklos Szeredi if (nbytes < reqsize) 1066a4d27e75SMiklos Szeredi return -EINVAL; 1067a4d27e75SMiklos Szeredi 1068c3021629SMiklos Szeredi err = fuse_copy_one(cs, &ih, sizeof(ih)); 1069a4d27e75SMiklos Szeredi if (!err) 1070c3021629SMiklos Szeredi err = fuse_copy_one(cs, &arg, sizeof(arg)); 1071c3021629SMiklos Szeredi fuse_copy_finish(cs); 1072a4d27e75SMiklos Szeredi 1073a4d27e75SMiklos Szeredi return err ? err : reqsize; 1074a4d27e75SMiklos Szeredi } 1075a4d27e75SMiklos Szeredi 10764388c5aaSVivek Goyal struct fuse_forget_link *fuse_dequeue_forget(struct fuse_iqueue *fiq, 10774388c5aaSVivek Goyal unsigned int max, 10784388c5aaSVivek Goyal unsigned int *countp) 107907e77dcaSMiklos Szeredi { 1080f88996a9SMiklos Szeredi struct fuse_forget_link *head = fiq->forget_list_head.next; 108102c048b9SMiklos Szeredi struct fuse_forget_link **newhead = &head; 108202c048b9SMiklos Szeredi unsigned count; 108307e77dcaSMiklos Szeredi 108402c048b9SMiklos Szeredi for (count = 0; *newhead != NULL && count < max; count++) 108502c048b9SMiklos Szeredi newhead = &(*newhead)->next; 108602c048b9SMiklos Szeredi 1087f88996a9SMiklos Szeredi fiq->forget_list_head.next = *newhead; 108802c048b9SMiklos Szeredi *newhead = NULL; 1089f88996a9SMiklos Szeredi if (fiq->forget_list_head.next == NULL) 1090f88996a9SMiklos Szeredi fiq->forget_list_tail = &fiq->forget_list_head; 109107e77dcaSMiklos Szeredi 109202c048b9SMiklos Szeredi if (countp != NULL) 109302c048b9SMiklos Szeredi *countp = count; 109402c048b9SMiklos Szeredi 109502c048b9SMiklos Szeredi return head; 109607e77dcaSMiklos Szeredi } 10974388c5aaSVivek Goyal EXPORT_SYMBOL(fuse_dequeue_forget); 109807e77dcaSMiklos Szeredi 1099fd22d62eSMiklos Szeredi static int fuse_read_single_forget(struct fuse_iqueue *fiq, 110007e77dcaSMiklos Szeredi struct fuse_copy_state *cs, 110107e77dcaSMiklos Szeredi size_t nbytes) 110276e43c8cSEric Biggers __releases(fiq->lock) 110307e77dcaSMiklos Szeredi { 110407e77dcaSMiklos Szeredi int err; 11054388c5aaSVivek Goyal struct fuse_forget_link *forget = fuse_dequeue_forget(fiq, 1, NULL); 110607e77dcaSMiklos Szeredi struct fuse_forget_in arg = { 110702c048b9SMiklos Szeredi .nlookup = forget->forget_one.nlookup, 110807e77dcaSMiklos Szeredi }; 110907e77dcaSMiklos Szeredi struct fuse_in_header ih = { 111007e77dcaSMiklos Szeredi .opcode = FUSE_FORGET, 111102c048b9SMiklos Szeredi .nodeid = forget->forget_one.nodeid, 1112f88996a9SMiklos Szeredi .unique = fuse_get_unique(fiq), 111307e77dcaSMiklos Szeredi .len = sizeof(ih) + sizeof(arg), 111407e77dcaSMiklos Szeredi }; 111507e77dcaSMiklos Szeredi 111676e43c8cSEric Biggers spin_unlock(&fiq->lock); 111707e77dcaSMiklos Szeredi kfree(forget); 111807e77dcaSMiklos Szeredi if (nbytes < ih.len) 111907e77dcaSMiklos Szeredi return -EINVAL; 112007e77dcaSMiklos Szeredi 112107e77dcaSMiklos Szeredi err = fuse_copy_one(cs, &ih, sizeof(ih)); 112207e77dcaSMiklos Szeredi if (!err) 112307e77dcaSMiklos Szeredi err = fuse_copy_one(cs, &arg, sizeof(arg)); 112407e77dcaSMiklos Szeredi fuse_copy_finish(cs); 112507e77dcaSMiklos Szeredi 112607e77dcaSMiklos Szeredi if (err) 112707e77dcaSMiklos Szeredi return err; 112807e77dcaSMiklos Szeredi 112907e77dcaSMiklos Szeredi return ih.len; 113007e77dcaSMiklos Szeredi } 113107e77dcaSMiklos Szeredi 1132fd22d62eSMiklos Szeredi static int fuse_read_batch_forget(struct fuse_iqueue *fiq, 113302c048b9SMiklos Szeredi struct fuse_copy_state *cs, size_t nbytes) 113476e43c8cSEric Biggers __releases(fiq->lock) 113502c048b9SMiklos Szeredi { 113602c048b9SMiklos Szeredi int err; 113702c048b9SMiklos Szeredi unsigned max_forgets; 113802c048b9SMiklos Szeredi unsigned count; 113902c048b9SMiklos Szeredi struct fuse_forget_link *head; 114002c048b9SMiklos Szeredi struct fuse_batch_forget_in arg = { .count = 0 }; 114102c048b9SMiklos Szeredi struct fuse_in_header ih = { 114202c048b9SMiklos Szeredi .opcode = FUSE_BATCH_FORGET, 1143f88996a9SMiklos Szeredi .unique = fuse_get_unique(fiq), 114402c048b9SMiklos Szeredi .len = sizeof(ih) + sizeof(arg), 114502c048b9SMiklos Szeredi }; 114602c048b9SMiklos Szeredi 114702c048b9SMiklos Szeredi if (nbytes < ih.len) { 114876e43c8cSEric Biggers spin_unlock(&fiq->lock); 114902c048b9SMiklos Szeredi return -EINVAL; 115002c048b9SMiklos Szeredi } 115102c048b9SMiklos Szeredi 115202c048b9SMiklos Szeredi max_forgets = (nbytes - ih.len) / sizeof(struct fuse_forget_one); 11534388c5aaSVivek Goyal head = fuse_dequeue_forget(fiq, max_forgets, &count); 115476e43c8cSEric Biggers spin_unlock(&fiq->lock); 115502c048b9SMiklos Szeredi 115602c048b9SMiklos Szeredi arg.count = count; 115702c048b9SMiklos Szeredi ih.len += count * sizeof(struct fuse_forget_one); 115802c048b9SMiklos Szeredi err = fuse_copy_one(cs, &ih, sizeof(ih)); 115902c048b9SMiklos Szeredi if (!err) 116002c048b9SMiklos Szeredi err = fuse_copy_one(cs, &arg, sizeof(arg)); 116102c048b9SMiklos Szeredi 116202c048b9SMiklos Szeredi while (head) { 116302c048b9SMiklos Szeredi struct fuse_forget_link *forget = head; 116402c048b9SMiklos Szeredi 116502c048b9SMiklos Szeredi if (!err) { 116602c048b9SMiklos Szeredi err = fuse_copy_one(cs, &forget->forget_one, 116702c048b9SMiklos Szeredi sizeof(forget->forget_one)); 116802c048b9SMiklos Szeredi } 116902c048b9SMiklos Szeredi head = forget->next; 117002c048b9SMiklos Szeredi kfree(forget); 117102c048b9SMiklos Szeredi } 117202c048b9SMiklos Szeredi 117302c048b9SMiklos Szeredi fuse_copy_finish(cs); 117402c048b9SMiklos Szeredi 117502c048b9SMiklos Szeredi if (err) 117602c048b9SMiklos Szeredi return err; 117702c048b9SMiklos Szeredi 117802c048b9SMiklos Szeredi return ih.len; 117902c048b9SMiklos Szeredi } 118002c048b9SMiklos Szeredi 1181fd22d62eSMiklos Szeredi static int fuse_read_forget(struct fuse_conn *fc, struct fuse_iqueue *fiq, 1182fd22d62eSMiklos Szeredi struct fuse_copy_state *cs, 118302c048b9SMiklos Szeredi size_t nbytes) 118476e43c8cSEric Biggers __releases(fiq->lock) 118502c048b9SMiklos Szeredi { 1186f88996a9SMiklos Szeredi if (fc->minor < 16 || fiq->forget_list_head.next->next == NULL) 1187fd22d62eSMiklos Szeredi return fuse_read_single_forget(fiq, cs, nbytes); 118802c048b9SMiklos Szeredi else 1189fd22d62eSMiklos Szeredi return fuse_read_batch_forget(fiq, cs, nbytes); 119002c048b9SMiklos Szeredi } 119102c048b9SMiklos Szeredi 1192a4d27e75SMiklos Szeredi /* 1193334f485dSMiklos Szeredi * Read a single request into the userspace filesystem's buffer. This 1194334f485dSMiklos Szeredi * function waits until a request is available, then removes it from 1195334f485dSMiklos Szeredi * the pending list and copies request data to userspace buffer. If 1196f9a2842eSMiklos Szeredi * no reply is needed (FORGET) or request has been aborted or there 1197f9a2842eSMiklos Szeredi * was an error during the copying then it's finished by calling 119804ec5af0SStefan Hajnoczi * fuse_request_end(). Otherwise add it to the processing list, and set 1199334f485dSMiklos Szeredi * the 'sent' flag. 1200334f485dSMiklos Szeredi */ 1201c3696046SMiklos Szeredi static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file, 1202c3021629SMiklos Szeredi struct fuse_copy_state *cs, size_t nbytes) 1203334f485dSMiklos Szeredi { 120482cbdcd3SMiklos Szeredi ssize_t err; 1205c3696046SMiklos Szeredi struct fuse_conn *fc = fud->fc; 1206f88996a9SMiklos Szeredi struct fuse_iqueue *fiq = &fc->iq; 1207c3696046SMiklos Szeredi struct fuse_pqueue *fpq = &fud->pq; 1208334f485dSMiklos Szeredi struct fuse_req *req; 1209d4993774SMiklos Szeredi struct fuse_args *args; 1210334f485dSMiklos Szeredi unsigned reqsize; 1211be2ff42cSKirill Tkhai unsigned int hash; 1212334f485dSMiklos Szeredi 12131fb027d7SKirill Smelkov /* 12141fb027d7SKirill Smelkov * Require sane minimum read buffer - that has capacity for fixed part 12151fb027d7SKirill Smelkov * of any request header + negotiated max_write room for data. 12161fb027d7SKirill Smelkov * 12171fb027d7SKirill Smelkov * Historically libfuse reserves 4K for fixed header room, but e.g. 12181fb027d7SKirill Smelkov * GlusterFS reserves only 80 bytes 12191fb027d7SKirill Smelkov * 12201fb027d7SKirill Smelkov * = `sizeof(fuse_in_header) + sizeof(fuse_write_in)` 12211fb027d7SKirill Smelkov * 12221fb027d7SKirill Smelkov * which is the absolute minimum any sane filesystem should be using 12231fb027d7SKirill Smelkov * for header room. 12241fb027d7SKirill Smelkov */ 12251fb027d7SKirill Smelkov if (nbytes < max_t(size_t, FUSE_MIN_READ_BUFFER, 12261fb027d7SKirill Smelkov sizeof(struct fuse_in_header) + 12271fb027d7SKirill Smelkov sizeof(struct fuse_write_in) + 12281fb027d7SKirill Smelkov fc->max_write)) 12291fb027d7SKirill Smelkov return -EINVAL; 12301fb027d7SKirill Smelkov 12311d3d752bSMiklos Szeredi restart: 123276e43c8cSEric Biggers for (;;) { 123376e43c8cSEric Biggers spin_lock(&fiq->lock); 123476e43c8cSEric Biggers if (!fiq->connected || request_pending(fiq)) 123576e43c8cSEric Biggers break; 123676e43c8cSEric Biggers spin_unlock(&fiq->lock); 1237e5ac1d1eSJeff Dike 123876e43c8cSEric Biggers if (file->f_flags & O_NONBLOCK) 123976e43c8cSEric Biggers return -EAGAIN; 124076e43c8cSEric Biggers err = wait_event_interruptible_exclusive(fiq->waitq, 12415250921bSMiklos Szeredi !fiq->connected || request_pending(fiq)); 12425250921bSMiklos Szeredi if (err) 124376e43c8cSEric Biggers return err; 124476e43c8cSEric Biggers } 12455250921bSMiklos Szeredi 12463b7008b2SSzymon Lukasz if (!fiq->connected) { 1247eb98e3bdSMiklos Szeredi err = fc->aborted ? -ECONNABORTED : -ENODEV; 1248334f485dSMiklos Szeredi goto err_unlock; 12493b7008b2SSzymon Lukasz } 1250334f485dSMiklos Szeredi 1251f88996a9SMiklos Szeredi if (!list_empty(&fiq->interrupts)) { 1252f88996a9SMiklos Szeredi req = list_entry(fiq->interrupts.next, struct fuse_req, 1253a4d27e75SMiklos Szeredi intr_entry); 1254fd22d62eSMiklos Szeredi return fuse_read_interrupt(fiq, cs, nbytes, req); 1255a4d27e75SMiklos Szeredi } 1256a4d27e75SMiklos Szeredi 1257f88996a9SMiklos Szeredi if (forget_pending(fiq)) { 1258f88996a9SMiklos Szeredi if (list_empty(&fiq->pending) || fiq->forget_batch-- > 0) 1259fd22d62eSMiklos Szeredi return fuse_read_forget(fc, fiq, cs, nbytes); 126007e77dcaSMiklos Szeredi 1261f88996a9SMiklos Szeredi if (fiq->forget_batch <= -8) 1262f88996a9SMiklos Szeredi fiq->forget_batch = 16; 126307e77dcaSMiklos Szeredi } 126407e77dcaSMiklos Szeredi 1265f88996a9SMiklos Szeredi req = list_entry(fiq->pending.next, struct fuse_req, list); 126633e14b4dSMiklos Szeredi clear_bit(FR_PENDING, &req->flags); 1267ef759258SMiklos Szeredi list_del_init(&req->list); 126876e43c8cSEric Biggers spin_unlock(&fiq->lock); 12694ce60812SMiklos Szeredi 1270d4993774SMiklos Szeredi args = req->args; 1271d4993774SMiklos Szeredi reqsize = req->in.h.len; 12725d6d3a30SMiklos Szeredi 12731d3d752bSMiklos Szeredi /* If request is too large, reply with an error and restart the read */ 1274c3021629SMiklos Szeredi if (nbytes < reqsize) { 12751d3d752bSMiklos Szeredi req->out.h.error = -EIO; 12761d3d752bSMiklos Szeredi /* SETXATTR is special, since it may contain too large data */ 1277d4993774SMiklos Szeredi if (args->opcode == FUSE_SETXATTR) 12781d3d752bSMiklos Szeredi req->out.h.error = -E2BIG; 12798f622e94SMax Reitz fuse_request_end(req); 12801d3d752bSMiklos Szeredi goto restart; 12811d3d752bSMiklos Szeredi } 128245a91cb1SMiklos Szeredi spin_lock(&fpq->lock); 128380ef0867SMiklos Szeredi /* 128480ef0867SMiklos Szeredi * Must not put request on fpq->io queue after having been shut down by 128580ef0867SMiklos Szeredi * fuse_abort_conn() 128680ef0867SMiklos Szeredi */ 128780ef0867SMiklos Szeredi if (!fpq->connected) { 128880ef0867SMiklos Szeredi req->out.h.error = err = -ECONNABORTED; 128980ef0867SMiklos Szeredi goto out_end; 129080ef0867SMiklos Szeredi 129180ef0867SMiklos Szeredi } 129282cbdcd3SMiklos Szeredi list_add(&req->list, &fpq->io); 129345a91cb1SMiklos Szeredi spin_unlock(&fpq->lock); 1294c3021629SMiklos Szeredi cs->req = req; 1295d4993774SMiklos Szeredi err = fuse_copy_one(cs, &req->in.h, sizeof(req->in.h)); 1296334f485dSMiklos Szeredi if (!err) 1297d4993774SMiklos Szeredi err = fuse_copy_args(cs, args->in_numargs, args->in_pages, 1298d4993774SMiklos Szeredi (struct fuse_arg *) args->in_args, 0); 1299c3021629SMiklos Szeredi fuse_copy_finish(cs); 130045a91cb1SMiklos Szeredi spin_lock(&fpq->lock); 1301825d6d33SMiklos Szeredi clear_bit(FR_LOCKED, &req->flags); 1302e96edd94SMiklos Szeredi if (!fpq->connected) { 1303eb98e3bdSMiklos Szeredi err = fc->aborted ? -ECONNABORTED : -ENODEV; 130482cbdcd3SMiklos Szeredi goto out_end; 1305c9c9d7dfSMiklos Szeredi } 1306334f485dSMiklos Szeredi if (err) { 1307334f485dSMiklos Szeredi req->out.h.error = -EIO; 130882cbdcd3SMiklos Szeredi goto out_end; 1309334f485dSMiklos Szeredi } 1310825d6d33SMiklos Szeredi if (!test_bit(FR_ISREPLY, &req->flags)) { 131182cbdcd3SMiklos Szeredi err = reqsize; 131282cbdcd3SMiklos Szeredi goto out_end; 131382cbdcd3SMiklos Szeredi } 1314be2ff42cSKirill Tkhai hash = fuse_req_hash(req->in.h.unique); 1315be2ff42cSKirill Tkhai list_move_tail(&req->list, &fpq->processing[hash]); 1316bc78abbdSKirill Tkhai __fuse_get_request(req); 13178f7bb368SMiklos Szeredi set_bit(FR_SENT, &req->flags); 13184c316f2fSMiklos Szeredi spin_unlock(&fpq->lock); 13198f7bb368SMiklos Szeredi /* matches barrier in request_wait_answer() */ 13208f7bb368SMiklos Szeredi smp_mb__after_atomic(); 1321825d6d33SMiklos Szeredi if (test_bit(FR_INTERRUPTED, &req->flags)) 13228f622e94SMax Reitz queue_interrupt(req); 13238f622e94SMax Reitz fuse_put_request(req); 132482cbdcd3SMiklos Szeredi 1325334f485dSMiklos Szeredi return reqsize; 1326334f485dSMiklos Szeredi 132782cbdcd3SMiklos Szeredi out_end: 132877cd9d48SMiklos Szeredi if (!test_bit(FR_PRIVATE, &req->flags)) 132982cbdcd3SMiklos Szeredi list_del_init(&req->list); 133045a91cb1SMiklos Szeredi spin_unlock(&fpq->lock); 13318f622e94SMax Reitz fuse_request_end(req); 133282cbdcd3SMiklos Szeredi return err; 133382cbdcd3SMiklos Szeredi 1334334f485dSMiklos Szeredi err_unlock: 133576e43c8cSEric Biggers spin_unlock(&fiq->lock); 1336334f485dSMiklos Szeredi return err; 1337334f485dSMiklos Szeredi } 1338334f485dSMiklos Szeredi 133994e4fe2cSTom Van Braeckel static int fuse_dev_open(struct inode *inode, struct file *file) 134094e4fe2cSTom Van Braeckel { 134194e4fe2cSTom Van Braeckel /* 134294e4fe2cSTom Van Braeckel * The fuse device's file's private_data is used to hold 134394e4fe2cSTom Van Braeckel * the fuse_conn(ection) when it is mounted, and is used to 134494e4fe2cSTom Van Braeckel * keep track of whether the file has been mounted already. 134594e4fe2cSTom Van Braeckel */ 134694e4fe2cSTom Van Braeckel file->private_data = NULL; 134794e4fe2cSTom Van Braeckel return 0; 134894e4fe2cSTom Van Braeckel } 134994e4fe2cSTom Van Braeckel 1350fbdbaccaSAl Viro static ssize_t fuse_dev_read(struct kiocb *iocb, struct iov_iter *to) 1351c3021629SMiklos Szeredi { 1352c3021629SMiklos Szeredi struct fuse_copy_state cs; 1353c3021629SMiklos Szeredi struct file *file = iocb->ki_filp; 1354cc080e9eSMiklos Szeredi struct fuse_dev *fud = fuse_get_dev(file); 1355cc080e9eSMiklos Szeredi 1356cc080e9eSMiklos Szeredi if (!fud) 1357c3021629SMiklos Szeredi return -EPERM; 1358c3021629SMiklos Szeredi 1359*fcb14cb1SAl Viro if (!user_backed_iter(to)) 1360fbdbaccaSAl Viro return -EINVAL; 1361c3021629SMiklos Szeredi 1362dc00809aSMiklos Szeredi fuse_copy_init(&cs, 1, to); 1363fbdbaccaSAl Viro 1364c3696046SMiklos Szeredi return fuse_dev_do_read(fud, file, &cs, iov_iter_count(to)); 1365c3021629SMiklos Szeredi } 1366c3021629SMiklos Szeredi 1367c3021629SMiklos Szeredi static ssize_t fuse_dev_splice_read(struct file *in, loff_t *ppos, 1368c3021629SMiklos Szeredi struct pipe_inode_info *pipe, 1369c3021629SMiklos Szeredi size_t len, unsigned int flags) 1370c3021629SMiklos Szeredi { 1371d82718e3SAl Viro int total, ret; 1372c3021629SMiklos Szeredi int page_nr = 0; 1373c3021629SMiklos Szeredi struct pipe_buffer *bufs; 1374c3021629SMiklos Szeredi struct fuse_copy_state cs; 1375cc080e9eSMiklos Szeredi struct fuse_dev *fud = fuse_get_dev(in); 1376cc080e9eSMiklos Szeredi 1377cc080e9eSMiklos Szeredi if (!fud) 1378c3021629SMiklos Szeredi return -EPERM; 1379c3021629SMiklos Szeredi 13806718b6f8SDavid Howells bufs = kvmalloc_array(pipe->max_usage, sizeof(struct pipe_buffer), 13816da2ec56SKees Cook GFP_KERNEL); 1382c3021629SMiklos Szeredi if (!bufs) 1383c3021629SMiklos Szeredi return -ENOMEM; 1384c3021629SMiklos Szeredi 1385dc00809aSMiklos Szeredi fuse_copy_init(&cs, 1, NULL); 1386c3021629SMiklos Szeredi cs.pipebufs = bufs; 1387c3021629SMiklos Szeredi cs.pipe = pipe; 1388c3696046SMiklos Szeredi ret = fuse_dev_do_read(fud, in, &cs, len); 1389c3021629SMiklos Szeredi if (ret < 0) 1390c3021629SMiklos Szeredi goto out; 1391c3021629SMiklos Szeredi 13926718b6f8SDavid Howells if (pipe_occupancy(pipe->head, pipe->tail) + cs.nr_segs > pipe->max_usage) { 1393c3021629SMiklos Szeredi ret = -EIO; 1394d82718e3SAl Viro goto out; 1395c3021629SMiklos Szeredi } 1396c3021629SMiklos Szeredi 1397d82718e3SAl Viro for (ret = total = 0; page_nr < cs.nr_segs; total += ret) { 139828a625cbSMiklos Szeredi /* 139928a625cbSMiklos Szeredi * Need to be careful about this. Having buf->ops in module 140028a625cbSMiklos Szeredi * code can Oops if the buffer persists after module unload. 140128a625cbSMiklos Szeredi */ 1402d82718e3SAl Viro bufs[page_nr].ops = &nosteal_pipe_buf_ops; 140384588a93SMiklos Szeredi bufs[page_nr].flags = 0; 1404d82718e3SAl Viro ret = add_to_pipe(pipe, &bufs[page_nr++]); 1405d82718e3SAl Viro if (unlikely(ret < 0)) 1406d82718e3SAl Viro break; 1407c3021629SMiklos Szeredi } 1408d82718e3SAl Viro if (total) 1409d82718e3SAl Viro ret = total; 1410c3021629SMiklos Szeredi out: 1411c3021629SMiklos Szeredi for (; page_nr < cs.nr_segs; page_nr++) 141209cbfeafSKirill A. Shutemov put_page(bufs[page_nr].page); 1413c3021629SMiklos Szeredi 1414d6d931adSAndrey Ryabinin kvfree(bufs); 1415c3021629SMiklos Szeredi return ret; 1416c3021629SMiklos Szeredi } 1417c3021629SMiklos Szeredi 141895668a69STejun Heo static int fuse_notify_poll(struct fuse_conn *fc, unsigned int size, 141995668a69STejun Heo struct fuse_copy_state *cs) 142095668a69STejun Heo { 142195668a69STejun Heo struct fuse_notify_poll_wakeup_out outarg; 1422f6d47a17SMiklos Szeredi int err = -EINVAL; 142395668a69STejun Heo 142495668a69STejun Heo if (size != sizeof(outarg)) 1425f6d47a17SMiklos Szeredi goto err; 142695668a69STejun Heo 142795668a69STejun Heo err = fuse_copy_one(cs, &outarg, sizeof(outarg)); 142895668a69STejun Heo if (err) 1429f6d47a17SMiklos Szeredi goto err; 143095668a69STejun Heo 1431f6d47a17SMiklos Szeredi fuse_copy_finish(cs); 143295668a69STejun Heo return fuse_notify_poll_wakeup(fc, &outarg); 1433f6d47a17SMiklos Szeredi 1434f6d47a17SMiklos Szeredi err: 1435f6d47a17SMiklos Szeredi fuse_copy_finish(cs); 1436f6d47a17SMiklos Szeredi return err; 143795668a69STejun Heo } 143895668a69STejun Heo 14393b463ae0SJohn Muir static int fuse_notify_inval_inode(struct fuse_conn *fc, unsigned int size, 14403b463ae0SJohn Muir struct fuse_copy_state *cs) 14413b463ae0SJohn Muir { 14423b463ae0SJohn Muir struct fuse_notify_inval_inode_out outarg; 14433b463ae0SJohn Muir int err = -EINVAL; 14443b463ae0SJohn Muir 14453b463ae0SJohn Muir if (size != sizeof(outarg)) 14463b463ae0SJohn Muir goto err; 14473b463ae0SJohn Muir 14483b463ae0SJohn Muir err = fuse_copy_one(cs, &outarg, sizeof(outarg)); 14493b463ae0SJohn Muir if (err) 14503b463ae0SJohn Muir goto err; 14513b463ae0SJohn Muir fuse_copy_finish(cs); 14523b463ae0SJohn Muir 14533b463ae0SJohn Muir down_read(&fc->killsb); 1454fcee216bSMax Reitz err = fuse_reverse_inval_inode(fc, outarg.ino, 14553b463ae0SJohn Muir outarg.off, outarg.len); 14563b463ae0SJohn Muir up_read(&fc->killsb); 14573b463ae0SJohn Muir return err; 14583b463ae0SJohn Muir 14593b463ae0SJohn Muir err: 14603b463ae0SJohn Muir fuse_copy_finish(cs); 14613b463ae0SJohn Muir return err; 14623b463ae0SJohn Muir } 14633b463ae0SJohn Muir 14643b463ae0SJohn Muir static int fuse_notify_inval_entry(struct fuse_conn *fc, unsigned int size, 14653b463ae0SJohn Muir struct fuse_copy_state *cs) 14663b463ae0SJohn Muir { 14673b463ae0SJohn Muir struct fuse_notify_inval_entry_out outarg; 1468b2d82ee3SFang Wenqi int err = -ENOMEM; 1469b2d82ee3SFang Wenqi char *buf; 14703b463ae0SJohn Muir struct qstr name; 14713b463ae0SJohn Muir 1472b2d82ee3SFang Wenqi buf = kzalloc(FUSE_NAME_MAX + 1, GFP_KERNEL); 1473b2d82ee3SFang Wenqi if (!buf) 1474b2d82ee3SFang Wenqi goto err; 1475b2d82ee3SFang Wenqi 1476b2d82ee3SFang Wenqi err = -EINVAL; 14773b463ae0SJohn Muir if (size < sizeof(outarg)) 14783b463ae0SJohn Muir goto err; 14793b463ae0SJohn Muir 14803b463ae0SJohn Muir err = fuse_copy_one(cs, &outarg, sizeof(outarg)); 14813b463ae0SJohn Muir if (err) 14823b463ae0SJohn Muir goto err; 14833b463ae0SJohn Muir 14843b463ae0SJohn Muir err = -ENAMETOOLONG; 14853b463ae0SJohn Muir if (outarg.namelen > FUSE_NAME_MAX) 14863b463ae0SJohn Muir goto err; 14873b463ae0SJohn Muir 1488c2183d1eSMiklos Szeredi err = -EINVAL; 1489c2183d1eSMiklos Szeredi if (size != sizeof(outarg) + outarg.namelen + 1) 1490c2183d1eSMiklos Szeredi goto err; 1491c2183d1eSMiklos Szeredi 14923b463ae0SJohn Muir name.name = buf; 14933b463ae0SJohn Muir name.len = outarg.namelen; 14943b463ae0SJohn Muir err = fuse_copy_one(cs, buf, outarg.namelen + 1); 14953b463ae0SJohn Muir if (err) 14963b463ae0SJohn Muir goto err; 14973b463ae0SJohn Muir fuse_copy_finish(cs); 14983b463ae0SJohn Muir buf[outarg.namelen] = 0; 14993b463ae0SJohn Muir 15003b463ae0SJohn Muir down_read(&fc->killsb); 1501fcee216bSMax Reitz err = fuse_reverse_inval_entry(fc, outarg.parent, 0, &name); 1502451d0f59SJohn Muir up_read(&fc->killsb); 1503451d0f59SJohn Muir kfree(buf); 1504451d0f59SJohn Muir return err; 1505451d0f59SJohn Muir 1506451d0f59SJohn Muir err: 1507451d0f59SJohn Muir kfree(buf); 1508451d0f59SJohn Muir fuse_copy_finish(cs); 1509451d0f59SJohn Muir return err; 1510451d0f59SJohn Muir } 1511451d0f59SJohn Muir 1512451d0f59SJohn Muir static int fuse_notify_delete(struct fuse_conn *fc, unsigned int size, 1513451d0f59SJohn Muir struct fuse_copy_state *cs) 1514451d0f59SJohn Muir { 1515451d0f59SJohn Muir struct fuse_notify_delete_out outarg; 1516451d0f59SJohn Muir int err = -ENOMEM; 1517451d0f59SJohn Muir char *buf; 1518451d0f59SJohn Muir struct qstr name; 1519451d0f59SJohn Muir 1520451d0f59SJohn Muir buf = kzalloc(FUSE_NAME_MAX + 1, GFP_KERNEL); 1521451d0f59SJohn Muir if (!buf) 1522451d0f59SJohn Muir goto err; 1523451d0f59SJohn Muir 1524451d0f59SJohn Muir err = -EINVAL; 1525451d0f59SJohn Muir if (size < sizeof(outarg)) 1526451d0f59SJohn Muir goto err; 1527451d0f59SJohn Muir 1528451d0f59SJohn Muir err = fuse_copy_one(cs, &outarg, sizeof(outarg)); 1529451d0f59SJohn Muir if (err) 1530451d0f59SJohn Muir goto err; 1531451d0f59SJohn Muir 1532451d0f59SJohn Muir err = -ENAMETOOLONG; 1533451d0f59SJohn Muir if (outarg.namelen > FUSE_NAME_MAX) 1534451d0f59SJohn Muir goto err; 1535451d0f59SJohn Muir 1536451d0f59SJohn Muir err = -EINVAL; 1537451d0f59SJohn Muir if (size != sizeof(outarg) + outarg.namelen + 1) 1538451d0f59SJohn Muir goto err; 1539451d0f59SJohn Muir 1540451d0f59SJohn Muir name.name = buf; 1541451d0f59SJohn Muir name.len = outarg.namelen; 1542451d0f59SJohn Muir err = fuse_copy_one(cs, buf, outarg.namelen + 1); 1543451d0f59SJohn Muir if (err) 1544451d0f59SJohn Muir goto err; 1545451d0f59SJohn Muir fuse_copy_finish(cs); 1546451d0f59SJohn Muir buf[outarg.namelen] = 0; 1547451d0f59SJohn Muir 1548451d0f59SJohn Muir down_read(&fc->killsb); 1549fcee216bSMax Reitz err = fuse_reverse_inval_entry(fc, outarg.parent, outarg.child, &name); 15503b463ae0SJohn Muir up_read(&fc->killsb); 1551b2d82ee3SFang Wenqi kfree(buf); 15523b463ae0SJohn Muir return err; 15533b463ae0SJohn Muir 15543b463ae0SJohn Muir err: 1555b2d82ee3SFang Wenqi kfree(buf); 15563b463ae0SJohn Muir fuse_copy_finish(cs); 15573b463ae0SJohn Muir return err; 15583b463ae0SJohn Muir } 15593b463ae0SJohn Muir 1560a1d75f25SMiklos Szeredi static int fuse_notify_store(struct fuse_conn *fc, unsigned int size, 1561a1d75f25SMiklos Szeredi struct fuse_copy_state *cs) 1562a1d75f25SMiklos Szeredi { 1563a1d75f25SMiklos Szeredi struct fuse_notify_store_out outarg; 1564a1d75f25SMiklos Szeredi struct inode *inode; 1565a1d75f25SMiklos Szeredi struct address_space *mapping; 1566a1d75f25SMiklos Szeredi u64 nodeid; 1567a1d75f25SMiklos Szeredi int err; 1568a1d75f25SMiklos Szeredi pgoff_t index; 1569a1d75f25SMiklos Szeredi unsigned int offset; 1570a1d75f25SMiklos Szeredi unsigned int num; 1571a1d75f25SMiklos Szeredi loff_t file_size; 1572a1d75f25SMiklos Szeredi loff_t end; 1573a1d75f25SMiklos Szeredi 1574a1d75f25SMiklos Szeredi err = -EINVAL; 1575a1d75f25SMiklos Szeredi if (size < sizeof(outarg)) 1576a1d75f25SMiklos Szeredi goto out_finish; 1577a1d75f25SMiklos Szeredi 1578a1d75f25SMiklos Szeredi err = fuse_copy_one(cs, &outarg, sizeof(outarg)); 1579a1d75f25SMiklos Szeredi if (err) 1580a1d75f25SMiklos Szeredi goto out_finish; 1581a1d75f25SMiklos Szeredi 1582a1d75f25SMiklos Szeredi err = -EINVAL; 1583a1d75f25SMiklos Szeredi if (size - sizeof(outarg) != outarg.size) 1584a1d75f25SMiklos Szeredi goto out_finish; 1585a1d75f25SMiklos Szeredi 1586a1d75f25SMiklos Szeredi nodeid = outarg.nodeid; 1587a1d75f25SMiklos Szeredi 1588a1d75f25SMiklos Szeredi down_read(&fc->killsb); 1589a1d75f25SMiklos Szeredi 1590a1d75f25SMiklos Szeredi err = -ENOENT; 1591fcee216bSMax Reitz inode = fuse_ilookup(fc, nodeid, NULL); 1592a1d75f25SMiklos Szeredi if (!inode) 1593a1d75f25SMiklos Szeredi goto out_up_killsb; 1594a1d75f25SMiklos Szeredi 1595a1d75f25SMiklos Szeredi mapping = inode->i_mapping; 159609cbfeafSKirill A. Shutemov index = outarg.offset >> PAGE_SHIFT; 159709cbfeafSKirill A. Shutemov offset = outarg.offset & ~PAGE_MASK; 1598a1d75f25SMiklos Szeredi file_size = i_size_read(inode); 1599a1d75f25SMiklos Szeredi end = outarg.offset + outarg.size; 1600a1d75f25SMiklos Szeredi if (end > file_size) { 1601a1d75f25SMiklos Szeredi file_size = end; 1602d347739aSMiklos Szeredi fuse_write_update_attr(inode, file_size, outarg.size); 1603a1d75f25SMiklos Szeredi } 1604a1d75f25SMiklos Szeredi 1605a1d75f25SMiklos Szeredi num = outarg.size; 1606a1d75f25SMiklos Szeredi while (num) { 1607a1d75f25SMiklos Szeredi struct page *page; 1608a1d75f25SMiklos Szeredi unsigned int this_num; 1609a1d75f25SMiklos Szeredi 1610a1d75f25SMiklos Szeredi err = -ENOMEM; 1611a1d75f25SMiklos Szeredi page = find_or_create_page(mapping, index, 1612a1d75f25SMiklos Szeredi mapping_gfp_mask(mapping)); 1613a1d75f25SMiklos Szeredi if (!page) 1614a1d75f25SMiklos Szeredi goto out_iput; 1615a1d75f25SMiklos Szeredi 161609cbfeafSKirill A. Shutemov this_num = min_t(unsigned, num, PAGE_SIZE - offset); 1617a1d75f25SMiklos Szeredi err = fuse_copy_page(cs, &page, offset, this_num, 0); 1618063ec1e5SMiklos Szeredi if (!err && offset == 0 && 161909cbfeafSKirill A. Shutemov (this_num == PAGE_SIZE || file_size == end)) 1620a1d75f25SMiklos Szeredi SetPageUptodate(page); 1621a1d75f25SMiklos Szeredi unlock_page(page); 162209cbfeafSKirill A. Shutemov put_page(page); 1623a1d75f25SMiklos Szeredi 1624a1d75f25SMiklos Szeredi if (err) 1625a1d75f25SMiklos Szeredi goto out_iput; 1626a1d75f25SMiklos Szeredi 1627a1d75f25SMiklos Szeredi num -= this_num; 1628a1d75f25SMiklos Szeredi offset = 0; 1629a1d75f25SMiklos Szeredi index++; 1630a1d75f25SMiklos Szeredi } 1631a1d75f25SMiklos Szeredi 1632a1d75f25SMiklos Szeredi err = 0; 1633a1d75f25SMiklos Szeredi 1634a1d75f25SMiklos Szeredi out_iput: 1635a1d75f25SMiklos Szeredi iput(inode); 1636a1d75f25SMiklos Szeredi out_up_killsb: 1637a1d75f25SMiklos Szeredi up_read(&fc->killsb); 1638a1d75f25SMiklos Szeredi out_finish: 1639a1d75f25SMiklos Szeredi fuse_copy_finish(cs); 1640a1d75f25SMiklos Szeredi return err; 1641a1d75f25SMiklos Szeredi } 1642a1d75f25SMiklos Szeredi 164375b399ddSMiklos Szeredi struct fuse_retrieve_args { 164475b399ddSMiklos Szeredi struct fuse_args_pages ap; 164575b399ddSMiklos Szeredi struct fuse_notify_retrieve_in inarg; 164675b399ddSMiklos Szeredi }; 164775b399ddSMiklos Szeredi 1648fcee216bSMax Reitz static void fuse_retrieve_end(struct fuse_mount *fm, struct fuse_args *args, 164975b399ddSMiklos Szeredi int error) 16502d45ba38SMiklos Szeredi { 165175b399ddSMiklos Szeredi struct fuse_retrieve_args *ra = 165275b399ddSMiklos Szeredi container_of(args, typeof(*ra), ap.args); 165375b399ddSMiklos Szeredi 165475b399ddSMiklos Szeredi release_pages(ra->ap.pages, ra->ap.num_pages); 165575b399ddSMiklos Szeredi kfree(ra); 16562d45ba38SMiklos Szeredi } 16572d45ba38SMiklos Szeredi 1658fcee216bSMax Reitz static int fuse_retrieve(struct fuse_mount *fm, struct inode *inode, 16592d45ba38SMiklos Szeredi struct fuse_notify_retrieve_out *outarg) 16602d45ba38SMiklos Szeredi { 16612d45ba38SMiklos Szeredi int err; 16622d45ba38SMiklos Szeredi struct address_space *mapping = inode->i_mapping; 16632d45ba38SMiklos Szeredi pgoff_t index; 16642d45ba38SMiklos Szeredi loff_t file_size; 16652d45ba38SMiklos Szeredi unsigned int num; 16662d45ba38SMiklos Szeredi unsigned int offset; 16670157443cSGeert Uytterhoeven size_t total_len = 0; 16685da784ccSConstantine Shulyupin unsigned int num_pages; 1669fcee216bSMax Reitz struct fuse_conn *fc = fm->fc; 167075b399ddSMiklos Szeredi struct fuse_retrieve_args *ra; 167175b399ddSMiklos Szeredi size_t args_size = sizeof(*ra); 167275b399ddSMiklos Szeredi struct fuse_args_pages *ap; 167375b399ddSMiklos Szeredi struct fuse_args *args; 16742d45ba38SMiklos Szeredi 167509cbfeafSKirill A. Shutemov offset = outarg->offset & ~PAGE_MASK; 16764d53dc99SMaxim Patlasov file_size = i_size_read(inode); 16774d53dc99SMaxim Patlasov 16787640682eSKirill Smelkov num = min(outarg->size, fc->max_write); 16794d53dc99SMaxim Patlasov if (outarg->offset > file_size) 16804d53dc99SMaxim Patlasov num = 0; 16814d53dc99SMaxim Patlasov else if (outarg->offset + num > file_size) 16824d53dc99SMaxim Patlasov num = file_size - outarg->offset; 16834d53dc99SMaxim Patlasov 16844d53dc99SMaxim Patlasov num_pages = (num + offset + PAGE_SIZE - 1) >> PAGE_SHIFT; 16855da784ccSConstantine Shulyupin num_pages = min(num_pages, fc->max_pages); 16864d53dc99SMaxim Patlasov 168775b399ddSMiklos Szeredi args_size += num_pages * (sizeof(ap->pages[0]) + sizeof(ap->descs[0])); 16882d45ba38SMiklos Szeredi 168975b399ddSMiklos Szeredi ra = kzalloc(args_size, GFP_KERNEL); 169075b399ddSMiklos Szeredi if (!ra) 169175b399ddSMiklos Szeredi return -ENOMEM; 169275b399ddSMiklos Szeredi 169375b399ddSMiklos Szeredi ap = &ra->ap; 169475b399ddSMiklos Szeredi ap->pages = (void *) (ra + 1); 169575b399ddSMiklos Szeredi ap->descs = (void *) (ap->pages + num_pages); 169675b399ddSMiklos Szeredi 169775b399ddSMiklos Szeredi args = &ap->args; 169875b399ddSMiklos Szeredi args->nodeid = outarg->nodeid; 169975b399ddSMiklos Szeredi args->opcode = FUSE_NOTIFY_REPLY; 170075b399ddSMiklos Szeredi args->in_numargs = 2; 170175b399ddSMiklos Szeredi args->in_pages = true; 170275b399ddSMiklos Szeredi args->end = fuse_retrieve_end; 17032d45ba38SMiklos Szeredi 170409cbfeafSKirill A. Shutemov index = outarg->offset >> PAGE_SHIFT; 17052d45ba38SMiklos Szeredi 170675b399ddSMiklos Szeredi while (num && ap->num_pages < num_pages) { 17072d45ba38SMiklos Szeredi struct page *page; 17082d45ba38SMiklos Szeredi unsigned int this_num; 17092d45ba38SMiklos Szeredi 17102d45ba38SMiklos Szeredi page = find_get_page(mapping, index); 17112d45ba38SMiklos Szeredi if (!page) 17122d45ba38SMiklos Szeredi break; 17132d45ba38SMiklos Szeredi 171409cbfeafSKirill A. Shutemov this_num = min_t(unsigned, num, PAGE_SIZE - offset); 171575b399ddSMiklos Szeredi ap->pages[ap->num_pages] = page; 171675b399ddSMiklos Szeredi ap->descs[ap->num_pages].offset = offset; 171775b399ddSMiklos Szeredi ap->descs[ap->num_pages].length = this_num; 171875b399ddSMiklos Szeredi ap->num_pages++; 17192d45ba38SMiklos Szeredi 1720c9e67d48SMiklos Szeredi offset = 0; 17212d45ba38SMiklos Szeredi num -= this_num; 17222d45ba38SMiklos Szeredi total_len += this_num; 172348706d0aSMiklos Szeredi index++; 17242d45ba38SMiklos Szeredi } 172575b399ddSMiklos Szeredi ra->inarg.offset = outarg->offset; 172675b399ddSMiklos Szeredi ra->inarg.size = total_len; 172775b399ddSMiklos Szeredi args->in_args[0].size = sizeof(ra->inarg); 172875b399ddSMiklos Szeredi args->in_args[0].value = &ra->inarg; 172975b399ddSMiklos Szeredi args->in_args[1].size = total_len; 17302d45ba38SMiklos Szeredi 1731fcee216bSMax Reitz err = fuse_simple_notify_reply(fm, args, outarg->notify_unique); 173275b399ddSMiklos Szeredi if (err) 1733fcee216bSMax Reitz fuse_retrieve_end(fm, args, err); 17342d45ba38SMiklos Szeredi 17352d45ba38SMiklos Szeredi return err; 17362d45ba38SMiklos Szeredi } 17372d45ba38SMiklos Szeredi 17382d45ba38SMiklos Szeredi static int fuse_notify_retrieve(struct fuse_conn *fc, unsigned int size, 17392d45ba38SMiklos Szeredi struct fuse_copy_state *cs) 17402d45ba38SMiklos Szeredi { 17412d45ba38SMiklos Szeredi struct fuse_notify_retrieve_out outarg; 1742fcee216bSMax Reitz struct fuse_mount *fm; 17432d45ba38SMiklos Szeredi struct inode *inode; 1744fcee216bSMax Reitz u64 nodeid; 17452d45ba38SMiklos Szeredi int err; 17462d45ba38SMiklos Szeredi 17472d45ba38SMiklos Szeredi err = -EINVAL; 17482d45ba38SMiklos Szeredi if (size != sizeof(outarg)) 17492d45ba38SMiklos Szeredi goto copy_finish; 17502d45ba38SMiklos Szeredi 17512d45ba38SMiklos Szeredi err = fuse_copy_one(cs, &outarg, sizeof(outarg)); 17522d45ba38SMiklos Szeredi if (err) 17532d45ba38SMiklos Szeredi goto copy_finish; 17542d45ba38SMiklos Szeredi 17552d45ba38SMiklos Szeredi fuse_copy_finish(cs); 17562d45ba38SMiklos Szeredi 17572d45ba38SMiklos Szeredi down_read(&fc->killsb); 17582d45ba38SMiklos Szeredi err = -ENOENT; 1759fcee216bSMax Reitz nodeid = outarg.nodeid; 17602d45ba38SMiklos Szeredi 1761fcee216bSMax Reitz inode = fuse_ilookup(fc, nodeid, &fm); 17622d45ba38SMiklos Szeredi if (inode) { 1763fcee216bSMax Reitz err = fuse_retrieve(fm, inode, &outarg); 17642d45ba38SMiklos Szeredi iput(inode); 17652d45ba38SMiklos Szeredi } 17662d45ba38SMiklos Szeredi up_read(&fc->killsb); 17672d45ba38SMiklos Szeredi 17682d45ba38SMiklos Szeredi return err; 17692d45ba38SMiklos Szeredi 17702d45ba38SMiklos Szeredi copy_finish: 17712d45ba38SMiklos Szeredi fuse_copy_finish(cs); 17722d45ba38SMiklos Szeredi return err; 17732d45ba38SMiklos Szeredi } 17742d45ba38SMiklos Szeredi 17758599396bSTejun Heo static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code, 17768599396bSTejun Heo unsigned int size, struct fuse_copy_state *cs) 17778599396bSTejun Heo { 17780d278362SMiklos Szeredi /* Don't try to move pages (yet) */ 17790d278362SMiklos Szeredi cs->move_pages = 0; 17800d278362SMiklos Szeredi 17818599396bSTejun Heo switch (code) { 178295668a69STejun Heo case FUSE_NOTIFY_POLL: 178395668a69STejun Heo return fuse_notify_poll(fc, size, cs); 178495668a69STejun Heo 17853b463ae0SJohn Muir case FUSE_NOTIFY_INVAL_INODE: 17863b463ae0SJohn Muir return fuse_notify_inval_inode(fc, size, cs); 17873b463ae0SJohn Muir 17883b463ae0SJohn Muir case FUSE_NOTIFY_INVAL_ENTRY: 17893b463ae0SJohn Muir return fuse_notify_inval_entry(fc, size, cs); 17903b463ae0SJohn Muir 1791a1d75f25SMiklos Szeredi case FUSE_NOTIFY_STORE: 1792a1d75f25SMiklos Szeredi return fuse_notify_store(fc, size, cs); 1793a1d75f25SMiklos Szeredi 17942d45ba38SMiklos Szeredi case FUSE_NOTIFY_RETRIEVE: 17952d45ba38SMiklos Szeredi return fuse_notify_retrieve(fc, size, cs); 17962d45ba38SMiklos Szeredi 1797451d0f59SJohn Muir case FUSE_NOTIFY_DELETE: 1798451d0f59SJohn Muir return fuse_notify_delete(fc, size, cs); 1799451d0f59SJohn Muir 18008599396bSTejun Heo default: 1801f6d47a17SMiklos Szeredi fuse_copy_finish(cs); 18028599396bSTejun Heo return -EINVAL; 18038599396bSTejun Heo } 18048599396bSTejun Heo } 18058599396bSTejun Heo 1806334f485dSMiklos Szeredi /* Look up request on processing list by unique ID */ 18073a2b5b9cSMiklos Szeredi static struct fuse_req *request_find(struct fuse_pqueue *fpq, u64 unique) 1808334f485dSMiklos Szeredi { 1809be2ff42cSKirill Tkhai unsigned int hash = fuse_req_hash(unique); 1810334f485dSMiklos Szeredi struct fuse_req *req; 181105726acaSDong Fang 1812be2ff42cSKirill Tkhai list_for_each_entry(req, &fpq->processing[hash], list) { 18133a5358d1SKirill Tkhai if (req->in.h.unique == unique) 1814334f485dSMiklos Szeredi return req; 1815334f485dSMiklos Szeredi } 1816334f485dSMiklos Szeredi return NULL; 1817334f485dSMiklos Szeredi } 1818334f485dSMiklos Szeredi 1819d4993774SMiklos Szeredi static int copy_out_args(struct fuse_copy_state *cs, struct fuse_args *args, 1820334f485dSMiklos Szeredi unsigned nbytes) 1821334f485dSMiklos Szeredi { 1822334f485dSMiklos Szeredi unsigned reqsize = sizeof(struct fuse_out_header); 1823334f485dSMiklos Szeredi 182414d46d7aSStefan Hajnoczi reqsize += fuse_len_args(args->out_numargs, args->out_args); 1825334f485dSMiklos Szeredi 1826d4993774SMiklos Szeredi if (reqsize < nbytes || (reqsize > nbytes && !args->out_argvar)) 1827334f485dSMiklos Szeredi return -EINVAL; 1828334f485dSMiklos Szeredi else if (reqsize > nbytes) { 1829d4993774SMiklos Szeredi struct fuse_arg *lastarg = &args->out_args[args->out_numargs-1]; 1830334f485dSMiklos Szeredi unsigned diffsize = reqsize - nbytes; 1831d4993774SMiklos Szeredi 1832334f485dSMiklos Szeredi if (diffsize > lastarg->size) 1833334f485dSMiklos Szeredi return -EINVAL; 1834334f485dSMiklos Szeredi lastarg->size -= diffsize; 1835334f485dSMiklos Szeredi } 1836d4993774SMiklos Szeredi return fuse_copy_args(cs, args->out_numargs, args->out_pages, 1837d4993774SMiklos Szeredi args->out_args, args->page_zeroing); 1838334f485dSMiklos Szeredi } 1839334f485dSMiklos Szeredi 1840334f485dSMiklos Szeredi /* 1841334f485dSMiklos Szeredi * Write a single reply to a request. First the header is copied from 1842334f485dSMiklos Szeredi * the write buffer. The request is then searched on the processing 1843334f485dSMiklos Szeredi * list by the unique ID found in the header. If found, then remove 1844334f485dSMiklos Szeredi * it from the list and copy the rest of the buffer to the request. 184504ec5af0SStefan Hajnoczi * The request is finished by calling fuse_request_end(). 1846334f485dSMiklos Szeredi */ 1847c3696046SMiklos Szeredi static ssize_t fuse_dev_do_write(struct fuse_dev *fud, 1848dd3bb14fSMiklos Szeredi struct fuse_copy_state *cs, size_t nbytes) 1849334f485dSMiklos Szeredi { 1850334f485dSMiklos Szeredi int err; 1851c3696046SMiklos Szeredi struct fuse_conn *fc = fud->fc; 1852c3696046SMiklos Szeredi struct fuse_pqueue *fpq = &fud->pq; 1853334f485dSMiklos Szeredi struct fuse_req *req; 1854334f485dSMiklos Szeredi struct fuse_out_header oh; 1855334f485dSMiklos Szeredi 18567407a10dSKirill Tkhai err = -EINVAL; 1857334f485dSMiklos Szeredi if (nbytes < sizeof(struct fuse_out_header)) 18587407a10dSKirill Tkhai goto out; 1859334f485dSMiklos Szeredi 1860dd3bb14fSMiklos Szeredi err = fuse_copy_one(cs, &oh, sizeof(oh)); 1861334f485dSMiklos Szeredi if (err) 18627407a10dSKirill Tkhai goto copy_finish; 18638599396bSTejun Heo 1864334f485dSMiklos Szeredi err = -EINVAL; 18658599396bSTejun Heo if (oh.len != nbytes) 18667407a10dSKirill Tkhai goto copy_finish; 18678599396bSTejun Heo 18688599396bSTejun Heo /* 18698599396bSTejun Heo * Zero oh.unique indicates unsolicited notification message 18708599396bSTejun Heo * and error contains notification code. 18718599396bSTejun Heo */ 18728599396bSTejun Heo if (!oh.unique) { 1873dd3bb14fSMiklos Szeredi err = fuse_notify(fc, oh.error, nbytes - sizeof(oh), cs); 18747407a10dSKirill Tkhai goto out; 18758599396bSTejun Heo } 18768599396bSTejun Heo 18778599396bSTejun Heo err = -EINVAL; 187849221cf8SMiklos Szeredi if (oh.error <= -512 || oh.error > 0) 18797407a10dSKirill Tkhai goto copy_finish; 1880334f485dSMiklos Szeredi 188145a91cb1SMiklos Szeredi spin_lock(&fpq->lock); 18827407a10dSKirill Tkhai req = NULL; 18837407a10dSKirill Tkhai if (fpq->connected) 18843a5358d1SKirill Tkhai req = request_find(fpq, oh.unique & ~FUSE_INT_REQ_BIT); 18857407a10dSKirill Tkhai 18867407a10dSKirill Tkhai err = -ENOENT; 18877407a10dSKirill Tkhai if (!req) { 18887407a10dSKirill Tkhai spin_unlock(&fpq->lock); 18897407a10dSKirill Tkhai goto copy_finish; 18907407a10dSKirill Tkhai } 1891334f485dSMiklos Szeredi 18923a5358d1SKirill Tkhai /* Is it an interrupt reply ID? */ 18933a5358d1SKirill Tkhai if (oh.unique & FUSE_INT_REQ_BIT) { 1894d2d2d4fbSKirill Tkhai __fuse_get_request(req); 189545a91cb1SMiklos Szeredi spin_unlock(&fpq->lock); 189645a91cb1SMiklos Szeredi 18977407a10dSKirill Tkhai err = 0; 18987407a10dSKirill Tkhai if (nbytes != sizeof(struct fuse_out_header)) 1899a4d27e75SMiklos Szeredi err = -EINVAL; 19007407a10dSKirill Tkhai else if (oh.error == -ENOSYS) 1901a4d27e75SMiklos Szeredi fc->no_interrupt = 1; 1902a4d27e75SMiklos Szeredi else if (oh.error == -EAGAIN) 19038f622e94SMax Reitz err = queue_interrupt(req); 19047407a10dSKirill Tkhai 19058f622e94SMax Reitz fuse_put_request(req); 1906a4d27e75SMiklos Szeredi 19077407a10dSKirill Tkhai goto copy_finish; 1908a4d27e75SMiklos Szeredi } 1909a4d27e75SMiklos Szeredi 191033e14b4dSMiklos Szeredi clear_bit(FR_SENT, &req->flags); 19113a2b5b9cSMiklos Szeredi list_move(&req->list, &fpq->io); 1912334f485dSMiklos Szeredi req->out.h = oh; 1913825d6d33SMiklos Szeredi set_bit(FR_LOCKED, &req->flags); 191445a91cb1SMiklos Szeredi spin_unlock(&fpq->lock); 1915dd3bb14fSMiklos Szeredi cs->req = req; 1916d4993774SMiklos Szeredi if (!req->args->page_replace) 1917ce534fb0SMiklos Szeredi cs->move_pages = 0; 1918334f485dSMiklos Szeredi 1919d4993774SMiklos Szeredi if (oh.error) 1920d4993774SMiklos Szeredi err = nbytes != sizeof(oh) ? -EINVAL : 0; 1921d4993774SMiklos Szeredi else 1922d4993774SMiklos Szeredi err = copy_out_args(cs, req->args, nbytes); 1923dd3bb14fSMiklos Szeredi fuse_copy_finish(cs); 1924334f485dSMiklos Szeredi 192545a91cb1SMiklos Szeredi spin_lock(&fpq->lock); 1926825d6d33SMiklos Szeredi clear_bit(FR_LOCKED, &req->flags); 1927e96edd94SMiklos Szeredi if (!fpq->connected) 1928334f485dSMiklos Szeredi err = -ENOENT; 19290d8e84b0SMiklos Szeredi else if (err) 1930334f485dSMiklos Szeredi req->out.h.error = -EIO; 193177cd9d48SMiklos Szeredi if (!test_bit(FR_PRIVATE, &req->flags)) 1932f377cb79SMiklos Szeredi list_del_init(&req->list); 193345a91cb1SMiklos Szeredi spin_unlock(&fpq->lock); 193446c34a34SMiklos Szeredi 19358f622e94SMax Reitz fuse_request_end(req); 19367407a10dSKirill Tkhai out: 1937334f485dSMiklos Szeredi return err ? err : nbytes; 1938334f485dSMiklos Szeredi 19397407a10dSKirill Tkhai copy_finish: 1940dd3bb14fSMiklos Szeredi fuse_copy_finish(cs); 19417407a10dSKirill Tkhai goto out; 1942334f485dSMiklos Szeredi } 1943334f485dSMiklos Szeredi 1944fbdbaccaSAl Viro static ssize_t fuse_dev_write(struct kiocb *iocb, struct iov_iter *from) 1945dd3bb14fSMiklos Szeredi { 1946dd3bb14fSMiklos Szeredi struct fuse_copy_state cs; 1947cc080e9eSMiklos Szeredi struct fuse_dev *fud = fuse_get_dev(iocb->ki_filp); 1948cc080e9eSMiklos Szeredi 1949cc080e9eSMiklos Szeredi if (!fud) 1950dd3bb14fSMiklos Szeredi return -EPERM; 1951dd3bb14fSMiklos Szeredi 1952*fcb14cb1SAl Viro if (!user_backed_iter(from)) 1953fbdbaccaSAl Viro return -EINVAL; 1954dd3bb14fSMiklos Szeredi 1955dc00809aSMiklos Szeredi fuse_copy_init(&cs, 0, from); 1956fbdbaccaSAl Viro 1957c3696046SMiklos Szeredi return fuse_dev_do_write(fud, &cs, iov_iter_count(from)); 1958dd3bb14fSMiklos Szeredi } 1959dd3bb14fSMiklos Szeredi 1960dd3bb14fSMiklos Szeredi static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, 1961dd3bb14fSMiklos Szeredi struct file *out, loff_t *ppos, 1962dd3bb14fSMiklos Szeredi size_t len, unsigned int flags) 1963dd3bb14fSMiklos Szeredi { 19648cefc107SDavid Howells unsigned int head, tail, mask, count; 1965dd3bb14fSMiklos Szeredi unsigned nbuf; 1966dd3bb14fSMiklos Szeredi unsigned idx; 1967dd3bb14fSMiklos Szeredi struct pipe_buffer *bufs; 1968dd3bb14fSMiklos Szeredi struct fuse_copy_state cs; 1969cc080e9eSMiklos Szeredi struct fuse_dev *fud; 1970dd3bb14fSMiklos Szeredi size_t rem; 1971dd3bb14fSMiklos Szeredi ssize_t ret; 1972dd3bb14fSMiklos Szeredi 1973cc080e9eSMiklos Szeredi fud = fuse_get_dev(out); 1974cc080e9eSMiklos Szeredi if (!fud) 1975dd3bb14fSMiklos Szeredi return -EPERM; 1976dd3bb14fSMiklos Szeredi 1977a2477b0eSAndrey Ryabinin pipe_lock(pipe); 1978a2477b0eSAndrey Ryabinin 19798cefc107SDavid Howells head = pipe->head; 19808cefc107SDavid Howells tail = pipe->tail; 19818cefc107SDavid Howells mask = pipe->ring_size - 1; 19828cefc107SDavid Howells count = head - tail; 19838cefc107SDavid Howells 19848cefc107SDavid Howells bufs = kvmalloc_array(count, sizeof(struct pipe_buffer), GFP_KERNEL); 1985a2477b0eSAndrey Ryabinin if (!bufs) { 1986a2477b0eSAndrey Ryabinin pipe_unlock(pipe); 1987dd3bb14fSMiklos Szeredi return -ENOMEM; 1988a2477b0eSAndrey Ryabinin } 1989dd3bb14fSMiklos Szeredi 1990dd3bb14fSMiklos Szeredi nbuf = 0; 1991dd3bb14fSMiklos Szeredi rem = 0; 199276f6777cSDavid Howells for (idx = tail; idx != head && rem < len; idx++) 19938cefc107SDavid Howells rem += pipe->bufs[idx & mask].len; 1994dd3bb14fSMiklos Szeredi 1995dd3bb14fSMiklos Szeredi ret = -EINVAL; 199615fab63eSMatthew Wilcox if (rem < len) 199715fab63eSMatthew Wilcox goto out_free; 1998dd3bb14fSMiklos Szeredi 1999dd3bb14fSMiklos Szeredi rem = len; 2000dd3bb14fSMiklos Szeredi while (rem) { 2001dd3bb14fSMiklos Szeredi struct pipe_buffer *ibuf; 2002dd3bb14fSMiklos Szeredi struct pipe_buffer *obuf; 2003dd3bb14fSMiklos Szeredi 20040e9fb6f1SVasily Averin if (WARN_ON(nbuf >= count || tail == head)) 20050e9fb6f1SVasily Averin goto out_free; 20060e9fb6f1SVasily Averin 20078cefc107SDavid Howells ibuf = &pipe->bufs[tail & mask]; 2008dd3bb14fSMiklos Szeredi obuf = &bufs[nbuf]; 2009dd3bb14fSMiklos Szeredi 2010dd3bb14fSMiklos Szeredi if (rem >= ibuf->len) { 2011dd3bb14fSMiklos Szeredi *obuf = *ibuf; 2012dd3bb14fSMiklos Szeredi ibuf->ops = NULL; 20138cefc107SDavid Howells tail++; 20148cefc107SDavid Howells pipe->tail = tail; 2015dd3bb14fSMiklos Szeredi } else { 201615fab63eSMatthew Wilcox if (!pipe_buf_get(pipe, ibuf)) 201715fab63eSMatthew Wilcox goto out_free; 201815fab63eSMatthew Wilcox 2019dd3bb14fSMiklos Szeredi *obuf = *ibuf; 2020dd3bb14fSMiklos Szeredi obuf->flags &= ~PIPE_BUF_FLAG_GIFT; 2021dd3bb14fSMiklos Szeredi obuf->len = rem; 2022dd3bb14fSMiklos Szeredi ibuf->offset += obuf->len; 2023dd3bb14fSMiklos Szeredi ibuf->len -= obuf->len; 2024dd3bb14fSMiklos Szeredi } 2025dd3bb14fSMiklos Szeredi nbuf++; 2026dd3bb14fSMiklos Szeredi rem -= obuf->len; 2027dd3bb14fSMiklos Szeredi } 2028dd3bb14fSMiklos Szeredi pipe_unlock(pipe); 2029dd3bb14fSMiklos Szeredi 2030dc00809aSMiklos Szeredi fuse_copy_init(&cs, 0, NULL); 2031dd3bb14fSMiklos Szeredi cs.pipebufs = bufs; 20326c09e94aSAl Viro cs.nr_segs = nbuf; 2033dd3bb14fSMiklos Szeredi cs.pipe = pipe; 2034dd3bb14fSMiklos Szeredi 2035ce534fb0SMiklos Szeredi if (flags & SPLICE_F_MOVE) 2036ce534fb0SMiklos Szeredi cs.move_pages = 1; 2037ce534fb0SMiklos Szeredi 2038c3696046SMiklos Szeredi ret = fuse_dev_do_write(fud, &cs, len); 2039dd3bb14fSMiklos Szeredi 20409509941eSJann Horn pipe_lock(pipe); 204115fab63eSMatthew Wilcox out_free: 2042712a9510SMiklos Szeredi for (idx = 0; idx < nbuf; idx++) { 2043712a9510SMiklos Szeredi struct pipe_buffer *buf = &bufs[idx]; 2044712a9510SMiklos Szeredi 2045712a9510SMiklos Szeredi if (buf->ops) 2046712a9510SMiklos Szeredi pipe_buf_release(pipe, buf); 2047712a9510SMiklos Szeredi } 20489509941eSJann Horn pipe_unlock(pipe); 2049a779638cSMiklos Szeredi 2050d6d931adSAndrey Ryabinin kvfree(bufs); 2051dd3bb14fSMiklos Szeredi return ret; 2052dd3bb14fSMiklos Szeredi } 2053dd3bb14fSMiklos Szeredi 2054076ccb76SAl Viro static __poll_t fuse_dev_poll(struct file *file, poll_table *wait) 2055334f485dSMiklos Szeredi { 2056a9a08845SLinus Torvalds __poll_t mask = EPOLLOUT | EPOLLWRNORM; 2057f88996a9SMiklos Szeredi struct fuse_iqueue *fiq; 2058cc080e9eSMiklos Szeredi struct fuse_dev *fud = fuse_get_dev(file); 2059cc080e9eSMiklos Szeredi 2060cc080e9eSMiklos Szeredi if (!fud) 2061a9a08845SLinus Torvalds return EPOLLERR; 2062334f485dSMiklos Szeredi 2063cc080e9eSMiklos Szeredi fiq = &fud->fc->iq; 2064f88996a9SMiklos Szeredi poll_wait(file, &fiq->waitq, wait); 2065334f485dSMiklos Szeredi 206676e43c8cSEric Biggers spin_lock(&fiq->lock); 2067e16714d8SMiklos Szeredi if (!fiq->connected) 2068a9a08845SLinus Torvalds mask = EPOLLERR; 2069f88996a9SMiklos Szeredi else if (request_pending(fiq)) 2070a9a08845SLinus Torvalds mask |= EPOLLIN | EPOLLRDNORM; 207176e43c8cSEric Biggers spin_unlock(&fiq->lock); 2072334f485dSMiklos Szeredi 2073334f485dSMiklos Szeredi return mask; 2074334f485dSMiklos Szeredi } 2075334f485dSMiklos Szeredi 207634061750SKirill Tkhai /* Abort all requests on the given list (pending or processing) */ 20778f622e94SMax Reitz static void end_requests(struct list_head *head) 2078334f485dSMiklos Szeredi { 2079334f485dSMiklos Szeredi while (!list_empty(head)) { 2080334f485dSMiklos Szeredi struct fuse_req *req; 2081334f485dSMiklos Szeredi req = list_entry(head->next, struct fuse_req, list); 2082334f485dSMiklos Szeredi req->out.h.error = -ECONNABORTED; 208333e14b4dSMiklos Szeredi clear_bit(FR_SENT, &req->flags); 2084f377cb79SMiklos Szeredi list_del_init(&req->list); 20858f622e94SMax Reitz fuse_request_end(req); 2086334f485dSMiklos Szeredi } 2087334f485dSMiklos Szeredi } 2088334f485dSMiklos Szeredi 2089357ccf2bSBryan Green static void end_polls(struct fuse_conn *fc) 2090357ccf2bSBryan Green { 2091357ccf2bSBryan Green struct rb_node *p; 2092357ccf2bSBryan Green 2093357ccf2bSBryan Green p = rb_first(&fc->polled_files); 2094357ccf2bSBryan Green 2095357ccf2bSBryan Green while (p) { 2096357ccf2bSBryan Green struct fuse_file *ff; 2097357ccf2bSBryan Green ff = rb_entry(p, struct fuse_file, polled_node); 2098357ccf2bSBryan Green wake_up_interruptible_all(&ff->poll_wait); 2099357ccf2bSBryan Green 2100357ccf2bSBryan Green p = rb_next(p); 2101357ccf2bSBryan Green } 2102357ccf2bSBryan Green } 2103357ccf2bSBryan Green 210469a53bf2SMiklos Szeredi /* 210569a53bf2SMiklos Szeredi * Abort all requests. 210669a53bf2SMiklos Szeredi * 2107b716d425SMiklos Szeredi * Emergency exit in case of a malicious or accidental deadlock, or just a hung 2108b716d425SMiklos Szeredi * filesystem. 210969a53bf2SMiklos Szeredi * 2110b716d425SMiklos Szeredi * The same effect is usually achievable through killing the filesystem daemon 2111b716d425SMiklos Szeredi * and all users of the filesystem. The exception is the combination of an 2112b716d425SMiklos Szeredi * asynchronous request and the tricky deadlock (see 211372ef5e52SMauro Carvalho Chehab * Documentation/filesystems/fuse.rst). 211469a53bf2SMiklos Szeredi * 2115b716d425SMiklos Szeredi * Aborting requests under I/O goes as follows: 1: Separate out unlocked 2116b716d425SMiklos Szeredi * requests, they should be finished off immediately. Locked requests will be 2117b716d425SMiklos Szeredi * finished after unlock; see unlock_request(). 2: Finish off the unlocked 2118b716d425SMiklos Szeredi * requests. It is possible that some request will finish before we can. This 2119b716d425SMiklos Szeredi * is OK, the request will in that case be removed from the list before we touch 2120b716d425SMiklos Szeredi * it. 212169a53bf2SMiklos Szeredi */ 2122eb98e3bdSMiklos Szeredi void fuse_abort_conn(struct fuse_conn *fc) 212369a53bf2SMiklos Szeredi { 2124f88996a9SMiklos Szeredi struct fuse_iqueue *fiq = &fc->iq; 2125f88996a9SMiklos Szeredi 2126d7133114SMiklos Szeredi spin_lock(&fc->lock); 212769a53bf2SMiklos Szeredi if (fc->connected) { 2128c3696046SMiklos Szeredi struct fuse_dev *fud; 2129b716d425SMiklos Szeredi struct fuse_req *req, *next; 213075f3ee4cSMiklos Szeredi LIST_HEAD(to_end); 2131be2ff42cSKirill Tkhai unsigned int i; 2132b716d425SMiklos Szeredi 213363825b4eSKirill Tkhai /* Background queuing checks fc->connected under bg_lock */ 213463825b4eSKirill Tkhai spin_lock(&fc->bg_lock); 213569a53bf2SMiklos Szeredi fc->connected = 0; 213663825b4eSKirill Tkhai spin_unlock(&fc->bg_lock); 213763825b4eSKirill Tkhai 21389759bd51SMiklos Szeredi fuse_set_initialized(fc); 2139c3696046SMiklos Szeredi list_for_each_entry(fud, &fc->devices, entry) { 2140c3696046SMiklos Szeredi struct fuse_pqueue *fpq = &fud->pq; 2141c3696046SMiklos Szeredi 214245a91cb1SMiklos Szeredi spin_lock(&fpq->lock); 2143e96edd94SMiklos Szeredi fpq->connected = 0; 21443a2b5b9cSMiklos Szeredi list_for_each_entry_safe(req, next, &fpq->io, list) { 2145b716d425SMiklos Szeredi req->out.h.error = -ECONNABORTED; 2146b716d425SMiklos Szeredi spin_lock(&req->waitq.lock); 2147b716d425SMiklos Szeredi set_bit(FR_ABORTED, &req->flags); 214877cd9d48SMiklos Szeredi if (!test_bit(FR_LOCKED, &req->flags)) { 214977cd9d48SMiklos Szeredi set_bit(FR_PRIVATE, &req->flags); 215087114373SMiklos Szeredi __fuse_get_request(req); 215175f3ee4cSMiklos Szeredi list_move(&req->list, &to_end); 215277cd9d48SMiklos Szeredi } 2153b716d425SMiklos Szeredi spin_unlock(&req->waitq.lock); 2154b716d425SMiklos Szeredi } 2155be2ff42cSKirill Tkhai for (i = 0; i < FUSE_PQ_HASH_SIZE; i++) 2156be2ff42cSKirill Tkhai list_splice_tail_init(&fpq->processing[i], 2157be2ff42cSKirill Tkhai &to_end); 215845a91cb1SMiklos Szeredi spin_unlock(&fpq->lock); 2159c3696046SMiklos Szeredi } 2160ae2dffa3SKirill Tkhai spin_lock(&fc->bg_lock); 2161ae2dffa3SKirill Tkhai fc->blocked = 0; 216241f98274SMiklos Szeredi fc->max_background = UINT_MAX; 216341f98274SMiklos Szeredi flush_bg_queue(fc); 2164ae2dffa3SKirill Tkhai spin_unlock(&fc->bg_lock); 21658c91189aSMiklos Szeredi 216676e43c8cSEric Biggers spin_lock(&fiq->lock); 21678c91189aSMiklos Szeredi fiq->connected = 0; 216875f3ee4cSMiklos Szeredi list_for_each_entry(req, &fiq->pending, list) 2169a8a86d78STahsin Erdogan clear_bit(FR_PENDING, &req->flags); 217075f3ee4cSMiklos Szeredi list_splice_tail_init(&fiq->pending, &to_end); 21718c91189aSMiklos Szeredi while (forget_pending(fiq)) 21724388c5aaSVivek Goyal kfree(fuse_dequeue_forget(fiq, 1, NULL)); 217376e43c8cSEric Biggers wake_up_all(&fiq->waitq); 217476e43c8cSEric Biggers spin_unlock(&fiq->lock); 21758c91189aSMiklos Szeredi kill_fasync(&fiq->fasync, SIGIO, POLL_IN); 2176ee314a87SMiklos Szeredi end_polls(fc); 2177ee314a87SMiklos Szeredi wake_up_all(&fc->blocked_waitq); 2178ee314a87SMiklos Szeredi spin_unlock(&fc->lock); 21798c91189aSMiklos Szeredi 21808f622e94SMax Reitz end_requests(&to_end); 2181ee314a87SMiklos Szeredi } else { 2182d7133114SMiklos Szeredi spin_unlock(&fc->lock); 218369a53bf2SMiklos Szeredi } 2184ee314a87SMiklos Szeredi } 218508cbf542STejun Heo EXPORT_SYMBOL_GPL(fuse_abort_conn); 218669a53bf2SMiklos Szeredi 2187b8f95e5dSMiklos Szeredi void fuse_wait_aborted(struct fuse_conn *fc) 2188b8f95e5dSMiklos Szeredi { 21892d84a2d1SMiklos Szeredi /* matches implicit memory barrier in fuse_drop_waiting() */ 21902d84a2d1SMiklos Szeredi smp_mb(); 2191b8f95e5dSMiklos Szeredi wait_event(fc->blocked_waitq, atomic_read(&fc->num_waiting) == 0); 2192b8f95e5dSMiklos Szeredi } 2193b8f95e5dSMiklos Szeredi 219408cbf542STejun Heo int fuse_dev_release(struct inode *inode, struct file *file) 2195334f485dSMiklos Szeredi { 2196cc080e9eSMiklos Szeredi struct fuse_dev *fud = fuse_get_dev(file); 2197cc080e9eSMiklos Szeredi 2198cc080e9eSMiklos Szeredi if (fud) { 2199cc080e9eSMiklos Szeredi struct fuse_conn *fc = fud->fc; 2200c3696046SMiklos Szeredi struct fuse_pqueue *fpq = &fud->pq; 220145ff350bSMiklos Szeredi LIST_HEAD(to_end); 2202be2ff42cSKirill Tkhai unsigned int i; 2203cc080e9eSMiklos Szeredi 220445ff350bSMiklos Szeredi spin_lock(&fpq->lock); 2205c3696046SMiklos Szeredi WARN_ON(!list_empty(&fpq->io)); 2206be2ff42cSKirill Tkhai for (i = 0; i < FUSE_PQ_HASH_SIZE; i++) 2207be2ff42cSKirill Tkhai list_splice_init(&fpq->processing[i], &to_end); 220845ff350bSMiklos Szeredi spin_unlock(&fpq->lock); 220945ff350bSMiklos Szeredi 22108f622e94SMax Reitz end_requests(&to_end); 221145ff350bSMiklos Szeredi 2212c3696046SMiklos Szeredi /* Are we the last open device? */ 2213c3696046SMiklos Szeredi if (atomic_dec_and_test(&fc->dev_count)) { 2214f88996a9SMiklos Szeredi WARN_ON(fc->iq.fasync != NULL); 2215eb98e3bdSMiklos Szeredi fuse_abort_conn(fc); 2216c3696046SMiklos Szeredi } 2217cc080e9eSMiklos Szeredi fuse_dev_free(fud); 2218385a17bfSJeff Dike } 2219334f485dSMiklos Szeredi return 0; 2220334f485dSMiklos Szeredi } 222108cbf542STejun Heo EXPORT_SYMBOL_GPL(fuse_dev_release); 2222334f485dSMiklos Szeredi 2223385a17bfSJeff Dike static int fuse_dev_fasync(int fd, struct file *file, int on) 2224385a17bfSJeff Dike { 2225cc080e9eSMiklos Szeredi struct fuse_dev *fud = fuse_get_dev(file); 2226cc080e9eSMiklos Szeredi 2227cc080e9eSMiklos Szeredi if (!fud) 2228a87046d8SMiklos Szeredi return -EPERM; 2229385a17bfSJeff Dike 2230385a17bfSJeff Dike /* No locking - fasync_helper does its own locking */ 2231cc080e9eSMiklos Szeredi return fasync_helper(fd, file, on, &fud->fc->iq.fasync); 2232385a17bfSJeff Dike } 2233385a17bfSJeff Dike 223400c570f4SMiklos Szeredi static int fuse_device_clone(struct fuse_conn *fc, struct file *new) 223500c570f4SMiklos Szeredi { 2236cc080e9eSMiklos Szeredi struct fuse_dev *fud; 2237cc080e9eSMiklos Szeredi 223800c570f4SMiklos Szeredi if (new->private_data) 223900c570f4SMiklos Szeredi return -EINVAL; 224000c570f4SMiklos Szeredi 22410cd1eb9aSVivek Goyal fud = fuse_dev_alloc_install(fc); 2242cc080e9eSMiklos Szeredi if (!fud) 2243cc080e9eSMiklos Szeredi return -ENOMEM; 2244cc080e9eSMiklos Szeredi 2245cc080e9eSMiklos Szeredi new->private_data = fud; 2246c3696046SMiklos Szeredi atomic_inc(&fc->dev_count); 224700c570f4SMiklos Szeredi 224800c570f4SMiklos Szeredi return 0; 224900c570f4SMiklos Szeredi } 225000c570f4SMiklos Szeredi 225100c570f4SMiklos Szeredi static long fuse_dev_ioctl(struct file *file, unsigned int cmd, 225200c570f4SMiklos Szeredi unsigned long arg) 225300c570f4SMiklos Szeredi { 2254f8425c93SAlessio Balsini int res; 225500c570f4SMiklos Szeredi int oldfd; 2256f8425c93SAlessio Balsini struct fuse_dev *fud = NULL; 225700c570f4SMiklos Szeredi 22586076f5f3SAlessio Balsini switch (cmd) { 22596076f5f3SAlessio Balsini case FUSE_DEV_IOC_CLONE: 2260f8425c93SAlessio Balsini res = -EFAULT; 226100c570f4SMiklos Szeredi if (!get_user(oldfd, (__u32 __user *)arg)) { 226200c570f4SMiklos Szeredi struct file *old = fget(oldfd); 226300c570f4SMiklos Szeredi 2264f8425c93SAlessio Balsini res = -EINVAL; 226500c570f4SMiklos Szeredi if (old) { 22668ed1f0e2SJann Horn /* 22678ed1f0e2SJann Horn * Check against file->f_op because CUSE 22688ed1f0e2SJann Horn * uses the same ioctl handler. 22698ed1f0e2SJann Horn */ 22708ed1f0e2SJann Horn if (old->f_op == file->f_op && 22718ed1f0e2SJann Horn old->f_cred->user_ns == file->f_cred->user_ns) 22728ed1f0e2SJann Horn fud = fuse_get_dev(old); 227300c570f4SMiklos Szeredi 2274cc080e9eSMiklos Szeredi if (fud) { 227500c570f4SMiklos Szeredi mutex_lock(&fuse_mutex); 2276f8425c93SAlessio Balsini res = fuse_device_clone(fud->fc, file); 227700c570f4SMiklos Szeredi mutex_unlock(&fuse_mutex); 227800c570f4SMiklos Szeredi } 227900c570f4SMiklos Szeredi fput(old); 228000c570f4SMiklos Szeredi } 228100c570f4SMiklos Szeredi } 2282f8425c93SAlessio Balsini break; 2283f8425c93SAlessio Balsini default: 2284f8425c93SAlessio Balsini res = -ENOTTY; 2285f8425c93SAlessio Balsini break; 228600c570f4SMiklos Szeredi } 2287f8425c93SAlessio Balsini return res; 228800c570f4SMiklos Szeredi } 228900c570f4SMiklos Szeredi 22904b6f5d20SArjan van de Ven const struct file_operations fuse_dev_operations = { 2291334f485dSMiklos Szeredi .owner = THIS_MODULE, 229294e4fe2cSTom Van Braeckel .open = fuse_dev_open, 2293334f485dSMiklos Szeredi .llseek = no_llseek, 2294fbdbaccaSAl Viro .read_iter = fuse_dev_read, 2295c3021629SMiklos Szeredi .splice_read = fuse_dev_splice_read, 2296fbdbaccaSAl Viro .write_iter = fuse_dev_write, 2297dd3bb14fSMiklos Szeredi .splice_write = fuse_dev_splice_write, 2298334f485dSMiklos Szeredi .poll = fuse_dev_poll, 2299334f485dSMiklos Szeredi .release = fuse_dev_release, 2300385a17bfSJeff Dike .fasync = fuse_dev_fasync, 230100c570f4SMiklos Szeredi .unlocked_ioctl = fuse_dev_ioctl, 23021832f2d8SArnd Bergmann .compat_ioctl = compat_ptr_ioctl, 2303334f485dSMiklos Szeredi }; 230408cbf542STejun Heo EXPORT_SYMBOL_GPL(fuse_dev_operations); 2305334f485dSMiklos Szeredi 2306334f485dSMiklos Szeredi static struct miscdevice fuse_miscdevice = { 2307334f485dSMiklos Szeredi .minor = FUSE_MINOR, 2308334f485dSMiklos Szeredi .name = "fuse", 2309334f485dSMiklos Szeredi .fops = &fuse_dev_operations, 2310334f485dSMiklos Szeredi }; 2311334f485dSMiklos Szeredi 2312334f485dSMiklos Szeredi int __init fuse_dev_init(void) 2313334f485dSMiklos Szeredi { 2314334f485dSMiklos Szeredi int err = -ENOMEM; 2315334f485dSMiklos Szeredi fuse_req_cachep = kmem_cache_create("fuse_request", 2316334f485dSMiklos Szeredi sizeof(struct fuse_req), 231720c2df83SPaul Mundt 0, 0, NULL); 2318334f485dSMiklos Szeredi if (!fuse_req_cachep) 2319334f485dSMiklos Szeredi goto out; 2320334f485dSMiklos Szeredi 2321334f485dSMiklos Szeredi err = misc_register(&fuse_miscdevice); 2322334f485dSMiklos Szeredi if (err) 2323334f485dSMiklos Szeredi goto out_cache_clean; 2324334f485dSMiklos Szeredi 2325334f485dSMiklos Szeredi return 0; 2326334f485dSMiklos Szeredi 2327334f485dSMiklos Szeredi out_cache_clean: 2328334f485dSMiklos Szeredi kmem_cache_destroy(fuse_req_cachep); 2329334f485dSMiklos Szeredi out: 2330334f485dSMiklos Szeredi return err; 2331334f485dSMiklos Szeredi } 2332334f485dSMiklos Szeredi 2333334f485dSMiklos Szeredi void fuse_dev_cleanup(void) 2334334f485dSMiklos Szeredi { 2335334f485dSMiklos Szeredi misc_deregister(&fuse_miscdevice); 2336334f485dSMiklos Szeredi kmem_cache_destroy(fuse_req_cachep); 2337334f485dSMiklos Szeredi } 2338