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 437213394cSMiklos Szeredi static void fuse_request_init(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); 50334f485dSMiklos Szeredi } 51334f485dSMiklos Szeredi 527213394cSMiklos Szeredi static struct fuse_req *fuse_request_alloc(gfp_t flags) 53334f485dSMiklos Szeredi { 548a7aa286SMiklos Szeredi struct fuse_req *req = kmem_cache_zalloc(fuse_req_cachep, flags); 557213394cSMiklos Szeredi if (req) 567213394cSMiklos Szeredi fuse_request_init(req); 574250c066SMaxim Patlasov 58334f485dSMiklos Szeredi return req; 59334f485dSMiklos Szeredi } 604250c066SMaxim Patlasov 6166abc359SMiklos Szeredi static void fuse_request_free(struct fuse_req *req) 62e52a8250SMiklos Szeredi { 63334f485dSMiklos Szeredi kmem_cache_free(fuse_req_cachep, req); 64334f485dSMiklos Szeredi } 65334f485dSMiklos Szeredi 6666abc359SMiklos Szeredi static void __fuse_get_request(struct fuse_req *req) 67334f485dSMiklos Szeredi { 68ec99f6d3SElena Reshetova refcount_inc(&req->count); 69334f485dSMiklos Szeredi } 70334f485dSMiklos Szeredi 71334f485dSMiklos Szeredi /* Must be called with > 1 refcount */ 72334f485dSMiklos Szeredi static void __fuse_put_request(struct fuse_req *req) 73334f485dSMiklos Szeredi { 74ec99f6d3SElena Reshetova refcount_dec(&req->count); 75334f485dSMiklos Szeredi } 76334f485dSMiklos Szeredi 779759bd51SMiklos Szeredi void fuse_set_initialized(struct fuse_conn *fc) 789759bd51SMiklos Szeredi { 799759bd51SMiklos Szeredi /* Make sure stores before this are seen on another CPU */ 809759bd51SMiklos Szeredi smp_wmb(); 819759bd51SMiklos Szeredi fc->initialized = 1; 829759bd51SMiklos Szeredi } 839759bd51SMiklos Szeredi 840aada884SMaxim Patlasov static bool fuse_block_alloc(struct fuse_conn *fc, bool for_background) 850aada884SMaxim Patlasov { 860aada884SMaxim Patlasov return !fc->initialized || (for_background && fc->blocked); 870aada884SMaxim Patlasov } 880aada884SMaxim Patlasov 89b8f95e5dSMiklos Szeredi static void fuse_drop_waiting(struct fuse_conn *fc) 90b8f95e5dSMiklos Szeredi { 912d84a2d1SMiklos Szeredi /* 922d84a2d1SMiklos Szeredi * lockess check of fc->connected is okay, because atomic_dec_and_test() 932d84a2d1SMiklos Szeredi * provides a memory barrier mached with the one in fuse_wait_aborted() 942d84a2d1SMiklos Szeredi * to ensure no wake-up is missed. 952d84a2d1SMiklos Szeredi */ 962d84a2d1SMiklos Szeredi if (atomic_dec_and_test(&fc->num_waiting) && 972d84a2d1SMiklos Szeredi !READ_ONCE(fc->connected)) { 98b8f95e5dSMiklos Szeredi /* wake up aborters */ 99b8f95e5dSMiklos Szeredi wake_up_all(&fc->blocked_waitq); 100b8f95e5dSMiklos Szeredi } 101b8f95e5dSMiklos Szeredi } 102b8f95e5dSMiklos Szeredi 10366abc359SMiklos Szeredi static void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req); 10466abc359SMiklos Szeredi 1057213394cSMiklos Szeredi static struct fuse_req *fuse_get_req(struct fuse_conn *fc, bool for_background) 106334f485dSMiklos Szeredi { 10708a53cdcSMiklos Szeredi struct fuse_req *req; 1080aada884SMaxim Patlasov int err; 1090aada884SMaxim Patlasov atomic_inc(&fc->num_waiting); 1100aada884SMaxim Patlasov 1110aada884SMaxim Patlasov if (fuse_block_alloc(fc, for_background)) { 1129bc5dddaSMiklos Szeredi err = -EINTR; 1137d3a07fcSAl Viro if (wait_event_killable_exclusive(fc->blocked_waitq, 1147d3a07fcSAl Viro !fuse_block_alloc(fc, for_background))) 1159bc5dddaSMiklos Szeredi goto out; 1160aada884SMaxim Patlasov } 1179759bd51SMiklos Szeredi /* Matches smp_wmb() in fuse_set_initialized() */ 1189759bd51SMiklos Szeredi smp_rmb(); 11908a53cdcSMiklos Szeredi 12051eb01e7SMiklos Szeredi err = -ENOTCONN; 12151eb01e7SMiklos Szeredi if (!fc->connected) 12251eb01e7SMiklos Szeredi goto out; 12351eb01e7SMiklos Szeredi 124de155226SMiklos Szeredi err = -ECONNREFUSED; 125de155226SMiklos Szeredi if (fc->conn_error) 126de155226SMiklos Szeredi goto out; 127de155226SMiklos Szeredi 1287213394cSMiklos Szeredi req = fuse_request_alloc(GFP_KERNEL); 1299bc5dddaSMiklos Szeredi err = -ENOMEM; 130722d2beaSMaxim Patlasov if (!req) { 131722d2beaSMaxim Patlasov if (for_background) 132722d2beaSMaxim Patlasov wake_up(&fc->blocked_waitq); 1339bc5dddaSMiklos Szeredi goto out; 134722d2beaSMaxim Patlasov } 135334f485dSMiklos Szeredi 1368cb08329SEric W. Biederman req->in.h.uid = from_kuid(fc->user_ns, current_fsuid()); 1378cb08329SEric W. Biederman req->in.h.gid = from_kgid(fc->user_ns, current_fsgid()); 138c9582eb0SEric W. Biederman req->in.h.pid = pid_nr_ns(task_pid(current), fc->pid_ns); 139c9582eb0SEric W. Biederman 140825d6d33SMiklos Szeredi __set_bit(FR_WAITING, &req->flags); 141825d6d33SMiklos Szeredi if (for_background) 142825d6d33SMiklos Szeredi __set_bit(FR_BACKGROUND, &req->flags); 143825d6d33SMiklos Szeredi 144c9582eb0SEric W. Biederman if (unlikely(req->in.h.uid == ((uid_t)-1) || 145c9582eb0SEric W. Biederman req->in.h.gid == ((gid_t)-1))) { 146c9582eb0SEric W. Biederman fuse_put_request(fc, req); 147c9582eb0SEric W. Biederman return ERR_PTR(-EOVERFLOW); 148c9582eb0SEric W. Biederman } 149334f485dSMiklos Szeredi return req; 1509bc5dddaSMiklos Szeredi 1519bc5dddaSMiklos Szeredi out: 152b8f95e5dSMiklos Szeredi fuse_drop_waiting(fc); 1539bc5dddaSMiklos Szeredi return ERR_PTR(err); 154334f485dSMiklos Szeredi } 1558b41e671SMaxim Patlasov 15666abc359SMiklos Szeredi static void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req) 157334f485dSMiklos Szeredi { 158ec99f6d3SElena Reshetova if (refcount_dec_and_test(&req->count)) { 159825d6d33SMiklos Szeredi if (test_bit(FR_BACKGROUND, &req->flags)) { 160722d2beaSMaxim Patlasov /* 161722d2beaSMaxim Patlasov * We get here in the unlikely case that a background 162722d2beaSMaxim Patlasov * request was allocated but not sent 163722d2beaSMaxim Patlasov */ 164ae2dffa3SKirill Tkhai spin_lock(&fc->bg_lock); 165722d2beaSMaxim Patlasov if (!fc->blocked) 166722d2beaSMaxim Patlasov wake_up(&fc->blocked_waitq); 167ae2dffa3SKirill Tkhai spin_unlock(&fc->bg_lock); 168722d2beaSMaxim Patlasov } 169722d2beaSMaxim Patlasov 170825d6d33SMiklos Szeredi if (test_bit(FR_WAITING, &req->flags)) { 171825d6d33SMiklos Szeredi __clear_bit(FR_WAITING, &req->flags); 172b8f95e5dSMiklos Szeredi fuse_drop_waiting(fc); 17373e0e738SMiklos Szeredi } 17433649c91SMiklos Szeredi 175ce1d5a49SMiklos Szeredi fuse_request_free(req); 1767128ec2aSMiklos Szeredi } 1777128ec2aSMiklos Szeredi } 1787128ec2aSMiklos Szeredi 17914d46d7aSStefan Hajnoczi unsigned int fuse_len_args(unsigned int numargs, struct fuse_arg *args) 180d12def1bSMiklos Szeredi { 181d12def1bSMiklos Szeredi unsigned nbytes = 0; 182d12def1bSMiklos Szeredi unsigned i; 183d12def1bSMiklos Szeredi 184d12def1bSMiklos Szeredi for (i = 0; i < numargs; i++) 185d12def1bSMiklos Szeredi nbytes += args[i].size; 186d12def1bSMiklos Szeredi 187d12def1bSMiklos Szeredi return nbytes; 188d12def1bSMiklos Szeredi } 18914d46d7aSStefan Hajnoczi EXPORT_SYMBOL_GPL(fuse_len_args); 190d12def1bSMiklos Szeredi 19179d96effSStefan Hajnoczi u64 fuse_get_unique(struct fuse_iqueue *fiq) 192d12def1bSMiklos Szeredi { 193c59fd85eSKirill Tkhai fiq->reqctr += FUSE_REQ_ID_STEP; 194c59fd85eSKirill Tkhai return fiq->reqctr; 195d12def1bSMiklos Szeredi } 19679d96effSStefan Hajnoczi EXPORT_SYMBOL_GPL(fuse_get_unique); 197d12def1bSMiklos Szeredi 198be2ff42cSKirill Tkhai static unsigned int fuse_req_hash(u64 unique) 199be2ff42cSKirill Tkhai { 200be2ff42cSKirill Tkhai return hash_long(unique & ~FUSE_INT_REQ_BIT, FUSE_PQ_HASH_BITS); 201be2ff42cSKirill Tkhai } 202be2ff42cSKirill Tkhai 203ae3aad77SStefan Hajnoczi /** 204ae3aad77SStefan Hajnoczi * A new request is available, wake fiq->waitq 205ae3aad77SStefan Hajnoczi */ 206ae3aad77SStefan Hajnoczi static void fuse_dev_wake_and_unlock(struct fuse_iqueue *fiq) 207ae3aad77SStefan Hajnoczi __releases(fiq->lock) 208ae3aad77SStefan Hajnoczi { 209ae3aad77SStefan Hajnoczi wake_up(&fiq->waitq); 210ae3aad77SStefan Hajnoczi kill_fasync(&fiq->fasync, SIGIO, POLL_IN); 211ae3aad77SStefan Hajnoczi spin_unlock(&fiq->lock); 212ae3aad77SStefan Hajnoczi } 213ae3aad77SStefan Hajnoczi 214ae3aad77SStefan Hajnoczi const struct fuse_iqueue_ops fuse_dev_fiq_ops = { 215ae3aad77SStefan Hajnoczi .wake_forget_and_unlock = fuse_dev_wake_and_unlock, 216ae3aad77SStefan Hajnoczi .wake_interrupt_and_unlock = fuse_dev_wake_and_unlock, 217ae3aad77SStefan Hajnoczi .wake_pending_and_unlock = fuse_dev_wake_and_unlock, 218ae3aad77SStefan Hajnoczi }; 219ae3aad77SStefan Hajnoczi EXPORT_SYMBOL_GPL(fuse_dev_fiq_ops); 220ae3aad77SStefan Hajnoczi 221ae3aad77SStefan Hajnoczi static void queue_request_and_unlock(struct fuse_iqueue *fiq, 222ae3aad77SStefan Hajnoczi struct fuse_req *req) 223ae3aad77SStefan Hajnoczi __releases(fiq->lock) 224d12def1bSMiklos Szeredi { 225d12def1bSMiklos Szeredi req->in.h.len = sizeof(struct fuse_in_header) + 22614d46d7aSStefan Hajnoczi fuse_len_args(req->args->in_numargs, 227d4993774SMiklos Szeredi (struct fuse_arg *) req->args->in_args); 228f88996a9SMiklos Szeredi list_add_tail(&req->list, &fiq->pending); 229ae3aad77SStefan Hajnoczi fiq->ops->wake_pending_and_unlock(fiq); 230d12def1bSMiklos Szeredi } 231d12def1bSMiklos Szeredi 23207e77dcaSMiklos Szeredi void fuse_queue_forget(struct fuse_conn *fc, struct fuse_forget_link *forget, 23307e77dcaSMiklos Szeredi u64 nodeid, u64 nlookup) 23407e77dcaSMiklos Szeredi { 235f88996a9SMiklos Szeredi struct fuse_iqueue *fiq = &fc->iq; 236f88996a9SMiklos Szeredi 23702c048b9SMiklos Szeredi forget->forget_one.nodeid = nodeid; 23802c048b9SMiklos Szeredi forget->forget_one.nlookup = nlookup; 23907e77dcaSMiklos Szeredi 24076e43c8cSEric Biggers spin_lock(&fiq->lock); 241e16714d8SMiklos Szeredi if (fiq->connected) { 242f88996a9SMiklos Szeredi fiq->forget_list_tail->next = forget; 243f88996a9SMiklos Szeredi fiq->forget_list_tail = forget; 244ae3aad77SStefan Hajnoczi fiq->ops->wake_forget_and_unlock(fiq); 2455dfcc87fSMiklos Szeredi } else { 2465dfcc87fSMiklos Szeredi kfree(forget); 24776e43c8cSEric Biggers spin_unlock(&fiq->lock); 24807e77dcaSMiklos Szeredi } 249ae3aad77SStefan Hajnoczi } 25007e77dcaSMiklos Szeredi 251d12def1bSMiklos Szeredi static void flush_bg_queue(struct fuse_conn *fc) 252d12def1bSMiklos Szeredi { 253e287179aSKirill Tkhai struct fuse_iqueue *fiq = &fc->iq; 254e287179aSKirill Tkhai 2557a6d3c8bSCsaba Henk while (fc->active_background < fc->max_background && 256d12def1bSMiklos Szeredi !list_empty(&fc->bg_queue)) { 257d12def1bSMiklos Szeredi struct fuse_req *req; 258d12def1bSMiklos Szeredi 259e287179aSKirill Tkhai req = list_first_entry(&fc->bg_queue, struct fuse_req, list); 260d12def1bSMiklos Szeredi list_del(&req->list); 261d12def1bSMiklos Szeredi fc->active_background++; 26276e43c8cSEric Biggers spin_lock(&fiq->lock); 263f88996a9SMiklos Szeredi req->in.h.unique = fuse_get_unique(fiq); 264ae3aad77SStefan Hajnoczi queue_request_and_unlock(fiq, req); 265d12def1bSMiklos Szeredi } 266d12def1bSMiklos Szeredi } 267d12def1bSMiklos Szeredi 2686dbbcb12SMiklos Szeredi /* 269334f485dSMiklos Szeredi * This function is called when a request is finished. Either a reply 270f9a2842eSMiklos Szeredi * has arrived or it was aborted (and not yet sent) or some error 271f43b155aSMiklos Szeredi * occurred during communication with userspace, or the device file 27251eb01e7SMiklos Szeredi * was closed. The requester thread is woken up (if still waiting), 27351eb01e7SMiklos Szeredi * the 'end' callback is called if given, else the reference to the 27451eb01e7SMiklos Szeredi * request is released 275334f485dSMiklos Szeredi */ 27604ec5af0SStefan Hajnoczi void fuse_request_end(struct fuse_conn *fc, struct fuse_req *req) 277334f485dSMiklos Szeredi { 2784ce60812SMiklos Szeredi struct fuse_iqueue *fiq = &fc->iq; 279d4993774SMiklos Szeredi bool async = req->args->end; 280365ae710SMiklos Szeredi 281efe2800fSMiklos Szeredi if (test_and_set_bit(FR_FINISHED, &req->flags)) 282b8f95e5dSMiklos Szeredi goto put_request; 283217316a6SKirill Tkhai /* 284217316a6SKirill Tkhai * test_and_set_bit() implies smp_mb() between bit 285217316a6SKirill Tkhai * changing and below intr_entry check. Pairs with 286217316a6SKirill Tkhai * smp_mb() from queue_interrupt(). 287217316a6SKirill Tkhai */ 288217316a6SKirill Tkhai if (!list_empty(&req->intr_entry)) { 28976e43c8cSEric Biggers spin_lock(&fiq->lock); 2900d8e84b0SMiklos Szeredi list_del_init(&req->intr_entry); 29176e43c8cSEric Biggers spin_unlock(&fiq->lock); 292217316a6SKirill Tkhai } 29333e14b4dSMiklos Szeredi WARN_ON(test_bit(FR_PENDING, &req->flags)); 29433e14b4dSMiklos Szeredi WARN_ON(test_bit(FR_SENT, &req->flags)); 295825d6d33SMiklos Szeredi if (test_bit(FR_BACKGROUND, &req->flags)) { 296ae2dffa3SKirill Tkhai spin_lock(&fc->bg_lock); 297825d6d33SMiklos Szeredi clear_bit(FR_BACKGROUND, &req->flags); 298908a572bSMiklos Szeredi if (fc->num_background == fc->max_background) { 29951eb01e7SMiklos Szeredi fc->blocked = 0; 300722d2beaSMaxim Patlasov wake_up(&fc->blocked_waitq); 301908a572bSMiklos Szeredi } else if (!fc->blocked) { 302908a572bSMiklos Szeredi /* 303908a572bSMiklos Szeredi * Wake up next waiter, if any. It's okay to use 304908a572bSMiklos Szeredi * waitqueue_active(), as we've already synced up 305908a572bSMiklos Szeredi * fc->blocked with waiters with the wake_up() call 306908a572bSMiklos Szeredi * above. 307908a572bSMiklos Szeredi */ 308908a572bSMiklos Szeredi if (waitqueue_active(&fc->blocked_waitq)) 309908a572bSMiklos Szeredi wake_up(&fc->blocked_waitq); 310908a572bSMiklos Szeredi } 311722d2beaSMaxim Patlasov 3128a301eb1STejun Heo if (fc->num_background == fc->congestion_threshold && fc->sb) { 3135f7f7543SJan Kara clear_bdi_congested(fc->sb->s_bdi, BLK_RW_SYNC); 3145f7f7543SJan Kara clear_bdi_congested(fc->sb->s_bdi, BLK_RW_ASYNC); 315f92b99b9SMiklos Szeredi } 31651eb01e7SMiklos Szeredi fc->num_background--; 317d12def1bSMiklos Szeredi fc->active_background--; 318d12def1bSMiklos Szeredi flush_bg_queue(fc); 319ae2dffa3SKirill Tkhai spin_unlock(&fc->bg_lock); 3205e0fed71SKirill Tkhai } else { 3215e0fed71SKirill Tkhai /* Wake up waiter sleeping in request_wait_answer() */ 32251eb01e7SMiklos Szeredi wake_up(&req->waitq); 3235e0fed71SKirill Tkhai } 3245e0fed71SKirill Tkhai 325d4993774SMiklos Szeredi if (async) 326d4993774SMiklos Szeredi req->args->end(fc, req->args, req->out.h.error); 327b8f95e5dSMiklos Szeredi put_request: 328f43b155aSMiklos Szeredi fuse_put_request(fc, req); 329334f485dSMiklos Szeredi } 33004ec5af0SStefan Hajnoczi EXPORT_SYMBOL_GPL(fuse_request_end); 331334f485dSMiklos Szeredi 332b782911bSKirill Tkhai static int queue_interrupt(struct fuse_iqueue *fiq, struct fuse_req *req) 333a4d27e75SMiklos Szeredi { 33476e43c8cSEric Biggers spin_lock(&fiq->lock); 335b782911bSKirill Tkhai /* Check for we've sent request to interrupt this req */ 336b782911bSKirill Tkhai if (unlikely(!test_bit(FR_INTERRUPTED, &req->flags))) { 33776e43c8cSEric Biggers spin_unlock(&fiq->lock); 338b782911bSKirill Tkhai return -EINVAL; 339b782911bSKirill Tkhai } 340b782911bSKirill Tkhai 341217316a6SKirill Tkhai if (list_empty(&req->intr_entry)) { 342217316a6SKirill Tkhai list_add_tail(&req->intr_entry, &fiq->interrupts); 343217316a6SKirill Tkhai /* 344217316a6SKirill Tkhai * Pairs with smp_mb() implied by test_and_set_bit() 345217316a6SKirill Tkhai * from request_end(). 346217316a6SKirill Tkhai */ 347217316a6SKirill Tkhai smp_mb(); 3486ba4d272SSahitya Tummala if (test_bit(FR_FINISHED, &req->flags)) { 349217316a6SKirill Tkhai list_del_init(&req->intr_entry); 35076e43c8cSEric Biggers spin_unlock(&fiq->lock); 351b782911bSKirill Tkhai return 0; 3526ba4d272SSahitya Tummala } 353ae3aad77SStefan Hajnoczi fiq->ops->wake_interrupt_and_unlock(fiq); 354ae3aad77SStefan Hajnoczi } else { 35576e43c8cSEric Biggers spin_unlock(&fiq->lock); 356ae3aad77SStefan Hajnoczi } 357b782911bSKirill Tkhai return 0; 358a4d27e75SMiklos Szeredi } 359a4d27e75SMiklos Szeredi 3607c352bdfSMiklos Szeredi static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req) 361334f485dSMiklos Szeredi { 3624ce60812SMiklos Szeredi struct fuse_iqueue *fiq = &fc->iq; 363c4775267SMiklos Szeredi int err; 364c4775267SMiklos Szeredi 365a4d27e75SMiklos Szeredi if (!fc->no_interrupt) { 366a4d27e75SMiklos Szeredi /* Any signal may interrupt this */ 367c4775267SMiklos Szeredi err = wait_event_interruptible(req->waitq, 36833e14b4dSMiklos Szeredi test_bit(FR_FINISHED, &req->flags)); 369c4775267SMiklos Szeredi if (!err) 370334f485dSMiklos Szeredi return; 371334f485dSMiklos Szeredi 372825d6d33SMiklos Szeredi set_bit(FR_INTERRUPTED, &req->flags); 3738f7bb368SMiklos Szeredi /* matches barrier in fuse_dev_do_read() */ 3748f7bb368SMiklos Szeredi smp_mb__after_atomic(); 37533e14b4dSMiklos Szeredi if (test_bit(FR_SENT, &req->flags)) 3764ce60812SMiklos Szeredi queue_interrupt(fiq, req); 377a4d27e75SMiklos Szeredi } 378a4d27e75SMiklos Szeredi 379825d6d33SMiklos Szeredi if (!test_bit(FR_FORCE, &req->flags)) { 380a4d27e75SMiklos Szeredi /* Only fatal signals may interrupt this */ 3817d3a07fcSAl Viro err = wait_event_killable(req->waitq, 38233e14b4dSMiklos Szeredi test_bit(FR_FINISHED, &req->flags)); 383c4775267SMiklos Szeredi if (!err) 384a4d27e75SMiklos Szeredi return; 385a4d27e75SMiklos Szeredi 38676e43c8cSEric Biggers spin_lock(&fiq->lock); 387a131de0aSMiklos Szeredi /* Request is not yet in userspace, bail out */ 38833e14b4dSMiklos Szeredi if (test_bit(FR_PENDING, &req->flags)) { 389a131de0aSMiklos Szeredi list_del(&req->list); 39076e43c8cSEric Biggers spin_unlock(&fiq->lock); 391a131de0aSMiklos Szeredi __fuse_put_request(req); 392334f485dSMiklos Szeredi req->out.h.error = -EINTR; 393a131de0aSMiklos Szeredi return; 394a131de0aSMiklos Szeredi } 39576e43c8cSEric Biggers spin_unlock(&fiq->lock); 396a131de0aSMiklos Szeredi } 397a131de0aSMiklos Szeredi 398a131de0aSMiklos Szeredi /* 399a131de0aSMiklos Szeredi * Either request is already in userspace, or it was forced. 400a131de0aSMiklos Szeredi * Wait it out. 401a131de0aSMiklos Szeredi */ 40233e14b4dSMiklos Szeredi wait_event(req->waitq, test_bit(FR_FINISHED, &req->flags)); 403334f485dSMiklos Szeredi } 404334f485dSMiklos Szeredi 4056a4e922cSEric Wong static void __fuse_request_send(struct fuse_conn *fc, struct fuse_req *req) 406334f485dSMiklos Szeredi { 407e16714d8SMiklos Szeredi struct fuse_iqueue *fiq = &fc->iq; 408e16714d8SMiklos Szeredi 409825d6d33SMiklos Szeredi BUG_ON(test_bit(FR_BACKGROUND, &req->flags)); 41076e43c8cSEric Biggers spin_lock(&fiq->lock); 411e16714d8SMiklos Szeredi if (!fiq->connected) { 41276e43c8cSEric Biggers spin_unlock(&fiq->lock); 413334f485dSMiklos Szeredi req->out.h.error = -ENOTCONN; 414c4775267SMiklos Szeredi } else { 415f88996a9SMiklos Szeredi req->in.h.unique = fuse_get_unique(fiq); 416334f485dSMiklos Szeredi /* acquire extra reference, since request is still needed 41704ec5af0SStefan Hajnoczi after fuse_request_end() */ 418334f485dSMiklos Szeredi __fuse_get_request(req); 419ae3aad77SStefan Hajnoczi queue_request_and_unlock(fiq, req); 420334f485dSMiklos Szeredi 4217c352bdfSMiklos Szeredi request_wait_answer(fc, req); 42204ec5af0SStefan Hajnoczi /* Pairs with smp_wmb() in fuse_request_end() */ 423c4775267SMiklos Szeredi smp_rmb(); 424334f485dSMiklos Szeredi } 425334f485dSMiklos Szeredi } 4266a4e922cSEric Wong 42721f62174SMiklos Szeredi static void fuse_adjust_compat(struct fuse_conn *fc, struct fuse_args *args) 42821f62174SMiklos Szeredi { 429d5b48543SMiklos Szeredi if (fc->minor < 4 && args->opcode == FUSE_STATFS) 430d5b48543SMiklos Szeredi args->out_args[0].size = FUSE_COMPAT_STATFS_SIZE; 43121f62174SMiklos Szeredi 43221f62174SMiklos Szeredi if (fc->minor < 9) { 433d5b48543SMiklos Szeredi switch (args->opcode) { 43421f62174SMiklos Szeredi case FUSE_LOOKUP: 43521f62174SMiklos Szeredi case FUSE_CREATE: 43621f62174SMiklos Szeredi case FUSE_MKNOD: 43721f62174SMiklos Szeredi case FUSE_MKDIR: 43821f62174SMiklos Szeredi case FUSE_SYMLINK: 43921f62174SMiklos Szeredi case FUSE_LINK: 440d5b48543SMiklos Szeredi args->out_args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE; 44121f62174SMiklos Szeredi break; 44221f62174SMiklos Szeredi case FUSE_GETATTR: 44321f62174SMiklos Szeredi case FUSE_SETATTR: 444d5b48543SMiklos Szeredi args->out_args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE; 44521f62174SMiklos Szeredi break; 44621f62174SMiklos Szeredi } 44721f62174SMiklos Szeredi } 44821f62174SMiklos Szeredi if (fc->minor < 12) { 449d5b48543SMiklos Szeredi switch (args->opcode) { 45021f62174SMiklos Szeredi case FUSE_CREATE: 451d5b48543SMiklos Szeredi args->in_args[0].size = sizeof(struct fuse_open_in); 45221f62174SMiklos Szeredi break; 45321f62174SMiklos Szeredi case FUSE_MKNOD: 454d5b48543SMiklos Szeredi args->in_args[0].size = FUSE_COMPAT_MKNOD_IN_SIZE; 45521f62174SMiklos Szeredi break; 45621f62174SMiklos Szeredi } 45721f62174SMiklos Szeredi } 45821f62174SMiklos Szeredi } 45921f62174SMiklos Szeredi 460e413754bSMiklos Szeredi static void fuse_force_creds(struct fuse_conn *fc, struct fuse_req *req) 461e413754bSMiklos Szeredi { 462e413754bSMiklos Szeredi req->in.h.uid = from_kuid_munged(fc->user_ns, current_fsuid()); 463e413754bSMiklos Szeredi req->in.h.gid = from_kgid_munged(fc->user_ns, current_fsgid()); 464e413754bSMiklos Szeredi req->in.h.pid = pid_nr_ns(task_pid(current), fc->pid_ns); 465e413754bSMiklos Szeredi } 466e413754bSMiklos Szeredi 4675addcd5dSYueHaibing static void fuse_args_to_req(struct fuse_req *req, struct fuse_args *args) 46868583165SMiklos Szeredi { 46968583165SMiklos Szeredi req->in.h.opcode = args->opcode; 47068583165SMiklos Szeredi req->in.h.nodeid = args->nodeid; 471d4993774SMiklos Szeredi req->args = args; 47268583165SMiklos Szeredi } 47368583165SMiklos Szeredi 4747078187aSMiklos Szeredi ssize_t fuse_simple_request(struct fuse_conn *fc, struct fuse_args *args) 4757078187aSMiklos Szeredi { 4767078187aSMiklos Szeredi struct fuse_req *req; 4777078187aSMiklos Szeredi ssize_t ret; 4787078187aSMiklos Szeredi 479c500ebaaSMiklos Szeredi if (args->force) { 480e413754bSMiklos Szeredi atomic_inc(&fc->num_waiting); 4817213394cSMiklos Szeredi req = fuse_request_alloc(GFP_KERNEL | __GFP_NOFAIL); 482e413754bSMiklos Szeredi 483e413754bSMiklos Szeredi if (!args->nocreds) 484e413754bSMiklos Szeredi fuse_force_creds(fc, req); 485e413754bSMiklos Szeredi 486e413754bSMiklos Szeredi __set_bit(FR_WAITING, &req->flags); 487c500ebaaSMiklos Szeredi __set_bit(FR_FORCE, &req->flags); 488c500ebaaSMiklos Szeredi } else { 489e413754bSMiklos Szeredi WARN_ON(args->nocreds); 4907213394cSMiklos Szeredi req = fuse_get_req(fc, false); 4917078187aSMiklos Szeredi if (IS_ERR(req)) 4927078187aSMiklos Szeredi return PTR_ERR(req); 493c500ebaaSMiklos Szeredi } 4947078187aSMiklos Szeredi 49521f62174SMiklos Szeredi /* Needs to be done after fuse_get_req() so that fc->minor is valid */ 49621f62174SMiklos Szeredi fuse_adjust_compat(fc, args); 49768583165SMiklos Szeredi fuse_args_to_req(req, args); 49821f62174SMiklos Szeredi 499454a7613SMiklos Szeredi if (!args->noreply) 500454a7613SMiklos Szeredi __set_bit(FR_ISREPLY, &req->flags); 501454a7613SMiklos Szeredi __fuse_request_send(fc, req); 5027078187aSMiklos Szeredi ret = req->out.h.error; 503d5b48543SMiklos Szeredi if (!ret && args->out_argvar) { 504093f38a2SMiklos Szeredi BUG_ON(args->out_numargs == 0); 505d4993774SMiklos Szeredi ret = args->out_args[args->out_numargs - 1].size; 5067078187aSMiklos Szeredi } 5077078187aSMiklos Szeredi fuse_put_request(fc, req); 5087078187aSMiklos Szeredi 5097078187aSMiklos Szeredi return ret; 5107078187aSMiklos Szeredi } 5117078187aSMiklos Szeredi 51266abc359SMiklos Szeredi static bool fuse_request_queue_background(struct fuse_conn *fc, 51366abc359SMiklos Szeredi struct fuse_req *req) 514334f485dSMiklos Szeredi { 51563825b4eSKirill Tkhai bool queued = false; 51663825b4eSKirill Tkhai 51763825b4eSKirill Tkhai WARN_ON(!test_bit(FR_BACKGROUND, &req->flags)); 518825d6d33SMiklos Szeredi if (!test_bit(FR_WAITING, &req->flags)) { 519825d6d33SMiklos Szeredi __set_bit(FR_WAITING, &req->flags); 5205437f241SMiklos Szeredi atomic_inc(&fc->num_waiting); 5215437f241SMiklos Szeredi } 522825d6d33SMiklos Szeredi __set_bit(FR_ISREPLY, &req->flags); 523ae2dffa3SKirill Tkhai spin_lock(&fc->bg_lock); 52463825b4eSKirill Tkhai if (likely(fc->connected)) { 52551eb01e7SMiklos Szeredi fc->num_background++; 5267a6d3c8bSCsaba Henk if (fc->num_background == fc->max_background) 52751eb01e7SMiklos Szeredi fc->blocked = 1; 5287fbbe972SJan Kara if (fc->num_background == fc->congestion_threshold && fc->sb) { 5295f7f7543SJan Kara set_bdi_congested(fc->sb->s_bdi, BLK_RW_SYNC); 5305f7f7543SJan Kara set_bdi_congested(fc->sb->s_bdi, BLK_RW_ASYNC); 531f92b99b9SMiklos Szeredi } 532d12def1bSMiklos Szeredi list_add_tail(&req->list, &fc->bg_queue); 533d12def1bSMiklos Szeredi flush_bg_queue(fc); 53463825b4eSKirill Tkhai queued = true; 53563825b4eSKirill Tkhai } 536ae2dffa3SKirill Tkhai spin_unlock(&fc->bg_lock); 53763825b4eSKirill Tkhai 53863825b4eSKirill Tkhai return queued; 539d12def1bSMiklos Szeredi } 54051eb01e7SMiklos Szeredi 54112597287SMiklos Szeredi int fuse_simple_background(struct fuse_conn *fc, struct fuse_args *args, 54212597287SMiklos Szeredi gfp_t gfp_flags) 54312597287SMiklos Szeredi { 54412597287SMiklos Szeredi struct fuse_req *req; 54512597287SMiklos Szeredi 54612597287SMiklos Szeredi if (args->force) { 54712597287SMiklos Szeredi WARN_ON(!args->nocreds); 5487213394cSMiklos Szeredi req = fuse_request_alloc(gfp_flags); 54912597287SMiklos Szeredi if (!req) 55012597287SMiklos Szeredi return -ENOMEM; 55112597287SMiklos Szeredi __set_bit(FR_BACKGROUND, &req->flags); 55212597287SMiklos Szeredi } else { 55312597287SMiklos Szeredi WARN_ON(args->nocreds); 5547213394cSMiklos Szeredi req = fuse_get_req(fc, true); 55512597287SMiklos Szeredi if (IS_ERR(req)) 55612597287SMiklos Szeredi return PTR_ERR(req); 55712597287SMiklos Szeredi } 55812597287SMiklos Szeredi 55912597287SMiklos Szeredi fuse_args_to_req(req, args); 56012597287SMiklos Szeredi 56112597287SMiklos Szeredi if (!fuse_request_queue_background(fc, req)) { 56212597287SMiklos Szeredi fuse_put_request(fc, req); 56312597287SMiklos Szeredi return -ENOTCONN; 56412597287SMiklos Szeredi } 56512597287SMiklos Szeredi 56612597287SMiklos Szeredi return 0; 56712597287SMiklos Szeredi } 56812597287SMiklos Szeredi EXPORT_SYMBOL_GPL(fuse_simple_background); 56912597287SMiklos Szeredi 57075b399ddSMiklos Szeredi static int fuse_simple_notify_reply(struct fuse_conn *fc, 57175b399ddSMiklos Szeredi struct fuse_args *args, u64 unique) 5722d45ba38SMiklos Szeredi { 57375b399ddSMiklos Szeredi struct fuse_req *req; 574f88996a9SMiklos Szeredi struct fuse_iqueue *fiq = &fc->iq; 57575b399ddSMiklos Szeredi int err = 0; 57675b399ddSMiklos Szeredi 5777213394cSMiklos Szeredi req = fuse_get_req(fc, false); 57875b399ddSMiklos Szeredi if (IS_ERR(req)) 57975b399ddSMiklos Szeredi return PTR_ERR(req); 5802d45ba38SMiklos Szeredi 581825d6d33SMiklos Szeredi __clear_bit(FR_ISREPLY, &req->flags); 5822d45ba38SMiklos Szeredi req->in.h.unique = unique; 58375b399ddSMiklos Szeredi 58475b399ddSMiklos Szeredi fuse_args_to_req(req, args); 58575b399ddSMiklos Szeredi 58676e43c8cSEric Biggers spin_lock(&fiq->lock); 587e16714d8SMiklos Szeredi if (fiq->connected) { 588ae3aad77SStefan Hajnoczi queue_request_and_unlock(fiq, req); 58975b399ddSMiklos Szeredi } else { 59075b399ddSMiklos Szeredi err = -ENODEV; 59175b399ddSMiklos Szeredi spin_unlock(&fiq->lock); 59275b399ddSMiklos Szeredi fuse_put_request(fc, req); 5932d45ba38SMiklos Szeredi } 5942d45ba38SMiklos Szeredi 5952d45ba38SMiklos Szeredi return err; 5962d45ba38SMiklos Szeredi } 5972d45ba38SMiklos Szeredi 5983be5a52bSMiklos Szeredi /* 599334f485dSMiklos Szeredi * Lock the request. Up to the next unlock_request() there mustn't be 600334f485dSMiklos Szeredi * anything that could cause a page-fault. If the request was already 601f9a2842eSMiklos Szeredi * aborted bail out. 602334f485dSMiklos Szeredi */ 603dc00809aSMiklos Szeredi static int lock_request(struct fuse_req *req) 604334f485dSMiklos Szeredi { 605334f485dSMiklos Szeredi int err = 0; 606334f485dSMiklos Szeredi if (req) { 607dc00809aSMiklos Szeredi spin_lock(&req->waitq.lock); 608825d6d33SMiklos Szeredi if (test_bit(FR_ABORTED, &req->flags)) 609334f485dSMiklos Szeredi err = -ENOENT; 610334f485dSMiklos Szeredi else 611825d6d33SMiklos Szeredi set_bit(FR_LOCKED, &req->flags); 612dc00809aSMiklos Szeredi spin_unlock(&req->waitq.lock); 613334f485dSMiklos Szeredi } 614334f485dSMiklos Szeredi return err; 615334f485dSMiklos Szeredi } 616334f485dSMiklos Szeredi 617334f485dSMiklos Szeredi /* 6180d8e84b0SMiklos Szeredi * Unlock request. If it was aborted while locked, caller is responsible 6190d8e84b0SMiklos Szeredi * for unlocking and ending the request. 620334f485dSMiklos Szeredi */ 621dc00809aSMiklos Szeredi static int unlock_request(struct fuse_req *req) 622334f485dSMiklos Szeredi { 6230d8e84b0SMiklos Szeredi int err = 0; 624334f485dSMiklos Szeredi if (req) { 625dc00809aSMiklos Szeredi spin_lock(&req->waitq.lock); 626825d6d33SMiklos Szeredi if (test_bit(FR_ABORTED, &req->flags)) 6270d8e84b0SMiklos Szeredi err = -ENOENT; 6280d8e84b0SMiklos Szeredi else 629825d6d33SMiklos Szeredi clear_bit(FR_LOCKED, &req->flags); 630dc00809aSMiklos Szeredi spin_unlock(&req->waitq.lock); 631334f485dSMiklos Szeredi } 6320d8e84b0SMiklos Szeredi return err; 633334f485dSMiklos Szeredi } 634334f485dSMiklos Szeredi 635334f485dSMiklos Szeredi struct fuse_copy_state { 636334f485dSMiklos Szeredi int write; 637334f485dSMiklos Szeredi struct fuse_req *req; 6386c09e94aSAl Viro struct iov_iter *iter; 639dd3bb14fSMiklos Szeredi struct pipe_buffer *pipebufs; 640dd3bb14fSMiklos Szeredi struct pipe_buffer *currbuf; 641dd3bb14fSMiklos Szeredi struct pipe_inode_info *pipe; 642334f485dSMiklos Szeredi unsigned long nr_segs; 643334f485dSMiklos Szeredi struct page *pg; 644334f485dSMiklos Szeredi unsigned len; 645c55a01d3SMiklos Szeredi unsigned offset; 646ce534fb0SMiklos Szeredi unsigned move_pages:1; 647334f485dSMiklos Szeredi }; 648334f485dSMiklos Szeredi 649dc00809aSMiklos Szeredi static void fuse_copy_init(struct fuse_copy_state *cs, int write, 6506c09e94aSAl Viro struct iov_iter *iter) 651334f485dSMiklos Szeredi { 652334f485dSMiklos Szeredi memset(cs, 0, sizeof(*cs)); 653334f485dSMiklos Szeredi cs->write = write; 6546c09e94aSAl Viro cs->iter = iter; 655334f485dSMiklos Szeredi } 656334f485dSMiklos Szeredi 657334f485dSMiklos Szeredi /* Unmap and put previous page of userspace buffer */ 6588bfc016dSMiklos Szeredi static void fuse_copy_finish(struct fuse_copy_state *cs) 659334f485dSMiklos Szeredi { 660dd3bb14fSMiklos Szeredi if (cs->currbuf) { 661dd3bb14fSMiklos Szeredi struct pipe_buffer *buf = cs->currbuf; 662dd3bb14fSMiklos Szeredi 663c55a01d3SMiklos Szeredi if (cs->write) 664c3021629SMiklos Szeredi buf->len = PAGE_SIZE - cs->len; 665dd3bb14fSMiklos Szeredi cs->currbuf = NULL; 666c55a01d3SMiklos Szeredi } else if (cs->pg) { 667334f485dSMiklos Szeredi if (cs->write) { 668334f485dSMiklos Szeredi flush_dcache_page(cs->pg); 669334f485dSMiklos Szeredi set_page_dirty_lock(cs->pg); 670334f485dSMiklos Szeredi } 671334f485dSMiklos Szeredi put_page(cs->pg); 672334f485dSMiklos Szeredi } 673c55a01d3SMiklos Szeredi cs->pg = NULL; 674334f485dSMiklos Szeredi } 675334f485dSMiklos Szeredi 676334f485dSMiklos Szeredi /* 677334f485dSMiklos Szeredi * Get another pagefull of userspace buffer, and map it to kernel 678334f485dSMiklos Szeredi * address space, and lock request 679334f485dSMiklos Szeredi */ 680334f485dSMiklos Szeredi static int fuse_copy_fill(struct fuse_copy_state *cs) 681334f485dSMiklos Szeredi { 682c55a01d3SMiklos Szeredi struct page *page; 683334f485dSMiklos Szeredi int err; 684334f485dSMiklos Szeredi 685dc00809aSMiklos Szeredi err = unlock_request(cs->req); 6860d8e84b0SMiklos Szeredi if (err) 6870d8e84b0SMiklos Szeredi return err; 6880d8e84b0SMiklos Szeredi 689334f485dSMiklos Szeredi fuse_copy_finish(cs); 690dd3bb14fSMiklos Szeredi if (cs->pipebufs) { 691dd3bb14fSMiklos Szeredi struct pipe_buffer *buf = cs->pipebufs; 692dd3bb14fSMiklos Szeredi 693c3021629SMiklos Szeredi if (!cs->write) { 694fba597dbSMiklos Szeredi err = pipe_buf_confirm(cs->pipe, buf); 695dd3bb14fSMiklos Szeredi if (err) 696dd3bb14fSMiklos Szeredi return err; 697dd3bb14fSMiklos Szeredi 698dd3bb14fSMiklos Szeredi BUG_ON(!cs->nr_segs); 699dd3bb14fSMiklos Szeredi cs->currbuf = buf; 700c55a01d3SMiklos Szeredi cs->pg = buf->page; 701c55a01d3SMiklos Szeredi cs->offset = buf->offset; 702dd3bb14fSMiklos Szeredi cs->len = buf->len; 703dd3bb14fSMiklos Szeredi cs->pipebufs++; 704dd3bb14fSMiklos Szeredi cs->nr_segs--; 705dd3bb14fSMiklos Szeredi } else { 706c3021629SMiklos Szeredi if (cs->nr_segs == cs->pipe->buffers) 707c3021629SMiklos Szeredi return -EIO; 708c3021629SMiklos Szeredi 709c3021629SMiklos Szeredi page = alloc_page(GFP_HIGHUSER); 710c3021629SMiklos Szeredi if (!page) 711c3021629SMiklos Szeredi return -ENOMEM; 712c3021629SMiklos Szeredi 713c3021629SMiklos Szeredi buf->page = page; 714c3021629SMiklos Szeredi buf->offset = 0; 715c3021629SMiklos Szeredi buf->len = 0; 716c3021629SMiklos Szeredi 717c3021629SMiklos Szeredi cs->currbuf = buf; 718c55a01d3SMiklos Szeredi cs->pg = page; 719c55a01d3SMiklos Szeredi cs->offset = 0; 720c3021629SMiklos Szeredi cs->len = PAGE_SIZE; 721c3021629SMiklos Szeredi cs->pipebufs++; 722c3021629SMiklos Szeredi cs->nr_segs++; 723c3021629SMiklos Szeredi } 724c3021629SMiklos Szeredi } else { 7256c09e94aSAl Viro size_t off; 7266c09e94aSAl Viro err = iov_iter_get_pages(cs->iter, &page, PAGE_SIZE, 1, &off); 727334f485dSMiklos Szeredi if (err < 0) 728334f485dSMiklos Szeredi return err; 7296c09e94aSAl Viro BUG_ON(!err); 7306c09e94aSAl Viro cs->len = err; 7316c09e94aSAl Viro cs->offset = off; 732c55a01d3SMiklos Szeredi cs->pg = page; 7336c09e94aSAl Viro iov_iter_advance(cs->iter, err); 734dd3bb14fSMiklos Szeredi } 735334f485dSMiklos Szeredi 736dc00809aSMiklos Szeredi return lock_request(cs->req); 737334f485dSMiklos Szeredi } 738334f485dSMiklos Szeredi 739334f485dSMiklos Szeredi /* Do as much copy to/from userspace buffer as we can */ 7408bfc016dSMiklos Szeredi static int fuse_copy_do(struct fuse_copy_state *cs, void **val, unsigned *size) 741334f485dSMiklos Szeredi { 742334f485dSMiklos Szeredi unsigned ncpy = min(*size, cs->len); 743334f485dSMiklos Szeredi if (val) { 744c55a01d3SMiklos Szeredi void *pgaddr = kmap_atomic(cs->pg); 745c55a01d3SMiklos Szeredi void *buf = pgaddr + cs->offset; 746c55a01d3SMiklos Szeredi 747334f485dSMiklos Szeredi if (cs->write) 748c55a01d3SMiklos Szeredi memcpy(buf, *val, ncpy); 749334f485dSMiklos Szeredi else 750c55a01d3SMiklos Szeredi memcpy(*val, buf, ncpy); 751c55a01d3SMiklos Szeredi 752c55a01d3SMiklos Szeredi kunmap_atomic(pgaddr); 753334f485dSMiklos Szeredi *val += ncpy; 754334f485dSMiklos Szeredi } 755334f485dSMiklos Szeredi *size -= ncpy; 756334f485dSMiklos Szeredi cs->len -= ncpy; 757c55a01d3SMiklos Szeredi cs->offset += ncpy; 758334f485dSMiklos Szeredi return ncpy; 759334f485dSMiklos Szeredi } 760334f485dSMiklos Szeredi 761ce534fb0SMiklos Szeredi static int fuse_check_page(struct page *page) 762ce534fb0SMiklos Szeredi { 763ce534fb0SMiklos Szeredi if (page_mapcount(page) || 764ce534fb0SMiklos Szeredi page->mapping != NULL || 765ce534fb0SMiklos Szeredi page_count(page) != 1 || 766ce534fb0SMiklos Szeredi (page->flags & PAGE_FLAGS_CHECK_AT_PREP & 767ce534fb0SMiklos Szeredi ~(1 << PG_locked | 768ce534fb0SMiklos Szeredi 1 << PG_referenced | 769ce534fb0SMiklos Szeredi 1 << PG_uptodate | 770ce534fb0SMiklos Szeredi 1 << PG_lru | 771ce534fb0SMiklos Szeredi 1 << PG_active | 772ce534fb0SMiklos Szeredi 1 << PG_reclaim))) { 773f2294482SKirill Smelkov pr_warn("trying to steal weird page\n"); 774f2294482SKirill Smelkov pr_warn(" page=%p index=%li flags=%08lx, count=%i, mapcount=%i, mapping=%p\n", page, page->index, page->flags, page_count(page), page_mapcount(page), page->mapping); 775ce534fb0SMiklos Szeredi return 1; 776ce534fb0SMiklos Szeredi } 777ce534fb0SMiklos Szeredi return 0; 778ce534fb0SMiklos Szeredi } 779ce534fb0SMiklos Szeredi 780ce534fb0SMiklos Szeredi static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep) 781ce534fb0SMiklos Szeredi { 782ce534fb0SMiklos Szeredi int err; 783ce534fb0SMiklos Szeredi struct page *oldpage = *pagep; 784ce534fb0SMiklos Szeredi struct page *newpage; 785ce534fb0SMiklos Szeredi struct pipe_buffer *buf = cs->pipebufs; 786ce534fb0SMiklos Szeredi 787dc00809aSMiklos Szeredi err = unlock_request(cs->req); 7880d8e84b0SMiklos Szeredi if (err) 7890d8e84b0SMiklos Szeredi return err; 7900d8e84b0SMiklos Szeredi 791ce534fb0SMiklos Szeredi fuse_copy_finish(cs); 792ce534fb0SMiklos Szeredi 793fba597dbSMiklos Szeredi err = pipe_buf_confirm(cs->pipe, buf); 794ce534fb0SMiklos Szeredi if (err) 795ce534fb0SMiklos Szeredi return err; 796ce534fb0SMiklos Szeredi 797ce534fb0SMiklos Szeredi BUG_ON(!cs->nr_segs); 798ce534fb0SMiklos Szeredi cs->currbuf = buf; 799ce534fb0SMiklos Szeredi cs->len = buf->len; 800ce534fb0SMiklos Szeredi cs->pipebufs++; 801ce534fb0SMiklos Szeredi cs->nr_segs--; 802ce534fb0SMiklos Szeredi 803ce534fb0SMiklos Szeredi if (cs->len != PAGE_SIZE) 804ce534fb0SMiklos Szeredi goto out_fallback; 805ce534fb0SMiklos Szeredi 806ca76f5b6SMiklos Szeredi if (pipe_buf_steal(cs->pipe, buf) != 0) 807ce534fb0SMiklos Szeredi goto out_fallback; 808ce534fb0SMiklos Szeredi 809ce534fb0SMiklos Szeredi newpage = buf->page; 810ce534fb0SMiklos Szeredi 811aa991b3bSMiklos Szeredi if (!PageUptodate(newpage)) 812aa991b3bSMiklos Szeredi SetPageUptodate(newpage); 813ce534fb0SMiklos Szeredi 814ce534fb0SMiklos Szeredi ClearPageMappedToDisk(newpage); 815ce534fb0SMiklos Szeredi 816ce534fb0SMiklos Szeredi if (fuse_check_page(newpage) != 0) 817ce534fb0SMiklos Szeredi goto out_fallback_unlock; 818ce534fb0SMiklos Szeredi 819ce534fb0SMiklos Szeredi /* 820ce534fb0SMiklos Szeredi * This is a new and locked page, it shouldn't be mapped or 821ce534fb0SMiklos Szeredi * have any special flags on it 822ce534fb0SMiklos Szeredi */ 823ce534fb0SMiklos Szeredi if (WARN_ON(page_mapped(oldpage))) 824ce534fb0SMiklos Szeredi goto out_fallback_unlock; 825ce534fb0SMiklos Szeredi if (WARN_ON(page_has_private(oldpage))) 826ce534fb0SMiklos Szeredi goto out_fallback_unlock; 827ce534fb0SMiklos Szeredi if (WARN_ON(PageDirty(oldpage) || PageWriteback(oldpage))) 828ce534fb0SMiklos Szeredi goto out_fallback_unlock; 829ce534fb0SMiklos Szeredi if (WARN_ON(PageMlocked(oldpage))) 830ce534fb0SMiklos Szeredi goto out_fallback_unlock; 831ce534fb0SMiklos Szeredi 832ef6a3c63SMiklos Szeredi err = replace_page_cache_page(oldpage, newpage, GFP_KERNEL); 833ce534fb0SMiklos Szeredi if (err) { 834ef6a3c63SMiklos Szeredi unlock_page(newpage); 835ef6a3c63SMiklos Szeredi return err; 836ce534fb0SMiklos Szeredi } 837ef6a3c63SMiklos Szeredi 83809cbfeafSKirill A. Shutemov get_page(newpage); 839ce534fb0SMiklos Szeredi 840ce534fb0SMiklos Szeredi if (!(buf->flags & PIPE_BUF_FLAG_LRU)) 841ce534fb0SMiklos Szeredi lru_cache_add_file(newpage); 842ce534fb0SMiklos Szeredi 843ce534fb0SMiklos Szeredi err = 0; 844dc00809aSMiklos Szeredi spin_lock(&cs->req->waitq.lock); 845825d6d33SMiklos Szeredi if (test_bit(FR_ABORTED, &cs->req->flags)) 846ce534fb0SMiklos Szeredi err = -ENOENT; 847ce534fb0SMiklos Szeredi else 848ce534fb0SMiklos Szeredi *pagep = newpage; 849dc00809aSMiklos Szeredi spin_unlock(&cs->req->waitq.lock); 850ce534fb0SMiklos Szeredi 851ce534fb0SMiklos Szeredi if (err) { 852ce534fb0SMiklos Szeredi unlock_page(newpage); 85309cbfeafSKirill A. Shutemov put_page(newpage); 854ce534fb0SMiklos Szeredi return err; 855ce534fb0SMiklos Szeredi } 856ce534fb0SMiklos Szeredi 857ce534fb0SMiklos Szeredi unlock_page(oldpage); 85809cbfeafSKirill A. Shutemov put_page(oldpage); 859ce534fb0SMiklos Szeredi cs->len = 0; 860ce534fb0SMiklos Szeredi 861ce534fb0SMiklos Szeredi return 0; 862ce534fb0SMiklos Szeredi 863ce534fb0SMiklos Szeredi out_fallback_unlock: 864ce534fb0SMiklos Szeredi unlock_page(newpage); 865ce534fb0SMiklos Szeredi out_fallback: 866c55a01d3SMiklos Szeredi cs->pg = buf->page; 867c55a01d3SMiklos Szeredi cs->offset = buf->offset; 868ce534fb0SMiklos Szeredi 869dc00809aSMiklos Szeredi err = lock_request(cs->req); 870ce534fb0SMiklos Szeredi if (err) 871ce534fb0SMiklos Szeredi return err; 872ce534fb0SMiklos Szeredi 873ce534fb0SMiklos Szeredi return 1; 874ce534fb0SMiklos Szeredi } 875ce534fb0SMiklos Szeredi 876c3021629SMiklos Szeredi static int fuse_ref_page(struct fuse_copy_state *cs, struct page *page, 877c3021629SMiklos Szeredi unsigned offset, unsigned count) 878c3021629SMiklos Szeredi { 879c3021629SMiklos Szeredi struct pipe_buffer *buf; 8800d8e84b0SMiklos Szeredi int err; 881c3021629SMiklos Szeredi 882c3021629SMiklos Szeredi if (cs->nr_segs == cs->pipe->buffers) 883c3021629SMiklos Szeredi return -EIO; 884c3021629SMiklos Szeredi 885dc00809aSMiklos Szeredi err = unlock_request(cs->req); 8860d8e84b0SMiklos Szeredi if (err) 8870d8e84b0SMiklos Szeredi return err; 8880d8e84b0SMiklos Szeredi 889c3021629SMiklos Szeredi fuse_copy_finish(cs); 890c3021629SMiklos Szeredi 891c3021629SMiklos Szeredi buf = cs->pipebufs; 89209cbfeafSKirill A. Shutemov get_page(page); 893c3021629SMiklos Szeredi buf->page = page; 894c3021629SMiklos Szeredi buf->offset = offset; 895c3021629SMiklos Szeredi buf->len = count; 896c3021629SMiklos Szeredi 897c3021629SMiklos Szeredi cs->pipebufs++; 898c3021629SMiklos Szeredi cs->nr_segs++; 899c3021629SMiklos Szeredi cs->len = 0; 900c3021629SMiklos Szeredi 901c3021629SMiklos Szeredi return 0; 902c3021629SMiklos Szeredi } 903c3021629SMiklos Szeredi 904334f485dSMiklos Szeredi /* 905334f485dSMiklos Szeredi * Copy a page in the request to/from the userspace buffer. Must be 906334f485dSMiklos Szeredi * done atomically 907334f485dSMiklos Szeredi */ 908ce534fb0SMiklos Szeredi static int fuse_copy_page(struct fuse_copy_state *cs, struct page **pagep, 909334f485dSMiklos Szeredi unsigned offset, unsigned count, int zeroing) 910334f485dSMiklos Szeredi { 911ce534fb0SMiklos Szeredi int err; 912ce534fb0SMiklos Szeredi struct page *page = *pagep; 913ce534fb0SMiklos Szeredi 914b6777c40SMiklos Szeredi if (page && zeroing && count < PAGE_SIZE) 915b6777c40SMiklos Szeredi clear_highpage(page); 916b6777c40SMiklos Szeredi 917334f485dSMiklos Szeredi while (count) { 918c3021629SMiklos Szeredi if (cs->write && cs->pipebufs && page) { 919c3021629SMiklos Szeredi return fuse_ref_page(cs, page, offset, count); 920c3021629SMiklos Szeredi } else if (!cs->len) { 921ce534fb0SMiklos Szeredi if (cs->move_pages && page && 922ce534fb0SMiklos Szeredi offset == 0 && count == PAGE_SIZE) { 923ce534fb0SMiklos Szeredi err = fuse_try_move_page(cs, pagep); 924ce534fb0SMiklos Szeredi if (err <= 0) 925ce534fb0SMiklos Szeredi return err; 926ce534fb0SMiklos Szeredi } else { 927ce534fb0SMiklos Szeredi err = fuse_copy_fill(cs); 9281729a16cSMiklos Szeredi if (err) 929334f485dSMiklos Szeredi return err; 9301729a16cSMiklos Szeredi } 931ce534fb0SMiklos Szeredi } 932334f485dSMiklos Szeredi if (page) { 9332408f6efSCong Wang void *mapaddr = kmap_atomic(page); 934334f485dSMiklos Szeredi void *buf = mapaddr + offset; 935334f485dSMiklos Szeredi offset += fuse_copy_do(cs, &buf, &count); 9362408f6efSCong Wang kunmap_atomic(mapaddr); 937334f485dSMiklos Szeredi } else 938334f485dSMiklos Szeredi offset += fuse_copy_do(cs, NULL, &count); 939334f485dSMiklos Szeredi } 940334f485dSMiklos Szeredi if (page && !cs->write) 941334f485dSMiklos Szeredi flush_dcache_page(page); 942334f485dSMiklos Szeredi return 0; 943334f485dSMiklos Szeredi } 944334f485dSMiklos Szeredi 945334f485dSMiklos Szeredi /* Copy pages in the request to/from userspace buffer */ 946334f485dSMiklos Szeredi static int fuse_copy_pages(struct fuse_copy_state *cs, unsigned nbytes, 947334f485dSMiklos Szeredi int zeroing) 948334f485dSMiklos Szeredi { 949334f485dSMiklos Szeredi unsigned i; 950334f485dSMiklos Szeredi struct fuse_req *req = cs->req; 95105ea48ccSMiklos Szeredi struct fuse_args_pages *ap = container_of(req->args, typeof(*ap), args); 952334f485dSMiklos Szeredi 95305ea48ccSMiklos Szeredi 95405ea48ccSMiklos Szeredi for (i = 0; i < ap->num_pages && (nbytes || zeroing); i++) { 955ce534fb0SMiklos Szeredi int err; 95605ea48ccSMiklos Szeredi unsigned int offset = ap->descs[i].offset; 95705ea48ccSMiklos Szeredi unsigned int count = min(nbytes, ap->descs[i].length); 958ce534fb0SMiklos Szeredi 95905ea48ccSMiklos Szeredi err = fuse_copy_page(cs, &ap->pages[i], offset, count, zeroing); 960334f485dSMiklos Szeredi if (err) 961334f485dSMiklos Szeredi return err; 962334f485dSMiklos Szeredi 963334f485dSMiklos Szeredi nbytes -= count; 964334f485dSMiklos Szeredi } 965334f485dSMiklos Szeredi return 0; 966334f485dSMiklos Szeredi } 967334f485dSMiklos Szeredi 968334f485dSMiklos Szeredi /* Copy a single argument in the request to/from userspace buffer */ 969334f485dSMiklos Szeredi static int fuse_copy_one(struct fuse_copy_state *cs, void *val, unsigned size) 970334f485dSMiklos Szeredi { 971334f485dSMiklos Szeredi while (size) { 9721729a16cSMiklos Szeredi if (!cs->len) { 9731729a16cSMiklos Szeredi int err = fuse_copy_fill(cs); 9741729a16cSMiklos Szeredi if (err) 975334f485dSMiklos Szeredi return err; 9761729a16cSMiklos Szeredi } 977334f485dSMiklos Szeredi fuse_copy_do(cs, &val, &size); 978334f485dSMiklos Szeredi } 979334f485dSMiklos Szeredi return 0; 980334f485dSMiklos Szeredi } 981334f485dSMiklos Szeredi 982334f485dSMiklos Szeredi /* Copy request arguments to/from userspace buffer */ 983334f485dSMiklos Szeredi static int fuse_copy_args(struct fuse_copy_state *cs, unsigned numargs, 984334f485dSMiklos Szeredi unsigned argpages, struct fuse_arg *args, 985334f485dSMiklos Szeredi int zeroing) 986334f485dSMiklos Szeredi { 987334f485dSMiklos Szeredi int err = 0; 988334f485dSMiklos Szeredi unsigned i; 989334f485dSMiklos Szeredi 990334f485dSMiklos Szeredi for (i = 0; !err && i < numargs; i++) { 991334f485dSMiklos Szeredi struct fuse_arg *arg = &args[i]; 992334f485dSMiklos Szeredi if (i == numargs - 1 && argpages) 993334f485dSMiklos Szeredi err = fuse_copy_pages(cs, arg->size, zeroing); 994334f485dSMiklos Szeredi else 995334f485dSMiklos Szeredi err = fuse_copy_one(cs, arg->value, arg->size); 996334f485dSMiklos Szeredi } 997334f485dSMiklos Szeredi return err; 998334f485dSMiklos Szeredi } 999334f485dSMiklos Szeredi 1000f88996a9SMiklos Szeredi static int forget_pending(struct fuse_iqueue *fiq) 100107e77dcaSMiklos Szeredi { 1002f88996a9SMiklos Szeredi return fiq->forget_list_head.next != NULL; 100307e77dcaSMiklos Szeredi } 100407e77dcaSMiklos Szeredi 1005f88996a9SMiklos Szeredi static int request_pending(struct fuse_iqueue *fiq) 1006a4d27e75SMiklos Szeredi { 1007f88996a9SMiklos Szeredi return !list_empty(&fiq->pending) || !list_empty(&fiq->interrupts) || 1008f88996a9SMiklos Szeredi forget_pending(fiq); 1009a4d27e75SMiklos Szeredi } 1010a4d27e75SMiklos Szeredi 1011334f485dSMiklos Szeredi /* 1012a4d27e75SMiklos Szeredi * Transfer an interrupt request to userspace 1013a4d27e75SMiklos Szeredi * 1014a4d27e75SMiklos Szeredi * Unlike other requests this is assembled on demand, without a need 1015a4d27e75SMiklos Szeredi * to allocate a separate fuse_req structure. 1016a4d27e75SMiklos Szeredi * 101776e43c8cSEric Biggers * Called with fiq->lock held, releases it 1018a4d27e75SMiklos Szeredi */ 1019fd22d62eSMiklos Szeredi static int fuse_read_interrupt(struct fuse_iqueue *fiq, 1020fd22d62eSMiklos Szeredi struct fuse_copy_state *cs, 1021c3021629SMiklos Szeredi size_t nbytes, struct fuse_req *req) 102276e43c8cSEric Biggers __releases(fiq->lock) 1023a4d27e75SMiklos Szeredi { 1024a4d27e75SMiklos Szeredi struct fuse_in_header ih; 1025a4d27e75SMiklos Szeredi struct fuse_interrupt_in arg; 1026a4d27e75SMiklos Szeredi unsigned reqsize = sizeof(ih) + sizeof(arg); 1027a4d27e75SMiklos Szeredi int err; 1028a4d27e75SMiklos Szeredi 1029a4d27e75SMiklos Szeredi list_del_init(&req->intr_entry); 1030a4d27e75SMiklos Szeredi memset(&ih, 0, sizeof(ih)); 1031a4d27e75SMiklos Szeredi memset(&arg, 0, sizeof(arg)); 1032a4d27e75SMiklos Szeredi ih.len = reqsize; 1033a4d27e75SMiklos Szeredi ih.opcode = FUSE_INTERRUPT; 10343a5358d1SKirill Tkhai ih.unique = (req->in.h.unique | FUSE_INT_REQ_BIT); 1035a4d27e75SMiklos Szeredi arg.unique = req->in.h.unique; 1036a4d27e75SMiklos Szeredi 103776e43c8cSEric Biggers spin_unlock(&fiq->lock); 1038c3021629SMiklos Szeredi if (nbytes < reqsize) 1039a4d27e75SMiklos Szeredi return -EINVAL; 1040a4d27e75SMiklos Szeredi 1041c3021629SMiklos Szeredi err = fuse_copy_one(cs, &ih, sizeof(ih)); 1042a4d27e75SMiklos Szeredi if (!err) 1043c3021629SMiklos Szeredi err = fuse_copy_one(cs, &arg, sizeof(arg)); 1044c3021629SMiklos Szeredi fuse_copy_finish(cs); 1045a4d27e75SMiklos Szeredi 1046a4d27e75SMiklos Szeredi return err ? err : reqsize; 1047a4d27e75SMiklos Szeredi } 1048a4d27e75SMiklos Szeredi 10494388c5aaSVivek Goyal struct fuse_forget_link *fuse_dequeue_forget(struct fuse_iqueue *fiq, 10504388c5aaSVivek Goyal unsigned int max, 10514388c5aaSVivek Goyal unsigned int *countp) 105207e77dcaSMiklos Szeredi { 1053f88996a9SMiklos Szeredi struct fuse_forget_link *head = fiq->forget_list_head.next; 105402c048b9SMiklos Szeredi struct fuse_forget_link **newhead = &head; 105502c048b9SMiklos Szeredi unsigned count; 105607e77dcaSMiklos Szeredi 105702c048b9SMiklos Szeredi for (count = 0; *newhead != NULL && count < max; count++) 105802c048b9SMiklos Szeredi newhead = &(*newhead)->next; 105902c048b9SMiklos Szeredi 1060f88996a9SMiklos Szeredi fiq->forget_list_head.next = *newhead; 106102c048b9SMiklos Szeredi *newhead = NULL; 1062f88996a9SMiklos Szeredi if (fiq->forget_list_head.next == NULL) 1063f88996a9SMiklos Szeredi fiq->forget_list_tail = &fiq->forget_list_head; 106407e77dcaSMiklos Szeredi 106502c048b9SMiklos Szeredi if (countp != NULL) 106602c048b9SMiklos Szeredi *countp = count; 106702c048b9SMiklos Szeredi 106802c048b9SMiklos Szeredi return head; 106907e77dcaSMiklos Szeredi } 10704388c5aaSVivek Goyal EXPORT_SYMBOL(fuse_dequeue_forget); 107107e77dcaSMiklos Szeredi 1072fd22d62eSMiklos Szeredi static int fuse_read_single_forget(struct fuse_iqueue *fiq, 107307e77dcaSMiklos Szeredi struct fuse_copy_state *cs, 107407e77dcaSMiklos Szeredi size_t nbytes) 107576e43c8cSEric Biggers __releases(fiq->lock) 107607e77dcaSMiklos Szeredi { 107707e77dcaSMiklos Szeredi int err; 10784388c5aaSVivek Goyal struct fuse_forget_link *forget = fuse_dequeue_forget(fiq, 1, NULL); 107907e77dcaSMiklos Szeredi struct fuse_forget_in arg = { 108002c048b9SMiklos Szeredi .nlookup = forget->forget_one.nlookup, 108107e77dcaSMiklos Szeredi }; 108207e77dcaSMiklos Szeredi struct fuse_in_header ih = { 108307e77dcaSMiklos Szeredi .opcode = FUSE_FORGET, 108402c048b9SMiklos Szeredi .nodeid = forget->forget_one.nodeid, 1085f88996a9SMiklos Szeredi .unique = fuse_get_unique(fiq), 108607e77dcaSMiklos Szeredi .len = sizeof(ih) + sizeof(arg), 108707e77dcaSMiklos Szeredi }; 108807e77dcaSMiklos Szeredi 108976e43c8cSEric Biggers spin_unlock(&fiq->lock); 109007e77dcaSMiklos Szeredi kfree(forget); 109107e77dcaSMiklos Szeredi if (nbytes < ih.len) 109207e77dcaSMiklos Szeredi return -EINVAL; 109307e77dcaSMiklos Szeredi 109407e77dcaSMiklos Szeredi err = fuse_copy_one(cs, &ih, sizeof(ih)); 109507e77dcaSMiklos Szeredi if (!err) 109607e77dcaSMiklos Szeredi err = fuse_copy_one(cs, &arg, sizeof(arg)); 109707e77dcaSMiklos Szeredi fuse_copy_finish(cs); 109807e77dcaSMiklos Szeredi 109907e77dcaSMiklos Szeredi if (err) 110007e77dcaSMiklos Szeredi return err; 110107e77dcaSMiklos Szeredi 110207e77dcaSMiklos Szeredi return ih.len; 110307e77dcaSMiklos Szeredi } 110407e77dcaSMiklos Szeredi 1105fd22d62eSMiklos Szeredi static int fuse_read_batch_forget(struct fuse_iqueue *fiq, 110602c048b9SMiklos Szeredi struct fuse_copy_state *cs, size_t nbytes) 110776e43c8cSEric Biggers __releases(fiq->lock) 110802c048b9SMiklos Szeredi { 110902c048b9SMiklos Szeredi int err; 111002c048b9SMiklos Szeredi unsigned max_forgets; 111102c048b9SMiklos Szeredi unsigned count; 111202c048b9SMiklos Szeredi struct fuse_forget_link *head; 111302c048b9SMiklos Szeredi struct fuse_batch_forget_in arg = { .count = 0 }; 111402c048b9SMiklos Szeredi struct fuse_in_header ih = { 111502c048b9SMiklos Szeredi .opcode = FUSE_BATCH_FORGET, 1116f88996a9SMiklos Szeredi .unique = fuse_get_unique(fiq), 111702c048b9SMiklos Szeredi .len = sizeof(ih) + sizeof(arg), 111802c048b9SMiklos Szeredi }; 111902c048b9SMiklos Szeredi 112002c048b9SMiklos Szeredi if (nbytes < ih.len) { 112176e43c8cSEric Biggers spin_unlock(&fiq->lock); 112202c048b9SMiklos Szeredi return -EINVAL; 112302c048b9SMiklos Szeredi } 112402c048b9SMiklos Szeredi 112502c048b9SMiklos Szeredi max_forgets = (nbytes - ih.len) / sizeof(struct fuse_forget_one); 11264388c5aaSVivek Goyal head = fuse_dequeue_forget(fiq, max_forgets, &count); 112776e43c8cSEric Biggers spin_unlock(&fiq->lock); 112802c048b9SMiklos Szeredi 112902c048b9SMiklos Szeredi arg.count = count; 113002c048b9SMiklos Szeredi ih.len += count * sizeof(struct fuse_forget_one); 113102c048b9SMiklos Szeredi err = fuse_copy_one(cs, &ih, sizeof(ih)); 113202c048b9SMiklos Szeredi if (!err) 113302c048b9SMiklos Szeredi err = fuse_copy_one(cs, &arg, sizeof(arg)); 113402c048b9SMiklos Szeredi 113502c048b9SMiklos Szeredi while (head) { 113602c048b9SMiklos Szeredi struct fuse_forget_link *forget = head; 113702c048b9SMiklos Szeredi 113802c048b9SMiklos Szeredi if (!err) { 113902c048b9SMiklos Szeredi err = fuse_copy_one(cs, &forget->forget_one, 114002c048b9SMiklos Szeredi sizeof(forget->forget_one)); 114102c048b9SMiklos Szeredi } 114202c048b9SMiklos Szeredi head = forget->next; 114302c048b9SMiklos Szeredi kfree(forget); 114402c048b9SMiklos Szeredi } 114502c048b9SMiklos Szeredi 114602c048b9SMiklos Szeredi fuse_copy_finish(cs); 114702c048b9SMiklos Szeredi 114802c048b9SMiklos Szeredi if (err) 114902c048b9SMiklos Szeredi return err; 115002c048b9SMiklos Szeredi 115102c048b9SMiklos Szeredi return ih.len; 115202c048b9SMiklos Szeredi } 115302c048b9SMiklos Szeredi 1154fd22d62eSMiklos Szeredi static int fuse_read_forget(struct fuse_conn *fc, struct fuse_iqueue *fiq, 1155fd22d62eSMiklos Szeredi struct fuse_copy_state *cs, 115602c048b9SMiklos Szeredi size_t nbytes) 115776e43c8cSEric Biggers __releases(fiq->lock) 115802c048b9SMiklos Szeredi { 1159f88996a9SMiklos Szeredi if (fc->minor < 16 || fiq->forget_list_head.next->next == NULL) 1160fd22d62eSMiklos Szeredi return fuse_read_single_forget(fiq, cs, nbytes); 116102c048b9SMiklos Szeredi else 1162fd22d62eSMiklos Szeredi return fuse_read_batch_forget(fiq, cs, nbytes); 116302c048b9SMiklos Szeredi } 116402c048b9SMiklos Szeredi 1165a4d27e75SMiklos Szeredi /* 1166334f485dSMiklos Szeredi * Read a single request into the userspace filesystem's buffer. This 1167334f485dSMiklos Szeredi * function waits until a request is available, then removes it from 1168334f485dSMiklos Szeredi * the pending list and copies request data to userspace buffer. If 1169f9a2842eSMiklos Szeredi * no reply is needed (FORGET) or request has been aborted or there 1170f9a2842eSMiklos Szeredi * was an error during the copying then it's finished by calling 117104ec5af0SStefan Hajnoczi * fuse_request_end(). Otherwise add it to the processing list, and set 1172334f485dSMiklos Szeredi * the 'sent' flag. 1173334f485dSMiklos Szeredi */ 1174c3696046SMiklos Szeredi static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file, 1175c3021629SMiklos Szeredi struct fuse_copy_state *cs, size_t nbytes) 1176334f485dSMiklos Szeredi { 117782cbdcd3SMiklos Szeredi ssize_t err; 1178c3696046SMiklos Szeredi struct fuse_conn *fc = fud->fc; 1179f88996a9SMiklos Szeredi struct fuse_iqueue *fiq = &fc->iq; 1180c3696046SMiklos Szeredi struct fuse_pqueue *fpq = &fud->pq; 1181334f485dSMiklos Szeredi struct fuse_req *req; 1182d4993774SMiklos Szeredi struct fuse_args *args; 1183334f485dSMiklos Szeredi unsigned reqsize; 1184be2ff42cSKirill Tkhai unsigned int hash; 1185334f485dSMiklos Szeredi 11861fb027d7SKirill Smelkov /* 11871fb027d7SKirill Smelkov * Require sane minimum read buffer - that has capacity for fixed part 11881fb027d7SKirill Smelkov * of any request header + negotiated max_write room for data. 11891fb027d7SKirill Smelkov * 11901fb027d7SKirill Smelkov * Historically libfuse reserves 4K for fixed header room, but e.g. 11911fb027d7SKirill Smelkov * GlusterFS reserves only 80 bytes 11921fb027d7SKirill Smelkov * 11931fb027d7SKirill Smelkov * = `sizeof(fuse_in_header) + sizeof(fuse_write_in)` 11941fb027d7SKirill Smelkov * 11951fb027d7SKirill Smelkov * which is the absolute minimum any sane filesystem should be using 11961fb027d7SKirill Smelkov * for header room. 11971fb027d7SKirill Smelkov */ 11981fb027d7SKirill Smelkov if (nbytes < max_t(size_t, FUSE_MIN_READ_BUFFER, 11991fb027d7SKirill Smelkov sizeof(struct fuse_in_header) + 12001fb027d7SKirill Smelkov sizeof(struct fuse_write_in) + 12011fb027d7SKirill Smelkov fc->max_write)) 12021fb027d7SKirill Smelkov return -EINVAL; 12031fb027d7SKirill Smelkov 12041d3d752bSMiklos Szeredi restart: 120576e43c8cSEric Biggers for (;;) { 120676e43c8cSEric Biggers spin_lock(&fiq->lock); 120776e43c8cSEric Biggers if (!fiq->connected || request_pending(fiq)) 120876e43c8cSEric Biggers break; 120976e43c8cSEric Biggers spin_unlock(&fiq->lock); 1210e5ac1d1eSJeff Dike 121176e43c8cSEric Biggers if (file->f_flags & O_NONBLOCK) 121276e43c8cSEric Biggers return -EAGAIN; 121376e43c8cSEric Biggers err = wait_event_interruptible_exclusive(fiq->waitq, 12145250921bSMiklos Szeredi !fiq->connected || request_pending(fiq)); 12155250921bSMiklos Szeredi if (err) 121676e43c8cSEric Biggers return err; 121776e43c8cSEric Biggers } 12185250921bSMiklos Szeredi 12193b7008b2SSzymon Lukasz if (!fiq->connected) { 1220eb98e3bdSMiklos Szeredi err = fc->aborted ? -ECONNABORTED : -ENODEV; 1221334f485dSMiklos Szeredi goto err_unlock; 12223b7008b2SSzymon Lukasz } 1223334f485dSMiklos Szeredi 1224f88996a9SMiklos Szeredi if (!list_empty(&fiq->interrupts)) { 1225f88996a9SMiklos Szeredi req = list_entry(fiq->interrupts.next, struct fuse_req, 1226a4d27e75SMiklos Szeredi intr_entry); 1227fd22d62eSMiklos Szeredi return fuse_read_interrupt(fiq, cs, nbytes, req); 1228a4d27e75SMiklos Szeredi } 1229a4d27e75SMiklos Szeredi 1230f88996a9SMiklos Szeredi if (forget_pending(fiq)) { 1231f88996a9SMiklos Szeredi if (list_empty(&fiq->pending) || fiq->forget_batch-- > 0) 1232fd22d62eSMiklos Szeredi return fuse_read_forget(fc, fiq, cs, nbytes); 123307e77dcaSMiklos Szeredi 1234f88996a9SMiklos Szeredi if (fiq->forget_batch <= -8) 1235f88996a9SMiklos Szeredi fiq->forget_batch = 16; 123607e77dcaSMiklos Szeredi } 123707e77dcaSMiklos Szeredi 1238f88996a9SMiklos Szeredi req = list_entry(fiq->pending.next, struct fuse_req, list); 123933e14b4dSMiklos Szeredi clear_bit(FR_PENDING, &req->flags); 1240ef759258SMiklos Szeredi list_del_init(&req->list); 124176e43c8cSEric Biggers spin_unlock(&fiq->lock); 12424ce60812SMiklos Szeredi 1243d4993774SMiklos Szeredi args = req->args; 1244d4993774SMiklos Szeredi reqsize = req->in.h.len; 12455d6d3a30SMiklos Szeredi 12461d3d752bSMiklos Szeredi /* If request is too large, reply with an error and restart the read */ 1247c3021629SMiklos Szeredi if (nbytes < reqsize) { 12481d3d752bSMiklos Szeredi req->out.h.error = -EIO; 12491d3d752bSMiklos Szeredi /* SETXATTR is special, since it may contain too large data */ 1250d4993774SMiklos Szeredi if (args->opcode == FUSE_SETXATTR) 12511d3d752bSMiklos Szeredi req->out.h.error = -E2BIG; 125204ec5af0SStefan Hajnoczi fuse_request_end(fc, req); 12531d3d752bSMiklos Szeredi goto restart; 12541d3d752bSMiklos Szeredi } 125545a91cb1SMiklos Szeredi spin_lock(&fpq->lock); 125682cbdcd3SMiklos Szeredi list_add(&req->list, &fpq->io); 125745a91cb1SMiklos Szeredi spin_unlock(&fpq->lock); 1258c3021629SMiklos Szeredi cs->req = req; 1259d4993774SMiklos Szeredi err = fuse_copy_one(cs, &req->in.h, sizeof(req->in.h)); 1260334f485dSMiklos Szeredi if (!err) 1261d4993774SMiklos Szeredi err = fuse_copy_args(cs, args->in_numargs, args->in_pages, 1262d4993774SMiklos Szeredi (struct fuse_arg *) args->in_args, 0); 1263c3021629SMiklos Szeredi fuse_copy_finish(cs); 126445a91cb1SMiklos Szeredi spin_lock(&fpq->lock); 1265825d6d33SMiklos Szeredi clear_bit(FR_LOCKED, &req->flags); 1266e96edd94SMiklos Szeredi if (!fpq->connected) { 1267eb98e3bdSMiklos Szeredi err = fc->aborted ? -ECONNABORTED : -ENODEV; 126882cbdcd3SMiklos Szeredi goto out_end; 1269c9c9d7dfSMiklos Szeredi } 1270334f485dSMiklos Szeredi if (err) { 1271334f485dSMiklos Szeredi req->out.h.error = -EIO; 127282cbdcd3SMiklos Szeredi goto out_end; 1273334f485dSMiklos Szeredi } 1274825d6d33SMiklos Szeredi if (!test_bit(FR_ISREPLY, &req->flags)) { 127582cbdcd3SMiklos Szeredi err = reqsize; 127682cbdcd3SMiklos Szeredi goto out_end; 127782cbdcd3SMiklos Szeredi } 1278be2ff42cSKirill Tkhai hash = fuse_req_hash(req->in.h.unique); 1279be2ff42cSKirill Tkhai list_move_tail(&req->list, &fpq->processing[hash]); 1280bc78abbdSKirill Tkhai __fuse_get_request(req); 12818f7bb368SMiklos Szeredi set_bit(FR_SENT, &req->flags); 12824c316f2fSMiklos Szeredi spin_unlock(&fpq->lock); 12838f7bb368SMiklos Szeredi /* matches barrier in request_wait_answer() */ 12848f7bb368SMiklos Szeredi smp_mb__after_atomic(); 1285825d6d33SMiklos Szeredi if (test_bit(FR_INTERRUPTED, &req->flags)) 1286f88996a9SMiklos Szeredi queue_interrupt(fiq, req); 1287bc78abbdSKirill Tkhai fuse_put_request(fc, req); 128882cbdcd3SMiklos Szeredi 1289334f485dSMiklos Szeredi return reqsize; 1290334f485dSMiklos Szeredi 129182cbdcd3SMiklos Szeredi out_end: 129277cd9d48SMiklos Szeredi if (!test_bit(FR_PRIVATE, &req->flags)) 129382cbdcd3SMiklos Szeredi list_del_init(&req->list); 129445a91cb1SMiklos Szeredi spin_unlock(&fpq->lock); 129504ec5af0SStefan Hajnoczi fuse_request_end(fc, req); 129682cbdcd3SMiklos Szeredi return err; 129782cbdcd3SMiklos Szeredi 1298334f485dSMiklos Szeredi err_unlock: 129976e43c8cSEric Biggers spin_unlock(&fiq->lock); 1300334f485dSMiklos Szeredi return err; 1301334f485dSMiklos Szeredi } 1302334f485dSMiklos Szeredi 130394e4fe2cSTom Van Braeckel static int fuse_dev_open(struct inode *inode, struct file *file) 130494e4fe2cSTom Van Braeckel { 130594e4fe2cSTom Van Braeckel /* 130694e4fe2cSTom Van Braeckel * The fuse device's file's private_data is used to hold 130794e4fe2cSTom Van Braeckel * the fuse_conn(ection) when it is mounted, and is used to 130894e4fe2cSTom Van Braeckel * keep track of whether the file has been mounted already. 130994e4fe2cSTom Van Braeckel */ 131094e4fe2cSTom Van Braeckel file->private_data = NULL; 131194e4fe2cSTom Van Braeckel return 0; 131294e4fe2cSTom Van Braeckel } 131394e4fe2cSTom Van Braeckel 1314fbdbaccaSAl Viro static ssize_t fuse_dev_read(struct kiocb *iocb, struct iov_iter *to) 1315c3021629SMiklos Szeredi { 1316c3021629SMiklos Szeredi struct fuse_copy_state cs; 1317c3021629SMiklos Szeredi struct file *file = iocb->ki_filp; 1318cc080e9eSMiklos Szeredi struct fuse_dev *fud = fuse_get_dev(file); 1319cc080e9eSMiklos Szeredi 1320cc080e9eSMiklos Szeredi if (!fud) 1321c3021629SMiklos Szeredi return -EPERM; 1322c3021629SMiklos Szeredi 1323fbdbaccaSAl Viro if (!iter_is_iovec(to)) 1324fbdbaccaSAl Viro return -EINVAL; 1325c3021629SMiklos Szeredi 1326dc00809aSMiklos Szeredi fuse_copy_init(&cs, 1, to); 1327fbdbaccaSAl Viro 1328c3696046SMiklos Szeredi return fuse_dev_do_read(fud, file, &cs, iov_iter_count(to)); 1329c3021629SMiklos Szeredi } 1330c3021629SMiklos Szeredi 1331c3021629SMiklos Szeredi static ssize_t fuse_dev_splice_read(struct file *in, loff_t *ppos, 1332c3021629SMiklos Szeredi struct pipe_inode_info *pipe, 1333c3021629SMiklos Szeredi size_t len, unsigned int flags) 1334c3021629SMiklos Szeredi { 1335d82718e3SAl Viro int total, ret; 1336c3021629SMiklos Szeredi int page_nr = 0; 1337c3021629SMiklos Szeredi struct pipe_buffer *bufs; 1338c3021629SMiklos Szeredi struct fuse_copy_state cs; 1339cc080e9eSMiklos Szeredi struct fuse_dev *fud = fuse_get_dev(in); 1340cc080e9eSMiklos Szeredi 1341cc080e9eSMiklos Szeredi if (!fud) 1342c3021629SMiklos Szeredi return -EPERM; 1343c3021629SMiklos Szeredi 1344d6d931adSAndrey Ryabinin bufs = kvmalloc_array(pipe->buffers, sizeof(struct pipe_buffer), 13456da2ec56SKees Cook GFP_KERNEL); 1346c3021629SMiklos Szeredi if (!bufs) 1347c3021629SMiklos Szeredi return -ENOMEM; 1348c3021629SMiklos Szeredi 1349dc00809aSMiklos Szeredi fuse_copy_init(&cs, 1, NULL); 1350c3021629SMiklos Szeredi cs.pipebufs = bufs; 1351c3021629SMiklos Szeredi cs.pipe = pipe; 1352c3696046SMiklos Szeredi ret = fuse_dev_do_read(fud, in, &cs, len); 1353c3021629SMiklos Szeredi if (ret < 0) 1354c3021629SMiklos Szeredi goto out; 1355c3021629SMiklos Szeredi 1356c3021629SMiklos Szeredi if (pipe->nrbufs + cs.nr_segs > pipe->buffers) { 1357c3021629SMiklos Szeredi ret = -EIO; 1358d82718e3SAl Viro goto out; 1359c3021629SMiklos Szeredi } 1360c3021629SMiklos Szeredi 1361d82718e3SAl Viro for (ret = total = 0; page_nr < cs.nr_segs; total += ret) { 136228a625cbSMiklos Szeredi /* 136328a625cbSMiklos Szeredi * Need to be careful about this. Having buf->ops in module 136428a625cbSMiklos Szeredi * code can Oops if the buffer persists after module unload. 136528a625cbSMiklos Szeredi */ 1366d82718e3SAl Viro bufs[page_nr].ops = &nosteal_pipe_buf_ops; 136784588a93SMiklos Szeredi bufs[page_nr].flags = 0; 1368d82718e3SAl Viro ret = add_to_pipe(pipe, &bufs[page_nr++]); 1369d82718e3SAl Viro if (unlikely(ret < 0)) 1370d82718e3SAl Viro break; 1371c3021629SMiklos Szeredi } 1372d82718e3SAl Viro if (total) 1373d82718e3SAl Viro ret = total; 1374c3021629SMiklos Szeredi out: 1375c3021629SMiklos Szeredi for (; page_nr < cs.nr_segs; page_nr++) 137609cbfeafSKirill A. Shutemov put_page(bufs[page_nr].page); 1377c3021629SMiklos Szeredi 1378d6d931adSAndrey Ryabinin kvfree(bufs); 1379c3021629SMiklos Szeredi return ret; 1380c3021629SMiklos Szeredi } 1381c3021629SMiklos Szeredi 138295668a69STejun Heo static int fuse_notify_poll(struct fuse_conn *fc, unsigned int size, 138395668a69STejun Heo struct fuse_copy_state *cs) 138495668a69STejun Heo { 138595668a69STejun Heo struct fuse_notify_poll_wakeup_out outarg; 1386f6d47a17SMiklos Szeredi int err = -EINVAL; 138795668a69STejun Heo 138895668a69STejun Heo if (size != sizeof(outarg)) 1389f6d47a17SMiklos Szeredi goto err; 139095668a69STejun Heo 139195668a69STejun Heo err = fuse_copy_one(cs, &outarg, sizeof(outarg)); 139295668a69STejun Heo if (err) 1393f6d47a17SMiklos Szeredi goto err; 139495668a69STejun Heo 1395f6d47a17SMiklos Szeredi fuse_copy_finish(cs); 139695668a69STejun Heo return fuse_notify_poll_wakeup(fc, &outarg); 1397f6d47a17SMiklos Szeredi 1398f6d47a17SMiklos Szeredi err: 1399f6d47a17SMiklos Szeredi fuse_copy_finish(cs); 1400f6d47a17SMiklos Szeredi return err; 140195668a69STejun Heo } 140295668a69STejun Heo 14033b463ae0SJohn Muir static int fuse_notify_inval_inode(struct fuse_conn *fc, unsigned int size, 14043b463ae0SJohn Muir struct fuse_copy_state *cs) 14053b463ae0SJohn Muir { 14063b463ae0SJohn Muir struct fuse_notify_inval_inode_out outarg; 14073b463ae0SJohn Muir int err = -EINVAL; 14083b463ae0SJohn Muir 14093b463ae0SJohn Muir if (size != sizeof(outarg)) 14103b463ae0SJohn Muir goto err; 14113b463ae0SJohn Muir 14123b463ae0SJohn Muir err = fuse_copy_one(cs, &outarg, sizeof(outarg)); 14133b463ae0SJohn Muir if (err) 14143b463ae0SJohn Muir goto err; 14153b463ae0SJohn Muir fuse_copy_finish(cs); 14163b463ae0SJohn Muir 14173b463ae0SJohn Muir down_read(&fc->killsb); 14183b463ae0SJohn Muir err = -ENOENT; 1419b21dda43SMiklos Szeredi if (fc->sb) { 14203b463ae0SJohn Muir err = fuse_reverse_inval_inode(fc->sb, outarg.ino, 14213b463ae0SJohn Muir outarg.off, outarg.len); 1422b21dda43SMiklos Szeredi } 14233b463ae0SJohn Muir up_read(&fc->killsb); 14243b463ae0SJohn Muir return err; 14253b463ae0SJohn Muir 14263b463ae0SJohn Muir err: 14273b463ae0SJohn Muir fuse_copy_finish(cs); 14283b463ae0SJohn Muir return err; 14293b463ae0SJohn Muir } 14303b463ae0SJohn Muir 14313b463ae0SJohn Muir static int fuse_notify_inval_entry(struct fuse_conn *fc, unsigned int size, 14323b463ae0SJohn Muir struct fuse_copy_state *cs) 14333b463ae0SJohn Muir { 14343b463ae0SJohn Muir struct fuse_notify_inval_entry_out outarg; 1435b2d82ee3SFang Wenqi int err = -ENOMEM; 1436b2d82ee3SFang Wenqi char *buf; 14373b463ae0SJohn Muir struct qstr name; 14383b463ae0SJohn Muir 1439b2d82ee3SFang Wenqi buf = kzalloc(FUSE_NAME_MAX + 1, GFP_KERNEL); 1440b2d82ee3SFang Wenqi if (!buf) 1441b2d82ee3SFang Wenqi goto err; 1442b2d82ee3SFang Wenqi 1443b2d82ee3SFang Wenqi err = -EINVAL; 14443b463ae0SJohn Muir if (size < sizeof(outarg)) 14453b463ae0SJohn Muir goto err; 14463b463ae0SJohn Muir 14473b463ae0SJohn Muir err = fuse_copy_one(cs, &outarg, sizeof(outarg)); 14483b463ae0SJohn Muir if (err) 14493b463ae0SJohn Muir goto err; 14503b463ae0SJohn Muir 14513b463ae0SJohn Muir err = -ENAMETOOLONG; 14523b463ae0SJohn Muir if (outarg.namelen > FUSE_NAME_MAX) 14533b463ae0SJohn Muir goto err; 14543b463ae0SJohn Muir 1455c2183d1eSMiklos Szeredi err = -EINVAL; 1456c2183d1eSMiklos Szeredi if (size != sizeof(outarg) + outarg.namelen + 1) 1457c2183d1eSMiklos Szeredi goto err; 1458c2183d1eSMiklos Szeredi 14593b463ae0SJohn Muir name.name = buf; 14603b463ae0SJohn Muir name.len = outarg.namelen; 14613b463ae0SJohn Muir err = fuse_copy_one(cs, buf, outarg.namelen + 1); 14623b463ae0SJohn Muir if (err) 14633b463ae0SJohn Muir goto err; 14643b463ae0SJohn Muir fuse_copy_finish(cs); 14653b463ae0SJohn Muir buf[outarg.namelen] = 0; 14663b463ae0SJohn Muir 14673b463ae0SJohn Muir down_read(&fc->killsb); 14683b463ae0SJohn Muir err = -ENOENT; 1469b21dda43SMiklos Szeredi if (fc->sb) 1470451d0f59SJohn Muir err = fuse_reverse_inval_entry(fc->sb, outarg.parent, 0, &name); 1471451d0f59SJohn Muir up_read(&fc->killsb); 1472451d0f59SJohn Muir kfree(buf); 1473451d0f59SJohn Muir return err; 1474451d0f59SJohn Muir 1475451d0f59SJohn Muir err: 1476451d0f59SJohn Muir kfree(buf); 1477451d0f59SJohn Muir fuse_copy_finish(cs); 1478451d0f59SJohn Muir return err; 1479451d0f59SJohn Muir } 1480451d0f59SJohn Muir 1481451d0f59SJohn Muir static int fuse_notify_delete(struct fuse_conn *fc, unsigned int size, 1482451d0f59SJohn Muir struct fuse_copy_state *cs) 1483451d0f59SJohn Muir { 1484451d0f59SJohn Muir struct fuse_notify_delete_out outarg; 1485451d0f59SJohn Muir int err = -ENOMEM; 1486451d0f59SJohn Muir char *buf; 1487451d0f59SJohn Muir struct qstr name; 1488451d0f59SJohn Muir 1489451d0f59SJohn Muir buf = kzalloc(FUSE_NAME_MAX + 1, GFP_KERNEL); 1490451d0f59SJohn Muir if (!buf) 1491451d0f59SJohn Muir goto err; 1492451d0f59SJohn Muir 1493451d0f59SJohn Muir err = -EINVAL; 1494451d0f59SJohn Muir if (size < sizeof(outarg)) 1495451d0f59SJohn Muir goto err; 1496451d0f59SJohn Muir 1497451d0f59SJohn Muir err = fuse_copy_one(cs, &outarg, sizeof(outarg)); 1498451d0f59SJohn Muir if (err) 1499451d0f59SJohn Muir goto err; 1500451d0f59SJohn Muir 1501451d0f59SJohn Muir err = -ENAMETOOLONG; 1502451d0f59SJohn Muir if (outarg.namelen > FUSE_NAME_MAX) 1503451d0f59SJohn Muir goto err; 1504451d0f59SJohn Muir 1505451d0f59SJohn Muir err = -EINVAL; 1506451d0f59SJohn Muir if (size != sizeof(outarg) + outarg.namelen + 1) 1507451d0f59SJohn Muir goto err; 1508451d0f59SJohn Muir 1509451d0f59SJohn Muir name.name = buf; 1510451d0f59SJohn Muir name.len = outarg.namelen; 1511451d0f59SJohn Muir err = fuse_copy_one(cs, buf, outarg.namelen + 1); 1512451d0f59SJohn Muir if (err) 1513451d0f59SJohn Muir goto err; 1514451d0f59SJohn Muir fuse_copy_finish(cs); 1515451d0f59SJohn Muir buf[outarg.namelen] = 0; 1516451d0f59SJohn Muir 1517451d0f59SJohn Muir down_read(&fc->killsb); 1518451d0f59SJohn Muir err = -ENOENT; 1519451d0f59SJohn Muir if (fc->sb) 1520451d0f59SJohn Muir err = fuse_reverse_inval_entry(fc->sb, outarg.parent, 1521451d0f59SJohn Muir outarg.child, &name); 15223b463ae0SJohn Muir up_read(&fc->killsb); 1523b2d82ee3SFang Wenqi kfree(buf); 15243b463ae0SJohn Muir return err; 15253b463ae0SJohn Muir 15263b463ae0SJohn Muir err: 1527b2d82ee3SFang Wenqi kfree(buf); 15283b463ae0SJohn Muir fuse_copy_finish(cs); 15293b463ae0SJohn Muir return err; 15303b463ae0SJohn Muir } 15313b463ae0SJohn Muir 1532a1d75f25SMiklos Szeredi static int fuse_notify_store(struct fuse_conn *fc, unsigned int size, 1533a1d75f25SMiklos Szeredi struct fuse_copy_state *cs) 1534a1d75f25SMiklos Szeredi { 1535a1d75f25SMiklos Szeredi struct fuse_notify_store_out outarg; 1536a1d75f25SMiklos Szeredi struct inode *inode; 1537a1d75f25SMiklos Szeredi struct address_space *mapping; 1538a1d75f25SMiklos Szeredi u64 nodeid; 1539a1d75f25SMiklos Szeredi int err; 1540a1d75f25SMiklos Szeredi pgoff_t index; 1541a1d75f25SMiklos Szeredi unsigned int offset; 1542a1d75f25SMiklos Szeredi unsigned int num; 1543a1d75f25SMiklos Szeredi loff_t file_size; 1544a1d75f25SMiklos Szeredi loff_t end; 1545a1d75f25SMiklos Szeredi 1546a1d75f25SMiklos Szeredi err = -EINVAL; 1547a1d75f25SMiklos Szeredi if (size < sizeof(outarg)) 1548a1d75f25SMiklos Szeredi goto out_finish; 1549a1d75f25SMiklos Szeredi 1550a1d75f25SMiklos Szeredi err = fuse_copy_one(cs, &outarg, sizeof(outarg)); 1551a1d75f25SMiklos Szeredi if (err) 1552a1d75f25SMiklos Szeredi goto out_finish; 1553a1d75f25SMiklos Szeredi 1554a1d75f25SMiklos Szeredi err = -EINVAL; 1555a1d75f25SMiklos Szeredi if (size - sizeof(outarg) != outarg.size) 1556a1d75f25SMiklos Szeredi goto out_finish; 1557a1d75f25SMiklos Szeredi 1558a1d75f25SMiklos Szeredi nodeid = outarg.nodeid; 1559a1d75f25SMiklos Szeredi 1560a1d75f25SMiklos Szeredi down_read(&fc->killsb); 1561a1d75f25SMiklos Szeredi 1562a1d75f25SMiklos Szeredi err = -ENOENT; 1563a1d75f25SMiklos Szeredi if (!fc->sb) 1564a1d75f25SMiklos Szeredi goto out_up_killsb; 1565a1d75f25SMiklos Szeredi 1566a1d75f25SMiklos Szeredi inode = ilookup5(fc->sb, nodeid, fuse_inode_eq, &nodeid); 1567a1d75f25SMiklos Szeredi if (!inode) 1568a1d75f25SMiklos Szeredi goto out_up_killsb; 1569a1d75f25SMiklos Szeredi 1570a1d75f25SMiklos Szeredi mapping = inode->i_mapping; 157109cbfeafSKirill A. Shutemov index = outarg.offset >> PAGE_SHIFT; 157209cbfeafSKirill A. Shutemov offset = outarg.offset & ~PAGE_MASK; 1573a1d75f25SMiklos Szeredi file_size = i_size_read(inode); 1574a1d75f25SMiklos Szeredi end = outarg.offset + outarg.size; 1575a1d75f25SMiklos Szeredi if (end > file_size) { 1576a1d75f25SMiklos Szeredi file_size = end; 1577a1d75f25SMiklos Szeredi fuse_write_update_size(inode, file_size); 1578a1d75f25SMiklos Szeredi } 1579a1d75f25SMiklos Szeredi 1580a1d75f25SMiklos Szeredi num = outarg.size; 1581a1d75f25SMiklos Szeredi while (num) { 1582a1d75f25SMiklos Szeredi struct page *page; 1583a1d75f25SMiklos Szeredi unsigned int this_num; 1584a1d75f25SMiklos Szeredi 1585a1d75f25SMiklos Szeredi err = -ENOMEM; 1586a1d75f25SMiklos Szeredi page = find_or_create_page(mapping, index, 1587a1d75f25SMiklos Szeredi mapping_gfp_mask(mapping)); 1588a1d75f25SMiklos Szeredi if (!page) 1589a1d75f25SMiklos Szeredi goto out_iput; 1590a1d75f25SMiklos Szeredi 159109cbfeafSKirill A. Shutemov this_num = min_t(unsigned, num, PAGE_SIZE - offset); 1592a1d75f25SMiklos Szeredi err = fuse_copy_page(cs, &page, offset, this_num, 0); 1593063ec1e5SMiklos Szeredi if (!err && offset == 0 && 159409cbfeafSKirill A. Shutemov (this_num == PAGE_SIZE || file_size == end)) 1595a1d75f25SMiklos Szeredi SetPageUptodate(page); 1596a1d75f25SMiklos Szeredi unlock_page(page); 159709cbfeafSKirill A. Shutemov put_page(page); 1598a1d75f25SMiklos Szeredi 1599a1d75f25SMiklos Szeredi if (err) 1600a1d75f25SMiklos Szeredi goto out_iput; 1601a1d75f25SMiklos Szeredi 1602a1d75f25SMiklos Szeredi num -= this_num; 1603a1d75f25SMiklos Szeredi offset = 0; 1604a1d75f25SMiklos Szeredi index++; 1605a1d75f25SMiklos Szeredi } 1606a1d75f25SMiklos Szeredi 1607a1d75f25SMiklos Szeredi err = 0; 1608a1d75f25SMiklos Szeredi 1609a1d75f25SMiklos Szeredi out_iput: 1610a1d75f25SMiklos Szeredi iput(inode); 1611a1d75f25SMiklos Szeredi out_up_killsb: 1612a1d75f25SMiklos Szeredi up_read(&fc->killsb); 1613a1d75f25SMiklos Szeredi out_finish: 1614a1d75f25SMiklos Szeredi fuse_copy_finish(cs); 1615a1d75f25SMiklos Szeredi return err; 1616a1d75f25SMiklos Szeredi } 1617a1d75f25SMiklos Szeredi 161875b399ddSMiklos Szeredi struct fuse_retrieve_args { 161975b399ddSMiklos Szeredi struct fuse_args_pages ap; 162075b399ddSMiklos Szeredi struct fuse_notify_retrieve_in inarg; 162175b399ddSMiklos Szeredi }; 162275b399ddSMiklos Szeredi 162375b399ddSMiklos Szeredi static void fuse_retrieve_end(struct fuse_conn *fc, struct fuse_args *args, 162475b399ddSMiklos Szeredi int error) 16252d45ba38SMiklos Szeredi { 162675b399ddSMiklos Szeredi struct fuse_retrieve_args *ra = 162775b399ddSMiklos Szeredi container_of(args, typeof(*ra), ap.args); 162875b399ddSMiklos Szeredi 162975b399ddSMiklos Szeredi release_pages(ra->ap.pages, ra->ap.num_pages); 163075b399ddSMiklos Szeredi kfree(ra); 16312d45ba38SMiklos Szeredi } 16322d45ba38SMiklos Szeredi 16332d45ba38SMiklos Szeredi static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode, 16342d45ba38SMiklos Szeredi struct fuse_notify_retrieve_out *outarg) 16352d45ba38SMiklos Szeredi { 16362d45ba38SMiklos Szeredi int err; 16372d45ba38SMiklos Szeredi struct address_space *mapping = inode->i_mapping; 16382d45ba38SMiklos Szeredi pgoff_t index; 16392d45ba38SMiklos Szeredi loff_t file_size; 16402d45ba38SMiklos Szeredi unsigned int num; 16412d45ba38SMiklos Szeredi unsigned int offset; 16420157443cSGeert Uytterhoeven size_t total_len = 0; 16435da784ccSConstantine Shulyupin unsigned int num_pages; 164475b399ddSMiklos Szeredi struct fuse_retrieve_args *ra; 164575b399ddSMiklos Szeredi size_t args_size = sizeof(*ra); 164675b399ddSMiklos Szeredi struct fuse_args_pages *ap; 164775b399ddSMiklos Szeredi struct fuse_args *args; 16482d45ba38SMiklos Szeredi 164909cbfeafSKirill A. Shutemov offset = outarg->offset & ~PAGE_MASK; 16504d53dc99SMaxim Patlasov file_size = i_size_read(inode); 16514d53dc99SMaxim Patlasov 16527640682eSKirill Smelkov num = min(outarg->size, fc->max_write); 16534d53dc99SMaxim Patlasov if (outarg->offset > file_size) 16544d53dc99SMaxim Patlasov num = 0; 16554d53dc99SMaxim Patlasov else if (outarg->offset + num > file_size) 16564d53dc99SMaxim Patlasov num = file_size - outarg->offset; 16574d53dc99SMaxim Patlasov 16584d53dc99SMaxim Patlasov num_pages = (num + offset + PAGE_SIZE - 1) >> PAGE_SHIFT; 16595da784ccSConstantine Shulyupin num_pages = min(num_pages, fc->max_pages); 16604d53dc99SMaxim Patlasov 166175b399ddSMiklos Szeredi args_size += num_pages * (sizeof(ap->pages[0]) + sizeof(ap->descs[0])); 16622d45ba38SMiklos Szeredi 166375b399ddSMiklos Szeredi ra = kzalloc(args_size, GFP_KERNEL); 166475b399ddSMiklos Szeredi if (!ra) 166575b399ddSMiklos Szeredi return -ENOMEM; 166675b399ddSMiklos Szeredi 166775b399ddSMiklos Szeredi ap = &ra->ap; 166875b399ddSMiklos Szeredi ap->pages = (void *) (ra + 1); 166975b399ddSMiklos Szeredi ap->descs = (void *) (ap->pages + num_pages); 167075b399ddSMiklos Szeredi 167175b399ddSMiklos Szeredi args = &ap->args; 167275b399ddSMiklos Szeredi args->nodeid = outarg->nodeid; 167375b399ddSMiklos Szeredi args->opcode = FUSE_NOTIFY_REPLY; 167475b399ddSMiklos Szeredi args->in_numargs = 2; 167575b399ddSMiklos Szeredi args->in_pages = true; 167675b399ddSMiklos Szeredi args->end = fuse_retrieve_end; 16772d45ba38SMiklos Szeredi 167809cbfeafSKirill A. Shutemov index = outarg->offset >> PAGE_SHIFT; 16792d45ba38SMiklos Szeredi 168075b399ddSMiklos Szeredi while (num && ap->num_pages < num_pages) { 16812d45ba38SMiklos Szeredi struct page *page; 16822d45ba38SMiklos Szeredi unsigned int this_num; 16832d45ba38SMiklos Szeredi 16842d45ba38SMiklos Szeredi page = find_get_page(mapping, index); 16852d45ba38SMiklos Szeredi if (!page) 16862d45ba38SMiklos Szeredi break; 16872d45ba38SMiklos Szeredi 168809cbfeafSKirill A. Shutemov this_num = min_t(unsigned, num, PAGE_SIZE - offset); 168975b399ddSMiklos Szeredi ap->pages[ap->num_pages] = page; 169075b399ddSMiklos Szeredi ap->descs[ap->num_pages].offset = offset; 169175b399ddSMiklos Szeredi ap->descs[ap->num_pages].length = this_num; 169275b399ddSMiklos Szeredi ap->num_pages++; 16932d45ba38SMiklos Szeredi 1694c9e67d48SMiklos Szeredi offset = 0; 16952d45ba38SMiklos Szeredi num -= this_num; 16962d45ba38SMiklos Szeredi total_len += this_num; 169748706d0aSMiklos Szeredi index++; 16982d45ba38SMiklos Szeredi } 169975b399ddSMiklos Szeredi ra->inarg.offset = outarg->offset; 170075b399ddSMiklos Szeredi ra->inarg.size = total_len; 170175b399ddSMiklos Szeredi args->in_args[0].size = sizeof(ra->inarg); 170275b399ddSMiklos Szeredi args->in_args[0].value = &ra->inarg; 170375b399ddSMiklos Szeredi args->in_args[1].size = total_len; 17042d45ba38SMiklos Szeredi 170575b399ddSMiklos Szeredi err = fuse_simple_notify_reply(fc, args, outarg->notify_unique); 170675b399ddSMiklos Szeredi if (err) 170775b399ddSMiklos Szeredi fuse_retrieve_end(fc, args, err); 17082d45ba38SMiklos Szeredi 17092d45ba38SMiklos Szeredi return err; 17102d45ba38SMiklos Szeredi } 17112d45ba38SMiklos Szeredi 17122d45ba38SMiklos Szeredi static int fuse_notify_retrieve(struct fuse_conn *fc, unsigned int size, 17132d45ba38SMiklos Szeredi struct fuse_copy_state *cs) 17142d45ba38SMiklos Szeredi { 17152d45ba38SMiklos Szeredi struct fuse_notify_retrieve_out outarg; 17162d45ba38SMiklos Szeredi struct inode *inode; 17172d45ba38SMiklos Szeredi int err; 17182d45ba38SMiklos Szeredi 17192d45ba38SMiklos Szeredi err = -EINVAL; 17202d45ba38SMiklos Szeredi if (size != sizeof(outarg)) 17212d45ba38SMiklos Szeredi goto copy_finish; 17222d45ba38SMiklos Szeredi 17232d45ba38SMiklos Szeredi err = fuse_copy_one(cs, &outarg, sizeof(outarg)); 17242d45ba38SMiklos Szeredi if (err) 17252d45ba38SMiklos Szeredi goto copy_finish; 17262d45ba38SMiklos Szeredi 17272d45ba38SMiklos Szeredi fuse_copy_finish(cs); 17282d45ba38SMiklos Szeredi 17292d45ba38SMiklos Szeredi down_read(&fc->killsb); 17302d45ba38SMiklos Szeredi err = -ENOENT; 17312d45ba38SMiklos Szeredi if (fc->sb) { 17322d45ba38SMiklos Szeredi u64 nodeid = outarg.nodeid; 17332d45ba38SMiklos Szeredi 17342d45ba38SMiklos Szeredi inode = ilookup5(fc->sb, nodeid, fuse_inode_eq, &nodeid); 17352d45ba38SMiklos Szeredi if (inode) { 17362d45ba38SMiklos Szeredi err = fuse_retrieve(fc, inode, &outarg); 17372d45ba38SMiklos Szeredi iput(inode); 17382d45ba38SMiklos Szeredi } 17392d45ba38SMiklos Szeredi } 17402d45ba38SMiklos Szeredi up_read(&fc->killsb); 17412d45ba38SMiklos Szeredi 17422d45ba38SMiklos Szeredi return err; 17432d45ba38SMiklos Szeredi 17442d45ba38SMiklos Szeredi copy_finish: 17452d45ba38SMiklos Szeredi fuse_copy_finish(cs); 17462d45ba38SMiklos Szeredi return err; 17472d45ba38SMiklos Szeredi } 17482d45ba38SMiklos Szeredi 17498599396bSTejun Heo static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code, 17508599396bSTejun Heo unsigned int size, struct fuse_copy_state *cs) 17518599396bSTejun Heo { 17520d278362SMiklos Szeredi /* Don't try to move pages (yet) */ 17530d278362SMiklos Szeredi cs->move_pages = 0; 17540d278362SMiklos Szeredi 17558599396bSTejun Heo switch (code) { 175695668a69STejun Heo case FUSE_NOTIFY_POLL: 175795668a69STejun Heo return fuse_notify_poll(fc, size, cs); 175895668a69STejun Heo 17593b463ae0SJohn Muir case FUSE_NOTIFY_INVAL_INODE: 17603b463ae0SJohn Muir return fuse_notify_inval_inode(fc, size, cs); 17613b463ae0SJohn Muir 17623b463ae0SJohn Muir case FUSE_NOTIFY_INVAL_ENTRY: 17633b463ae0SJohn Muir return fuse_notify_inval_entry(fc, size, cs); 17643b463ae0SJohn Muir 1765a1d75f25SMiklos Szeredi case FUSE_NOTIFY_STORE: 1766a1d75f25SMiklos Szeredi return fuse_notify_store(fc, size, cs); 1767a1d75f25SMiklos Szeredi 17682d45ba38SMiklos Szeredi case FUSE_NOTIFY_RETRIEVE: 17692d45ba38SMiklos Szeredi return fuse_notify_retrieve(fc, size, cs); 17702d45ba38SMiklos Szeredi 1771451d0f59SJohn Muir case FUSE_NOTIFY_DELETE: 1772451d0f59SJohn Muir return fuse_notify_delete(fc, size, cs); 1773451d0f59SJohn Muir 17748599396bSTejun Heo default: 1775f6d47a17SMiklos Szeredi fuse_copy_finish(cs); 17768599396bSTejun Heo return -EINVAL; 17778599396bSTejun Heo } 17788599396bSTejun Heo } 17798599396bSTejun Heo 1780334f485dSMiklos Szeredi /* Look up request on processing list by unique ID */ 17813a2b5b9cSMiklos Szeredi static struct fuse_req *request_find(struct fuse_pqueue *fpq, u64 unique) 1782334f485dSMiklos Szeredi { 1783be2ff42cSKirill Tkhai unsigned int hash = fuse_req_hash(unique); 1784334f485dSMiklos Szeredi struct fuse_req *req; 178505726acaSDong Fang 1786be2ff42cSKirill Tkhai list_for_each_entry(req, &fpq->processing[hash], list) { 17873a5358d1SKirill Tkhai if (req->in.h.unique == unique) 1788334f485dSMiklos Szeredi return req; 1789334f485dSMiklos Szeredi } 1790334f485dSMiklos Szeredi return NULL; 1791334f485dSMiklos Szeredi } 1792334f485dSMiklos Szeredi 1793d4993774SMiklos Szeredi static int copy_out_args(struct fuse_copy_state *cs, struct fuse_args *args, 1794334f485dSMiklos Szeredi unsigned nbytes) 1795334f485dSMiklos Szeredi { 1796334f485dSMiklos Szeredi unsigned reqsize = sizeof(struct fuse_out_header); 1797334f485dSMiklos Szeredi 179814d46d7aSStefan Hajnoczi reqsize += fuse_len_args(args->out_numargs, args->out_args); 1799334f485dSMiklos Szeredi 1800d4993774SMiklos Szeredi if (reqsize < nbytes || (reqsize > nbytes && !args->out_argvar)) 1801334f485dSMiklos Szeredi return -EINVAL; 1802334f485dSMiklos Szeredi else if (reqsize > nbytes) { 1803d4993774SMiklos Szeredi struct fuse_arg *lastarg = &args->out_args[args->out_numargs-1]; 1804334f485dSMiklos Szeredi unsigned diffsize = reqsize - nbytes; 1805d4993774SMiklos Szeredi 1806334f485dSMiklos Szeredi if (diffsize > lastarg->size) 1807334f485dSMiklos Szeredi return -EINVAL; 1808334f485dSMiklos Szeredi lastarg->size -= diffsize; 1809334f485dSMiklos Szeredi } 1810d4993774SMiklos Szeredi return fuse_copy_args(cs, args->out_numargs, args->out_pages, 1811d4993774SMiklos Szeredi args->out_args, args->page_zeroing); 1812334f485dSMiklos Szeredi } 1813334f485dSMiklos Szeredi 1814334f485dSMiklos Szeredi /* 1815334f485dSMiklos Szeredi * Write a single reply to a request. First the header is copied from 1816334f485dSMiklos Szeredi * the write buffer. The request is then searched on the processing 1817334f485dSMiklos Szeredi * list by the unique ID found in the header. If found, then remove 1818334f485dSMiklos Szeredi * it from the list and copy the rest of the buffer to the request. 181904ec5af0SStefan Hajnoczi * The request is finished by calling fuse_request_end(). 1820334f485dSMiklos Szeredi */ 1821c3696046SMiklos Szeredi static ssize_t fuse_dev_do_write(struct fuse_dev *fud, 1822dd3bb14fSMiklos Szeredi struct fuse_copy_state *cs, size_t nbytes) 1823334f485dSMiklos Szeredi { 1824334f485dSMiklos Szeredi int err; 1825c3696046SMiklos Szeredi struct fuse_conn *fc = fud->fc; 1826c3696046SMiklos Szeredi struct fuse_pqueue *fpq = &fud->pq; 1827334f485dSMiklos Szeredi struct fuse_req *req; 1828334f485dSMiklos Szeredi struct fuse_out_header oh; 1829334f485dSMiklos Szeredi 18307407a10dSKirill Tkhai err = -EINVAL; 1831334f485dSMiklos Szeredi if (nbytes < sizeof(struct fuse_out_header)) 18327407a10dSKirill Tkhai goto out; 1833334f485dSMiklos Szeredi 1834dd3bb14fSMiklos Szeredi err = fuse_copy_one(cs, &oh, sizeof(oh)); 1835334f485dSMiklos Szeredi if (err) 18367407a10dSKirill Tkhai goto copy_finish; 18378599396bSTejun Heo 1838334f485dSMiklos Szeredi err = -EINVAL; 18398599396bSTejun Heo if (oh.len != nbytes) 18407407a10dSKirill Tkhai goto copy_finish; 18418599396bSTejun Heo 18428599396bSTejun Heo /* 18438599396bSTejun Heo * Zero oh.unique indicates unsolicited notification message 18448599396bSTejun Heo * and error contains notification code. 18458599396bSTejun Heo */ 18468599396bSTejun Heo if (!oh.unique) { 1847dd3bb14fSMiklos Szeredi err = fuse_notify(fc, oh.error, nbytes - sizeof(oh), cs); 18487407a10dSKirill Tkhai goto out; 18498599396bSTejun Heo } 18508599396bSTejun Heo 18518599396bSTejun Heo err = -EINVAL; 18528599396bSTejun Heo if (oh.error <= -1000 || oh.error > 0) 18537407a10dSKirill Tkhai goto copy_finish; 1854334f485dSMiklos Szeredi 185545a91cb1SMiklos Szeredi spin_lock(&fpq->lock); 18567407a10dSKirill Tkhai req = NULL; 18577407a10dSKirill Tkhai if (fpq->connected) 18583a5358d1SKirill Tkhai req = request_find(fpq, oh.unique & ~FUSE_INT_REQ_BIT); 18597407a10dSKirill Tkhai 18607407a10dSKirill Tkhai err = -ENOENT; 18617407a10dSKirill Tkhai if (!req) { 18627407a10dSKirill Tkhai spin_unlock(&fpq->lock); 18637407a10dSKirill Tkhai goto copy_finish; 18647407a10dSKirill Tkhai } 1865334f485dSMiklos Szeredi 18663a5358d1SKirill Tkhai /* Is it an interrupt reply ID? */ 18673a5358d1SKirill Tkhai if (oh.unique & FUSE_INT_REQ_BIT) { 1868d2d2d4fbSKirill Tkhai __fuse_get_request(req); 186945a91cb1SMiklos Szeredi spin_unlock(&fpq->lock); 187045a91cb1SMiklos Szeredi 18717407a10dSKirill Tkhai err = 0; 18727407a10dSKirill Tkhai if (nbytes != sizeof(struct fuse_out_header)) 1873a4d27e75SMiklos Szeredi err = -EINVAL; 18747407a10dSKirill Tkhai else if (oh.error == -ENOSYS) 1875a4d27e75SMiklos Szeredi fc->no_interrupt = 1; 1876a4d27e75SMiklos Szeredi else if (oh.error == -EAGAIN) 1877b782911bSKirill Tkhai err = queue_interrupt(&fc->iq, req); 18787407a10dSKirill Tkhai 1879d2d2d4fbSKirill Tkhai fuse_put_request(fc, req); 1880a4d27e75SMiklos Szeredi 18817407a10dSKirill Tkhai goto copy_finish; 1882a4d27e75SMiklos Szeredi } 1883a4d27e75SMiklos Szeredi 188433e14b4dSMiklos Szeredi clear_bit(FR_SENT, &req->flags); 18853a2b5b9cSMiklos Szeredi list_move(&req->list, &fpq->io); 1886334f485dSMiklos Szeredi req->out.h = oh; 1887825d6d33SMiklos Szeredi set_bit(FR_LOCKED, &req->flags); 188845a91cb1SMiklos Szeredi spin_unlock(&fpq->lock); 1889dd3bb14fSMiklos Szeredi cs->req = req; 1890d4993774SMiklos Szeredi if (!req->args->page_replace) 1891ce534fb0SMiklos Szeredi cs->move_pages = 0; 1892334f485dSMiklos Szeredi 1893d4993774SMiklos Szeredi if (oh.error) 1894d4993774SMiklos Szeredi err = nbytes != sizeof(oh) ? -EINVAL : 0; 1895d4993774SMiklos Szeredi else 1896d4993774SMiklos Szeredi err = copy_out_args(cs, req->args, nbytes); 1897dd3bb14fSMiklos Szeredi fuse_copy_finish(cs); 1898334f485dSMiklos Szeredi 189945a91cb1SMiklos Szeredi spin_lock(&fpq->lock); 1900825d6d33SMiklos Szeredi clear_bit(FR_LOCKED, &req->flags); 1901e96edd94SMiklos Szeredi if (!fpq->connected) 1902334f485dSMiklos Szeredi err = -ENOENT; 19030d8e84b0SMiklos Szeredi else if (err) 1904334f485dSMiklos Szeredi req->out.h.error = -EIO; 190577cd9d48SMiklos Szeredi if (!test_bit(FR_PRIVATE, &req->flags)) 1906f377cb79SMiklos Szeredi list_del_init(&req->list); 190745a91cb1SMiklos Szeredi spin_unlock(&fpq->lock); 190846c34a34SMiklos Szeredi 190904ec5af0SStefan Hajnoczi fuse_request_end(fc, req); 19107407a10dSKirill Tkhai out: 1911334f485dSMiklos Szeredi return err ? err : nbytes; 1912334f485dSMiklos Szeredi 19137407a10dSKirill Tkhai copy_finish: 1914dd3bb14fSMiklos Szeredi fuse_copy_finish(cs); 19157407a10dSKirill Tkhai goto out; 1916334f485dSMiklos Szeredi } 1917334f485dSMiklos Szeredi 1918fbdbaccaSAl Viro static ssize_t fuse_dev_write(struct kiocb *iocb, struct iov_iter *from) 1919dd3bb14fSMiklos Szeredi { 1920dd3bb14fSMiklos Szeredi struct fuse_copy_state cs; 1921cc080e9eSMiklos Szeredi struct fuse_dev *fud = fuse_get_dev(iocb->ki_filp); 1922cc080e9eSMiklos Szeredi 1923cc080e9eSMiklos Szeredi if (!fud) 1924dd3bb14fSMiklos Szeredi return -EPERM; 1925dd3bb14fSMiklos Szeredi 1926fbdbaccaSAl Viro if (!iter_is_iovec(from)) 1927fbdbaccaSAl Viro return -EINVAL; 1928dd3bb14fSMiklos Szeredi 1929dc00809aSMiklos Szeredi fuse_copy_init(&cs, 0, from); 1930fbdbaccaSAl Viro 1931c3696046SMiklos Szeredi return fuse_dev_do_write(fud, &cs, iov_iter_count(from)); 1932dd3bb14fSMiklos Szeredi } 1933dd3bb14fSMiklos Szeredi 1934dd3bb14fSMiklos Szeredi static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, 1935dd3bb14fSMiklos Szeredi struct file *out, loff_t *ppos, 1936dd3bb14fSMiklos Szeredi size_t len, unsigned int flags) 1937dd3bb14fSMiklos Szeredi { 1938dd3bb14fSMiklos Szeredi unsigned nbuf; 1939dd3bb14fSMiklos Szeredi unsigned idx; 1940dd3bb14fSMiklos Szeredi struct pipe_buffer *bufs; 1941dd3bb14fSMiklos Szeredi struct fuse_copy_state cs; 1942cc080e9eSMiklos Szeredi struct fuse_dev *fud; 1943dd3bb14fSMiklos Szeredi size_t rem; 1944dd3bb14fSMiklos Szeredi ssize_t ret; 1945dd3bb14fSMiklos Szeredi 1946cc080e9eSMiklos Szeredi fud = fuse_get_dev(out); 1947cc080e9eSMiklos Szeredi if (!fud) 1948dd3bb14fSMiklos Szeredi return -EPERM; 1949dd3bb14fSMiklos Szeredi 1950a2477b0eSAndrey Ryabinin pipe_lock(pipe); 1951a2477b0eSAndrey Ryabinin 195296354535SAndrey Ryabinin bufs = kvmalloc_array(pipe->nrbufs, sizeof(struct pipe_buffer), 19536da2ec56SKees Cook GFP_KERNEL); 1954a2477b0eSAndrey Ryabinin if (!bufs) { 1955a2477b0eSAndrey Ryabinin pipe_unlock(pipe); 1956dd3bb14fSMiklos Szeredi return -ENOMEM; 1957a2477b0eSAndrey Ryabinin } 1958dd3bb14fSMiklos Szeredi 1959dd3bb14fSMiklos Szeredi nbuf = 0; 1960dd3bb14fSMiklos Szeredi rem = 0; 1961dd3bb14fSMiklos Szeredi for (idx = 0; idx < pipe->nrbufs && rem < len; idx++) 1962dd3bb14fSMiklos Szeredi rem += pipe->bufs[(pipe->curbuf + idx) & (pipe->buffers - 1)].len; 1963dd3bb14fSMiklos Szeredi 1964dd3bb14fSMiklos Szeredi ret = -EINVAL; 196515fab63eSMatthew Wilcox if (rem < len) 196615fab63eSMatthew Wilcox goto out_free; 1967dd3bb14fSMiklos Szeredi 1968dd3bb14fSMiklos Szeredi rem = len; 1969dd3bb14fSMiklos Szeredi while (rem) { 1970dd3bb14fSMiklos Szeredi struct pipe_buffer *ibuf; 1971dd3bb14fSMiklos Szeredi struct pipe_buffer *obuf; 1972dd3bb14fSMiklos Szeredi 1973dd3bb14fSMiklos Szeredi BUG_ON(nbuf >= pipe->buffers); 1974dd3bb14fSMiklos Szeredi BUG_ON(!pipe->nrbufs); 1975dd3bb14fSMiklos Szeredi ibuf = &pipe->bufs[pipe->curbuf]; 1976dd3bb14fSMiklos Szeredi obuf = &bufs[nbuf]; 1977dd3bb14fSMiklos Szeredi 1978dd3bb14fSMiklos Szeredi if (rem >= ibuf->len) { 1979dd3bb14fSMiklos Szeredi *obuf = *ibuf; 1980dd3bb14fSMiklos Szeredi ibuf->ops = NULL; 1981dd3bb14fSMiklos Szeredi pipe->curbuf = (pipe->curbuf + 1) & (pipe->buffers - 1); 1982dd3bb14fSMiklos Szeredi pipe->nrbufs--; 1983dd3bb14fSMiklos Szeredi } else { 198415fab63eSMatthew Wilcox if (!pipe_buf_get(pipe, ibuf)) 198515fab63eSMatthew Wilcox goto out_free; 198615fab63eSMatthew Wilcox 1987dd3bb14fSMiklos Szeredi *obuf = *ibuf; 1988dd3bb14fSMiklos Szeredi obuf->flags &= ~PIPE_BUF_FLAG_GIFT; 1989dd3bb14fSMiklos Szeredi obuf->len = rem; 1990dd3bb14fSMiklos Szeredi ibuf->offset += obuf->len; 1991dd3bb14fSMiklos Szeredi ibuf->len -= obuf->len; 1992dd3bb14fSMiklos Szeredi } 1993dd3bb14fSMiklos Szeredi nbuf++; 1994dd3bb14fSMiklos Szeredi rem -= obuf->len; 1995dd3bb14fSMiklos Szeredi } 1996dd3bb14fSMiklos Szeredi pipe_unlock(pipe); 1997dd3bb14fSMiklos Szeredi 1998dc00809aSMiklos Szeredi fuse_copy_init(&cs, 0, NULL); 1999dd3bb14fSMiklos Szeredi cs.pipebufs = bufs; 20006c09e94aSAl Viro cs.nr_segs = nbuf; 2001dd3bb14fSMiklos Szeredi cs.pipe = pipe; 2002dd3bb14fSMiklos Szeredi 2003ce534fb0SMiklos Szeredi if (flags & SPLICE_F_MOVE) 2004ce534fb0SMiklos Szeredi cs.move_pages = 1; 2005ce534fb0SMiklos Szeredi 2006c3696046SMiklos Szeredi ret = fuse_dev_do_write(fud, &cs, len); 2007dd3bb14fSMiklos Szeredi 20089509941eSJann Horn pipe_lock(pipe); 200915fab63eSMatthew Wilcox out_free: 2010a779638cSMiklos Szeredi for (idx = 0; idx < nbuf; idx++) 2011a779638cSMiklos Szeredi pipe_buf_release(pipe, &bufs[idx]); 20129509941eSJann Horn pipe_unlock(pipe); 2013a779638cSMiklos Szeredi 2014d6d931adSAndrey Ryabinin kvfree(bufs); 2015dd3bb14fSMiklos Szeredi return ret; 2016dd3bb14fSMiklos Szeredi } 2017dd3bb14fSMiklos Szeredi 2018076ccb76SAl Viro static __poll_t fuse_dev_poll(struct file *file, poll_table *wait) 2019334f485dSMiklos Szeredi { 2020a9a08845SLinus Torvalds __poll_t mask = EPOLLOUT | EPOLLWRNORM; 2021f88996a9SMiklos Szeredi struct fuse_iqueue *fiq; 2022cc080e9eSMiklos Szeredi struct fuse_dev *fud = fuse_get_dev(file); 2023cc080e9eSMiklos Szeredi 2024cc080e9eSMiklos Szeredi if (!fud) 2025a9a08845SLinus Torvalds return EPOLLERR; 2026334f485dSMiklos Szeredi 2027cc080e9eSMiklos Szeredi fiq = &fud->fc->iq; 2028f88996a9SMiklos Szeredi poll_wait(file, &fiq->waitq, wait); 2029334f485dSMiklos Szeredi 203076e43c8cSEric Biggers spin_lock(&fiq->lock); 2031e16714d8SMiklos Szeredi if (!fiq->connected) 2032a9a08845SLinus Torvalds mask = EPOLLERR; 2033f88996a9SMiklos Szeredi else if (request_pending(fiq)) 2034a9a08845SLinus Torvalds mask |= EPOLLIN | EPOLLRDNORM; 203576e43c8cSEric Biggers spin_unlock(&fiq->lock); 2036334f485dSMiklos Szeredi 2037334f485dSMiklos Szeredi return mask; 2038334f485dSMiklos Szeredi } 2039334f485dSMiklos Szeredi 204034061750SKirill Tkhai /* Abort all requests on the given list (pending or processing) */ 2041334f485dSMiklos Szeredi static void end_requests(struct fuse_conn *fc, struct list_head *head) 2042334f485dSMiklos Szeredi { 2043334f485dSMiklos Szeredi while (!list_empty(head)) { 2044334f485dSMiklos Szeredi struct fuse_req *req; 2045334f485dSMiklos Szeredi req = list_entry(head->next, struct fuse_req, list); 2046334f485dSMiklos Szeredi req->out.h.error = -ECONNABORTED; 204733e14b4dSMiklos Szeredi clear_bit(FR_SENT, &req->flags); 2048f377cb79SMiklos Szeredi list_del_init(&req->list); 204904ec5af0SStefan Hajnoczi fuse_request_end(fc, req); 2050334f485dSMiklos Szeredi } 2051334f485dSMiklos Szeredi } 2052334f485dSMiklos Szeredi 2053357ccf2bSBryan Green static void end_polls(struct fuse_conn *fc) 2054357ccf2bSBryan Green { 2055357ccf2bSBryan Green struct rb_node *p; 2056357ccf2bSBryan Green 2057357ccf2bSBryan Green p = rb_first(&fc->polled_files); 2058357ccf2bSBryan Green 2059357ccf2bSBryan Green while (p) { 2060357ccf2bSBryan Green struct fuse_file *ff; 2061357ccf2bSBryan Green ff = rb_entry(p, struct fuse_file, polled_node); 2062357ccf2bSBryan Green wake_up_interruptible_all(&ff->poll_wait); 2063357ccf2bSBryan Green 2064357ccf2bSBryan Green p = rb_next(p); 2065357ccf2bSBryan Green } 2066357ccf2bSBryan Green } 2067357ccf2bSBryan Green 206869a53bf2SMiklos Szeredi /* 206969a53bf2SMiklos Szeredi * Abort all requests. 207069a53bf2SMiklos Szeredi * 2071b716d425SMiklos Szeredi * Emergency exit in case of a malicious or accidental deadlock, or just a hung 2072b716d425SMiklos Szeredi * filesystem. 207369a53bf2SMiklos Szeredi * 2074b716d425SMiklos Szeredi * The same effect is usually achievable through killing the filesystem daemon 2075b716d425SMiklos Szeredi * and all users of the filesystem. The exception is the combination of an 2076b716d425SMiklos Szeredi * asynchronous request and the tricky deadlock (see 2077b716d425SMiklos Szeredi * Documentation/filesystems/fuse.txt). 207869a53bf2SMiklos Szeredi * 2079b716d425SMiklos Szeredi * Aborting requests under I/O goes as follows: 1: Separate out unlocked 2080b716d425SMiklos Szeredi * requests, they should be finished off immediately. Locked requests will be 2081b716d425SMiklos Szeredi * finished after unlock; see unlock_request(). 2: Finish off the unlocked 2082b716d425SMiklos Szeredi * requests. It is possible that some request will finish before we can. This 2083b716d425SMiklos Szeredi * is OK, the request will in that case be removed from the list before we touch 2084b716d425SMiklos Szeredi * it. 208569a53bf2SMiklos Szeredi */ 2086eb98e3bdSMiklos Szeredi void fuse_abort_conn(struct fuse_conn *fc) 208769a53bf2SMiklos Szeredi { 2088f88996a9SMiklos Szeredi struct fuse_iqueue *fiq = &fc->iq; 2089f88996a9SMiklos Szeredi 2090d7133114SMiklos Szeredi spin_lock(&fc->lock); 209169a53bf2SMiklos Szeredi if (fc->connected) { 2092c3696046SMiklos Szeredi struct fuse_dev *fud; 2093b716d425SMiklos Szeredi struct fuse_req *req, *next; 209475f3ee4cSMiklos Szeredi LIST_HEAD(to_end); 2095be2ff42cSKirill Tkhai unsigned int i; 2096b716d425SMiklos Szeredi 209763825b4eSKirill Tkhai /* Background queuing checks fc->connected under bg_lock */ 209863825b4eSKirill Tkhai spin_lock(&fc->bg_lock); 209969a53bf2SMiklos Szeredi fc->connected = 0; 210063825b4eSKirill Tkhai spin_unlock(&fc->bg_lock); 210163825b4eSKirill Tkhai 21029759bd51SMiklos Szeredi fuse_set_initialized(fc); 2103c3696046SMiklos Szeredi list_for_each_entry(fud, &fc->devices, entry) { 2104c3696046SMiklos Szeredi struct fuse_pqueue *fpq = &fud->pq; 2105c3696046SMiklos Szeredi 210645a91cb1SMiklos Szeredi spin_lock(&fpq->lock); 2107e96edd94SMiklos Szeredi fpq->connected = 0; 21083a2b5b9cSMiklos Szeredi list_for_each_entry_safe(req, next, &fpq->io, list) { 2109b716d425SMiklos Szeredi req->out.h.error = -ECONNABORTED; 2110b716d425SMiklos Szeredi spin_lock(&req->waitq.lock); 2111b716d425SMiklos Szeredi set_bit(FR_ABORTED, &req->flags); 211277cd9d48SMiklos Szeredi if (!test_bit(FR_LOCKED, &req->flags)) { 211377cd9d48SMiklos Szeredi set_bit(FR_PRIVATE, &req->flags); 211487114373SMiklos Szeredi __fuse_get_request(req); 211575f3ee4cSMiklos Szeredi list_move(&req->list, &to_end); 211677cd9d48SMiklos Szeredi } 2117b716d425SMiklos Szeredi spin_unlock(&req->waitq.lock); 2118b716d425SMiklos Szeredi } 2119be2ff42cSKirill Tkhai for (i = 0; i < FUSE_PQ_HASH_SIZE; i++) 2120be2ff42cSKirill Tkhai list_splice_tail_init(&fpq->processing[i], 2121be2ff42cSKirill Tkhai &to_end); 212245a91cb1SMiklos Szeredi spin_unlock(&fpq->lock); 2123c3696046SMiklos Szeredi } 2124ae2dffa3SKirill Tkhai spin_lock(&fc->bg_lock); 2125ae2dffa3SKirill Tkhai fc->blocked = 0; 212641f98274SMiklos Szeredi fc->max_background = UINT_MAX; 212741f98274SMiklos Szeredi flush_bg_queue(fc); 2128ae2dffa3SKirill Tkhai spin_unlock(&fc->bg_lock); 21298c91189aSMiklos Szeredi 213076e43c8cSEric Biggers spin_lock(&fiq->lock); 21318c91189aSMiklos Szeredi fiq->connected = 0; 213275f3ee4cSMiklos Szeredi list_for_each_entry(req, &fiq->pending, list) 2133a8a86d78STahsin Erdogan clear_bit(FR_PENDING, &req->flags); 213475f3ee4cSMiklos Szeredi list_splice_tail_init(&fiq->pending, &to_end); 21358c91189aSMiklos Szeredi while (forget_pending(fiq)) 21364388c5aaSVivek Goyal kfree(fuse_dequeue_forget(fiq, 1, NULL)); 213776e43c8cSEric Biggers wake_up_all(&fiq->waitq); 213876e43c8cSEric Biggers spin_unlock(&fiq->lock); 21398c91189aSMiklos Szeredi kill_fasync(&fiq->fasync, SIGIO, POLL_IN); 2140ee314a87SMiklos Szeredi end_polls(fc); 2141ee314a87SMiklos Szeredi wake_up_all(&fc->blocked_waitq); 2142ee314a87SMiklos Szeredi spin_unlock(&fc->lock); 21438c91189aSMiklos Szeredi 214475f3ee4cSMiklos Szeredi end_requests(fc, &to_end); 2145ee314a87SMiklos Szeredi } else { 2146d7133114SMiklos Szeredi spin_unlock(&fc->lock); 214769a53bf2SMiklos Szeredi } 2148ee314a87SMiklos Szeredi } 214908cbf542STejun Heo EXPORT_SYMBOL_GPL(fuse_abort_conn); 215069a53bf2SMiklos Szeredi 2151b8f95e5dSMiklos Szeredi void fuse_wait_aborted(struct fuse_conn *fc) 2152b8f95e5dSMiklos Szeredi { 21532d84a2d1SMiklos Szeredi /* matches implicit memory barrier in fuse_drop_waiting() */ 21542d84a2d1SMiklos Szeredi smp_mb(); 2155b8f95e5dSMiklos Szeredi wait_event(fc->blocked_waitq, atomic_read(&fc->num_waiting) == 0); 2156b8f95e5dSMiklos Szeredi } 2157b8f95e5dSMiklos Szeredi 215808cbf542STejun Heo int fuse_dev_release(struct inode *inode, struct file *file) 2159334f485dSMiklos Szeredi { 2160cc080e9eSMiklos Szeredi struct fuse_dev *fud = fuse_get_dev(file); 2161cc080e9eSMiklos Szeredi 2162cc080e9eSMiklos Szeredi if (fud) { 2163cc080e9eSMiklos Szeredi struct fuse_conn *fc = fud->fc; 2164c3696046SMiklos Szeredi struct fuse_pqueue *fpq = &fud->pq; 216545ff350bSMiklos Szeredi LIST_HEAD(to_end); 2166be2ff42cSKirill Tkhai unsigned int i; 2167cc080e9eSMiklos Szeredi 216845ff350bSMiklos Szeredi spin_lock(&fpq->lock); 2169c3696046SMiklos Szeredi WARN_ON(!list_empty(&fpq->io)); 2170be2ff42cSKirill Tkhai for (i = 0; i < FUSE_PQ_HASH_SIZE; i++) 2171be2ff42cSKirill Tkhai list_splice_init(&fpq->processing[i], &to_end); 217245ff350bSMiklos Szeredi spin_unlock(&fpq->lock); 217345ff350bSMiklos Szeredi 217445ff350bSMiklos Szeredi end_requests(fc, &to_end); 217545ff350bSMiklos Szeredi 2176c3696046SMiklos Szeredi /* Are we the last open device? */ 2177c3696046SMiklos Szeredi if (atomic_dec_and_test(&fc->dev_count)) { 2178f88996a9SMiklos Szeredi WARN_ON(fc->iq.fasync != NULL); 2179eb98e3bdSMiklos Szeredi fuse_abort_conn(fc); 2180c3696046SMiklos Szeredi } 2181cc080e9eSMiklos Szeredi fuse_dev_free(fud); 2182385a17bfSJeff Dike } 2183334f485dSMiklos Szeredi return 0; 2184334f485dSMiklos Szeredi } 218508cbf542STejun Heo EXPORT_SYMBOL_GPL(fuse_dev_release); 2186334f485dSMiklos Szeredi 2187385a17bfSJeff Dike static int fuse_dev_fasync(int fd, struct file *file, int on) 2188385a17bfSJeff Dike { 2189cc080e9eSMiklos Szeredi struct fuse_dev *fud = fuse_get_dev(file); 2190cc080e9eSMiklos Szeredi 2191cc080e9eSMiklos Szeredi if (!fud) 2192a87046d8SMiklos Szeredi return -EPERM; 2193385a17bfSJeff Dike 2194385a17bfSJeff Dike /* No locking - fasync_helper does its own locking */ 2195cc080e9eSMiklos Szeredi return fasync_helper(fd, file, on, &fud->fc->iq.fasync); 2196385a17bfSJeff Dike } 2197385a17bfSJeff Dike 219800c570f4SMiklos Szeredi static int fuse_device_clone(struct fuse_conn *fc, struct file *new) 219900c570f4SMiklos Szeredi { 2200cc080e9eSMiklos Szeredi struct fuse_dev *fud; 2201cc080e9eSMiklos Szeredi 220200c570f4SMiklos Szeredi if (new->private_data) 220300c570f4SMiklos Szeredi return -EINVAL; 220400c570f4SMiklos Szeredi 22050cd1eb9aSVivek Goyal fud = fuse_dev_alloc_install(fc); 2206cc080e9eSMiklos Szeredi if (!fud) 2207cc080e9eSMiklos Szeredi return -ENOMEM; 2208cc080e9eSMiklos Szeredi 2209cc080e9eSMiklos Szeredi new->private_data = fud; 2210c3696046SMiklos Szeredi atomic_inc(&fc->dev_count); 221100c570f4SMiklos Szeredi 221200c570f4SMiklos Szeredi return 0; 221300c570f4SMiklos Szeredi } 221400c570f4SMiklos Szeredi 221500c570f4SMiklos Szeredi static long fuse_dev_ioctl(struct file *file, unsigned int cmd, 221600c570f4SMiklos Szeredi unsigned long arg) 221700c570f4SMiklos Szeredi { 221800c570f4SMiklos Szeredi int err = -ENOTTY; 221900c570f4SMiklos Szeredi 222000c570f4SMiklos Szeredi if (cmd == FUSE_DEV_IOC_CLONE) { 222100c570f4SMiklos Szeredi int oldfd; 222200c570f4SMiklos Szeredi 222300c570f4SMiklos Szeredi err = -EFAULT; 222400c570f4SMiklos Szeredi if (!get_user(oldfd, (__u32 __user *) arg)) { 222500c570f4SMiklos Szeredi struct file *old = fget(oldfd); 222600c570f4SMiklos Szeredi 222700c570f4SMiklos Szeredi err = -EINVAL; 222800c570f4SMiklos Szeredi if (old) { 22298ed1f0e2SJann Horn struct fuse_dev *fud = NULL; 22308ed1f0e2SJann Horn 22318ed1f0e2SJann Horn /* 22328ed1f0e2SJann Horn * Check against file->f_op because CUSE 22338ed1f0e2SJann Horn * uses the same ioctl handler. 22348ed1f0e2SJann Horn */ 22358ed1f0e2SJann Horn if (old->f_op == file->f_op && 22368ed1f0e2SJann Horn old->f_cred->user_ns == file->f_cred->user_ns) 22378ed1f0e2SJann Horn fud = fuse_get_dev(old); 223800c570f4SMiklos Szeredi 2239cc080e9eSMiklos Szeredi if (fud) { 224000c570f4SMiklos Szeredi mutex_lock(&fuse_mutex); 2241cc080e9eSMiklos Szeredi err = fuse_device_clone(fud->fc, file); 224200c570f4SMiklos Szeredi mutex_unlock(&fuse_mutex); 224300c570f4SMiklos Szeredi } 224400c570f4SMiklos Szeredi fput(old); 224500c570f4SMiklos Szeredi } 224600c570f4SMiklos Szeredi } 224700c570f4SMiklos Szeredi } 224800c570f4SMiklos Szeredi return err; 224900c570f4SMiklos Szeredi } 225000c570f4SMiklos Szeredi 22514b6f5d20SArjan van de Ven const struct file_operations fuse_dev_operations = { 2252334f485dSMiklos Szeredi .owner = THIS_MODULE, 225394e4fe2cSTom Van Braeckel .open = fuse_dev_open, 2254334f485dSMiklos Szeredi .llseek = no_llseek, 2255fbdbaccaSAl Viro .read_iter = fuse_dev_read, 2256c3021629SMiklos Szeredi .splice_read = fuse_dev_splice_read, 2257fbdbaccaSAl Viro .write_iter = fuse_dev_write, 2258dd3bb14fSMiklos Szeredi .splice_write = fuse_dev_splice_write, 2259334f485dSMiklos Szeredi .poll = fuse_dev_poll, 2260334f485dSMiklos Szeredi .release = fuse_dev_release, 2261385a17bfSJeff Dike .fasync = fuse_dev_fasync, 226200c570f4SMiklos Szeredi .unlocked_ioctl = fuse_dev_ioctl, 226300c570f4SMiklos Szeredi .compat_ioctl = fuse_dev_ioctl, 2264334f485dSMiklos Szeredi }; 226508cbf542STejun Heo EXPORT_SYMBOL_GPL(fuse_dev_operations); 2266334f485dSMiklos Szeredi 2267334f485dSMiklos Szeredi static struct miscdevice fuse_miscdevice = { 2268334f485dSMiklos Szeredi .minor = FUSE_MINOR, 2269334f485dSMiklos Szeredi .name = "fuse", 2270334f485dSMiklos Szeredi .fops = &fuse_dev_operations, 2271334f485dSMiklos Szeredi }; 2272334f485dSMiklos Szeredi 2273334f485dSMiklos Szeredi int __init fuse_dev_init(void) 2274334f485dSMiklos Szeredi { 2275334f485dSMiklos Szeredi int err = -ENOMEM; 2276334f485dSMiklos Szeredi fuse_req_cachep = kmem_cache_create("fuse_request", 2277334f485dSMiklos Szeredi sizeof(struct fuse_req), 227820c2df83SPaul Mundt 0, 0, NULL); 2279334f485dSMiklos Szeredi if (!fuse_req_cachep) 2280334f485dSMiklos Szeredi goto out; 2281334f485dSMiklos Szeredi 2282334f485dSMiklos Szeredi err = misc_register(&fuse_miscdevice); 2283334f485dSMiklos Szeredi if (err) 2284334f485dSMiklos Szeredi goto out_cache_clean; 2285334f485dSMiklos Szeredi 2286334f485dSMiklos Szeredi return 0; 2287334f485dSMiklos Szeredi 2288334f485dSMiklos Szeredi out_cache_clean: 2289334f485dSMiklos Szeredi kmem_cache_destroy(fuse_req_cachep); 2290334f485dSMiklos Szeredi out: 2291334f485dSMiklos Szeredi return err; 2292334f485dSMiklos Szeredi } 2293334f485dSMiklos Szeredi 2294334f485dSMiklos Szeredi void fuse_dev_cleanup(void) 2295334f485dSMiklos Szeredi { 2296334f485dSMiklos Szeredi misc_deregister(&fuse_miscdevice); 2297334f485dSMiklos Szeredi kmem_cache_destroy(fuse_req_cachep); 2298334f485dSMiklos Szeredi } 2299