1334f485dSMiklos Szeredi /* 2334f485dSMiklos Szeredi FUSE: Filesystem in Userspace 3d7133114SMiklos Szeredi Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu> 4334f485dSMiklos Szeredi 5334f485dSMiklos Szeredi This program can be distributed under the terms of the GNU GPL. 6334f485dSMiklos Szeredi See the file COPYING. 7334f485dSMiklos Szeredi */ 8334f485dSMiklos Szeredi 9334f485dSMiklos Szeredi #include "fuse_i.h" 10334f485dSMiklos Szeredi 11334f485dSMiklos Szeredi #include <linux/init.h> 12334f485dSMiklos Szeredi #include <linux/module.h> 13334f485dSMiklos Szeredi #include <linux/poll.h> 14334f485dSMiklos Szeredi #include <linux/uio.h> 15334f485dSMiklos Szeredi #include <linux/miscdevice.h> 16334f485dSMiklos Szeredi #include <linux/pagemap.h> 17334f485dSMiklos Szeredi #include <linux/file.h> 18334f485dSMiklos Szeredi #include <linux/slab.h> 19334f485dSMiklos Szeredi 20334f485dSMiklos Szeredi MODULE_ALIAS_MISCDEV(FUSE_MINOR); 21334f485dSMiklos Szeredi 22334f485dSMiklos Szeredi static kmem_cache_t *fuse_req_cachep; 23334f485dSMiklos Szeredi 248bfc016dSMiklos Szeredi static struct fuse_conn *fuse_get_conn(struct file *file) 25334f485dSMiklos Szeredi { 260720b315SMiklos Szeredi /* 270720b315SMiklos Szeredi * Lockless access is OK, because file->private data is set 280720b315SMiklos Szeredi * once during mount and is valid until the file is released. 290720b315SMiklos Szeredi */ 300720b315SMiklos Szeredi return file->private_data; 31334f485dSMiklos Szeredi } 32334f485dSMiklos Szeredi 338bfc016dSMiklos Szeredi static void fuse_request_init(struct fuse_req *req) 34334f485dSMiklos Szeredi { 35334f485dSMiklos Szeredi memset(req, 0, sizeof(*req)); 36334f485dSMiklos Szeredi INIT_LIST_HEAD(&req->list); 37334f485dSMiklos Szeredi init_waitqueue_head(&req->waitq); 38334f485dSMiklos Szeredi atomic_set(&req->count, 1); 39334f485dSMiklos Szeredi } 40334f485dSMiklos Szeredi 41334f485dSMiklos Szeredi struct fuse_req *fuse_request_alloc(void) 42334f485dSMiklos Szeredi { 43334f485dSMiklos Szeredi struct fuse_req *req = kmem_cache_alloc(fuse_req_cachep, SLAB_KERNEL); 44334f485dSMiklos Szeredi if (req) 45334f485dSMiklos Szeredi fuse_request_init(req); 46334f485dSMiklos Szeredi return req; 47334f485dSMiklos Szeredi } 48334f485dSMiklos Szeredi 49334f485dSMiklos Szeredi void fuse_request_free(struct fuse_req *req) 50334f485dSMiklos Szeredi { 51334f485dSMiklos Szeredi kmem_cache_free(fuse_req_cachep, req); 52334f485dSMiklos Szeredi } 53334f485dSMiklos Szeredi 548bfc016dSMiklos Szeredi static void block_sigs(sigset_t *oldset) 55334f485dSMiklos Szeredi { 56334f485dSMiklos Szeredi sigset_t mask; 57334f485dSMiklos Szeredi 58334f485dSMiklos Szeredi siginitsetinv(&mask, sigmask(SIGKILL)); 59334f485dSMiklos Szeredi sigprocmask(SIG_BLOCK, &mask, oldset); 60334f485dSMiklos Szeredi } 61334f485dSMiklos Szeredi 628bfc016dSMiklos Szeredi static void restore_sigs(sigset_t *oldset) 63334f485dSMiklos Szeredi { 64334f485dSMiklos Szeredi sigprocmask(SIG_SETMASK, oldset, NULL); 65334f485dSMiklos Szeredi } 66334f485dSMiklos Szeredi 6777e7f250SMiklos Szeredi /* 6877e7f250SMiklos Szeredi * Reset request, so that it can be reused 6977e7f250SMiklos Szeredi * 7077e7f250SMiklos Szeredi * The caller must be _very_ careful to make sure, that it is holding 7177e7f250SMiklos Szeredi * the only reference to req 7277e7f250SMiklos Szeredi */ 73334f485dSMiklos Szeredi void fuse_reset_request(struct fuse_req *req) 74334f485dSMiklos Szeredi { 75334f485dSMiklos Szeredi int preallocated = req->preallocated; 76334f485dSMiklos Szeredi BUG_ON(atomic_read(&req->count) != 1); 77334f485dSMiklos Szeredi fuse_request_init(req); 78334f485dSMiklos Szeredi req->preallocated = preallocated; 79334f485dSMiklos Szeredi } 80334f485dSMiklos Szeredi 81334f485dSMiklos Szeredi static void __fuse_get_request(struct fuse_req *req) 82334f485dSMiklos Szeredi { 83334f485dSMiklos Szeredi atomic_inc(&req->count); 84334f485dSMiklos Szeredi } 85334f485dSMiklos Szeredi 86334f485dSMiklos Szeredi /* Must be called with > 1 refcount */ 87334f485dSMiklos Szeredi static void __fuse_put_request(struct fuse_req *req) 88334f485dSMiklos Szeredi { 89334f485dSMiklos Szeredi BUG_ON(atomic_read(&req->count) < 2); 90334f485dSMiklos Szeredi atomic_dec(&req->count); 91334f485dSMiklos Szeredi } 92334f485dSMiklos Szeredi 93334f485dSMiklos Szeredi static struct fuse_req *do_get_request(struct fuse_conn *fc) 94334f485dSMiklos Szeredi { 95334f485dSMiklos Szeredi struct fuse_req *req; 96334f485dSMiklos Szeredi 97d7133114SMiklos Szeredi spin_lock(&fc->lock); 98334f485dSMiklos Szeredi BUG_ON(list_empty(&fc->unused_list)); 99334f485dSMiklos Szeredi req = list_entry(fc->unused_list.next, struct fuse_req, list); 100334f485dSMiklos Szeredi list_del_init(&req->list); 101d7133114SMiklos Szeredi spin_unlock(&fc->lock); 102334f485dSMiklos Szeredi fuse_request_init(req); 103334f485dSMiklos Szeredi req->preallocated = 1; 104334f485dSMiklos Szeredi req->in.h.uid = current->fsuid; 105334f485dSMiklos Szeredi req->in.h.gid = current->fsgid; 106334f485dSMiklos Szeredi req->in.h.pid = current->pid; 107334f485dSMiklos Szeredi return req; 108334f485dSMiklos Szeredi } 109334f485dSMiklos Szeredi 1107c352bdfSMiklos Szeredi /* This can return NULL, but only in case it's interrupted by a SIGKILL */ 111334f485dSMiklos Szeredi struct fuse_req *fuse_get_request(struct fuse_conn *fc) 112334f485dSMiklos Szeredi { 113334f485dSMiklos Szeredi int intr; 114334f485dSMiklos Szeredi sigset_t oldset; 115334f485dSMiklos Szeredi 1160cd5b885SMiklos Szeredi atomic_inc(&fc->num_waiting); 117334f485dSMiklos Szeredi block_sigs(&oldset); 118334f485dSMiklos Szeredi intr = down_interruptible(&fc->outstanding_sem); 119334f485dSMiklos Szeredi restore_sigs(&oldset); 1200cd5b885SMiklos Szeredi if (intr) { 1210cd5b885SMiklos Szeredi atomic_dec(&fc->num_waiting); 1220cd5b885SMiklos Szeredi return NULL; 1230cd5b885SMiklos Szeredi } 1240cd5b885SMiklos Szeredi return do_get_request(fc); 125334f485dSMiklos Szeredi } 126334f485dSMiklos Szeredi 127d7133114SMiklos Szeredi /* Must be called with fc->lock held */ 128334f485dSMiklos Szeredi static void fuse_putback_request(struct fuse_conn *fc, struct fuse_req *req) 129334f485dSMiklos Szeredi { 1300cd5b885SMiklos Szeredi if (req->preallocated) { 1310cd5b885SMiklos Szeredi atomic_dec(&fc->num_waiting); 132334f485dSMiklos Szeredi list_add(&req->list, &fc->unused_list); 1330cd5b885SMiklos Szeredi } else 134334f485dSMiklos Szeredi fuse_request_free(req); 135334f485dSMiklos Szeredi 136334f485dSMiklos Szeredi /* If we are in debt decrease that first */ 137334f485dSMiklos Szeredi if (fc->outstanding_debt) 138334f485dSMiklos Szeredi fc->outstanding_debt--; 139334f485dSMiklos Szeredi else 140334f485dSMiklos Szeredi up(&fc->outstanding_sem); 141334f485dSMiklos Szeredi } 142334f485dSMiklos Szeredi 143334f485dSMiklos Szeredi void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req) 144334f485dSMiklos Szeredi { 1457128ec2aSMiklos Szeredi if (atomic_dec_and_test(&req->count)) { 146d7133114SMiklos Szeredi spin_lock(&fc->lock); 1477128ec2aSMiklos Szeredi fuse_putback_request(fc, req); 148d7133114SMiklos Szeredi spin_unlock(&fc->lock); 1497128ec2aSMiklos Szeredi } 1507128ec2aSMiklos Szeredi } 1517128ec2aSMiklos Szeredi 1527128ec2aSMiklos Szeredi static void fuse_put_request_locked(struct fuse_conn *fc, struct fuse_req *req) 1537128ec2aSMiklos Szeredi { 154334f485dSMiklos Szeredi if (atomic_dec_and_test(&req->count)) 155334f485dSMiklos Szeredi fuse_putback_request(fc, req); 156334f485dSMiklos Szeredi } 157334f485dSMiklos Szeredi 158d7133114SMiklos Szeredi void fuse_release_background(struct fuse_conn *fc, struct fuse_req *req) 1591e9a4ed9SMiklos Szeredi { 1601e9a4ed9SMiklos Szeredi iput(req->inode); 1611e9a4ed9SMiklos Szeredi iput(req->inode2); 1621e9a4ed9SMiklos Szeredi if (req->file) 1631e9a4ed9SMiklos Szeredi fput(req->file); 164d7133114SMiklos Szeredi spin_lock(&fc->lock); 1651e9a4ed9SMiklos Szeredi list_del(&req->bg_entry); 166d7133114SMiklos Szeredi spin_unlock(&fc->lock); 1671e9a4ed9SMiklos Szeredi } 1681e9a4ed9SMiklos Szeredi 169334f485dSMiklos Szeredi /* 170334f485dSMiklos Szeredi * This function is called when a request is finished. Either a reply 171334f485dSMiklos Szeredi * has arrived or it was interrupted (and not yet sent) or some error 172f43b155aSMiklos Szeredi * occurred during communication with userspace, or the device file 173f43b155aSMiklos Szeredi * was closed. In case of a background request the reference to the 174f43b155aSMiklos Szeredi * stored objects are released. The requester thread is woken up (if 17564c6d8edSMiklos Szeredi * still waiting), the 'end' callback is called if given, else the 17664c6d8edSMiklos Szeredi * reference to the request is released 177334f485dSMiklos Szeredi * 1787128ec2aSMiklos Szeredi * Releasing extra reference for foreground requests must be done 1797128ec2aSMiklos Szeredi * within the same locked region as setting state to finished. This 1807128ec2aSMiklos Szeredi * is because fuse_reset_request() may be called after request is 1817128ec2aSMiklos Szeredi * finished and it must be the sole possessor. If request is 1827128ec2aSMiklos Szeredi * interrupted and put in the background, it will return with an error 1837128ec2aSMiklos Szeredi * and hence never be reset and reused. 1847128ec2aSMiklos Szeredi * 185d7133114SMiklos Szeredi * Called with fc->lock, unlocks it 186334f485dSMiklos Szeredi */ 187334f485dSMiklos Szeredi static void request_end(struct fuse_conn *fc, struct fuse_req *req) 188334f485dSMiklos Szeredi { 189d77a1d5bSMiklos Szeredi list_del(&req->list); 19083cfd493SMiklos Szeredi req->state = FUSE_REQ_FINISHED; 1917128ec2aSMiklos Szeredi if (!req->background) { 1927128ec2aSMiklos Szeredi wake_up(&req->waitq); 1937128ec2aSMiklos Szeredi fuse_put_request_locked(fc, req); 194d7133114SMiklos Szeredi spin_unlock(&fc->lock); 1957128ec2aSMiklos Szeredi } else { 1967128ec2aSMiklos Szeredi void (*end) (struct fuse_conn *, struct fuse_req *) = req->end; 1977128ec2aSMiklos Szeredi req->end = NULL; 198d7133114SMiklos Szeredi spin_unlock(&fc->lock); 1991e9a4ed9SMiklos Szeredi down_read(&fc->sbput_sem); 2001e9a4ed9SMiklos Szeredi if (fc->mounted) 201d7133114SMiklos Szeredi fuse_release_background(fc, req); 2021e9a4ed9SMiklos Szeredi up_read(&fc->sbput_sem); 20364c6d8edSMiklos Szeredi if (end) 20464c6d8edSMiklos Szeredi end(fc, req); 20564c6d8edSMiklos Szeredi else 206f43b155aSMiklos Szeredi fuse_put_request(fc, req); 207334f485dSMiklos Szeredi } 2087128ec2aSMiklos Szeredi } 209334f485dSMiklos Szeredi 2101e9a4ed9SMiklos Szeredi /* 2111e9a4ed9SMiklos Szeredi * Unfortunately request interruption not just solves the deadlock 2121e9a4ed9SMiklos Szeredi * problem, it causes problems too. These stem from the fact, that an 2131e9a4ed9SMiklos Szeredi * interrupted request is continued to be processed in userspace, 2141e9a4ed9SMiklos Szeredi * while all the locks and object references (inode and file) held 2151e9a4ed9SMiklos Szeredi * during the operation are released. 2161e9a4ed9SMiklos Szeredi * 2171e9a4ed9SMiklos Szeredi * To release the locks is exactly why there's a need to interrupt the 2181e9a4ed9SMiklos Szeredi * request, so there's not a lot that can be done about this, except 2191e9a4ed9SMiklos Szeredi * introduce additional locking in userspace. 2201e9a4ed9SMiklos Szeredi * 2211e9a4ed9SMiklos Szeredi * More important is to keep inode and file references until userspace 2221e9a4ed9SMiklos Szeredi * has replied, otherwise FORGET and RELEASE could be sent while the 2231e9a4ed9SMiklos Szeredi * inode/file is still used by the filesystem. 2241e9a4ed9SMiklos Szeredi * 2251e9a4ed9SMiklos Szeredi * For this reason the concept of "background" request is introduced. 2261e9a4ed9SMiklos Szeredi * An interrupted request is backgrounded if it has been already sent 2271e9a4ed9SMiklos Szeredi * to userspace. Backgrounding involves getting an extra reference to 2281e9a4ed9SMiklos Szeredi * inode(s) or file used in the request, and adding the request to 2291e9a4ed9SMiklos Szeredi * fc->background list. When a reply is received for a background 2301e9a4ed9SMiklos Szeredi * request, the object references are released, and the request is 2311e9a4ed9SMiklos Szeredi * removed from the list. If the filesystem is unmounted while there 2321e9a4ed9SMiklos Szeredi * are still background requests, the list is walked and references 2331e9a4ed9SMiklos Szeredi * are released as if a reply was received. 2341e9a4ed9SMiklos Szeredi * 2351e9a4ed9SMiklos Szeredi * There's one more use for a background request. The RELEASE message is 2361e9a4ed9SMiklos Szeredi * always sent as background, since it doesn't return an error or 2371e9a4ed9SMiklos Szeredi * data. 2381e9a4ed9SMiklos Szeredi */ 2391e9a4ed9SMiklos Szeredi static void background_request(struct fuse_conn *fc, struct fuse_req *req) 240334f485dSMiklos Szeredi { 241334f485dSMiklos Szeredi req->background = 1; 2421e9a4ed9SMiklos Szeredi list_add(&req->bg_entry, &fc->background); 243334f485dSMiklos Szeredi if (req->inode) 244334f485dSMiklos Szeredi req->inode = igrab(req->inode); 245334f485dSMiklos Szeredi if (req->inode2) 246334f485dSMiklos Szeredi req->inode2 = igrab(req->inode2); 247334f485dSMiklos Szeredi if (req->file) 248334f485dSMiklos Szeredi get_file(req->file); 249334f485dSMiklos Szeredi } 250334f485dSMiklos Szeredi 251d7133114SMiklos Szeredi /* Called with fc->lock held. Releases, and then reacquires it. */ 2527c352bdfSMiklos Szeredi static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req) 253334f485dSMiklos Szeredi { 2547c352bdfSMiklos Szeredi sigset_t oldset; 255334f485dSMiklos Szeredi 256d7133114SMiklos Szeredi spin_unlock(&fc->lock); 2577c352bdfSMiklos Szeredi block_sigs(&oldset); 25883cfd493SMiklos Szeredi wait_event_interruptible(req->waitq, req->state == FUSE_REQ_FINISHED); 2597c352bdfSMiklos Szeredi restore_sigs(&oldset); 260d7133114SMiklos Szeredi spin_lock(&fc->lock); 26169a53bf2SMiklos Szeredi if (req->state == FUSE_REQ_FINISHED && !req->interrupted) 262334f485dSMiklos Szeredi return; 263334f485dSMiklos Szeredi 26469a53bf2SMiklos Szeredi if (!req->interrupted) { 265334f485dSMiklos Szeredi req->out.h.error = -EINTR; 266334f485dSMiklos Szeredi req->interrupted = 1; 26769a53bf2SMiklos Szeredi } 268334f485dSMiklos Szeredi if (req->locked) { 269334f485dSMiklos Szeredi /* This is uninterruptible sleep, because data is 270334f485dSMiklos Szeredi being copied to/from the buffers of req. During 271334f485dSMiklos Szeredi locked state, there mustn't be any filesystem 272334f485dSMiklos Szeredi operation (e.g. page fault), since that could lead 273334f485dSMiklos Szeredi to deadlock */ 274d7133114SMiklos Szeredi spin_unlock(&fc->lock); 275334f485dSMiklos Szeredi wait_event(req->waitq, !req->locked); 276d7133114SMiklos Szeredi spin_lock(&fc->lock); 277334f485dSMiklos Szeredi } 27883cfd493SMiklos Szeredi if (req->state == FUSE_REQ_PENDING) { 279334f485dSMiklos Szeredi list_del(&req->list); 280334f485dSMiklos Szeredi __fuse_put_request(req); 28183cfd493SMiklos Szeredi } else if (req->state == FUSE_REQ_SENT) 2821e9a4ed9SMiklos Szeredi background_request(fc, req); 283334f485dSMiklos Szeredi } 284334f485dSMiklos Szeredi 285334f485dSMiklos Szeredi static unsigned len_args(unsigned numargs, struct fuse_arg *args) 286334f485dSMiklos Szeredi { 287334f485dSMiklos Szeredi unsigned nbytes = 0; 288334f485dSMiklos Szeredi unsigned i; 289334f485dSMiklos Szeredi 290334f485dSMiklos Szeredi for (i = 0; i < numargs; i++) 291334f485dSMiklos Szeredi nbytes += args[i].size; 292334f485dSMiklos Szeredi 293334f485dSMiklos Szeredi return nbytes; 294334f485dSMiklos Szeredi } 295334f485dSMiklos Szeredi 296334f485dSMiklos Szeredi static void queue_request(struct fuse_conn *fc, struct fuse_req *req) 297334f485dSMiklos Szeredi { 298334f485dSMiklos Szeredi fc->reqctr++; 299334f485dSMiklos Szeredi /* zero is special */ 300334f485dSMiklos Szeredi if (fc->reqctr == 0) 301334f485dSMiklos Szeredi fc->reqctr = 1; 302334f485dSMiklos Szeredi req->in.h.unique = fc->reqctr; 303334f485dSMiklos Szeredi req->in.h.len = sizeof(struct fuse_in_header) + 304334f485dSMiklos Szeredi len_args(req->in.numargs, (struct fuse_arg *) req->in.args); 305334f485dSMiklos Szeredi if (!req->preallocated) { 306334f485dSMiklos Szeredi /* If request is not preallocated (either FORGET or 307334f485dSMiklos Szeredi RELEASE), then still decrease outstanding_sem, so 308334f485dSMiklos Szeredi user can't open infinite number of files while not 309334f485dSMiklos Szeredi processing the RELEASE requests. However for 310334f485dSMiklos Szeredi efficiency do it without blocking, so if down() 311334f485dSMiklos Szeredi would block, just increase the debt instead */ 312334f485dSMiklos Szeredi if (down_trylock(&fc->outstanding_sem)) 313334f485dSMiklos Szeredi fc->outstanding_debt++; 314334f485dSMiklos Szeredi } 315334f485dSMiklos Szeredi list_add_tail(&req->list, &fc->pending); 31683cfd493SMiklos Szeredi req->state = FUSE_REQ_PENDING; 317334f485dSMiklos Szeredi wake_up(&fc->waitq); 318385a17bfSJeff Dike kill_fasync(&fc->fasync, SIGIO, POLL_IN); 319334f485dSMiklos Szeredi } 320334f485dSMiklos Szeredi 3217c352bdfSMiklos Szeredi /* 3227c352bdfSMiklos Szeredi * This can only be interrupted by a SIGKILL 3237c352bdfSMiklos Szeredi */ 3247c352bdfSMiklos Szeredi void request_send(struct fuse_conn *fc, struct fuse_req *req) 325334f485dSMiklos Szeredi { 326334f485dSMiklos Szeredi req->isreply = 1; 327d7133114SMiklos Szeredi spin_lock(&fc->lock); 3281e9a4ed9SMiklos Szeredi if (!fc->connected) 329334f485dSMiklos Szeredi req->out.h.error = -ENOTCONN; 330334f485dSMiklos Szeredi else if (fc->conn_error) 331334f485dSMiklos Szeredi req->out.h.error = -ECONNREFUSED; 332334f485dSMiklos Szeredi else { 333334f485dSMiklos Szeredi queue_request(fc, req); 334334f485dSMiklos Szeredi /* acquire extra reference, since request is still needed 335334f485dSMiklos Szeredi after request_end() */ 336334f485dSMiklos Szeredi __fuse_get_request(req); 337334f485dSMiklos Szeredi 3387c352bdfSMiklos Szeredi request_wait_answer(fc, req); 339334f485dSMiklos Szeredi } 340d7133114SMiklos Szeredi spin_unlock(&fc->lock); 341334f485dSMiklos Szeredi } 342334f485dSMiklos Szeredi 343334f485dSMiklos Szeredi static void request_send_nowait(struct fuse_conn *fc, struct fuse_req *req) 344334f485dSMiklos Szeredi { 345d7133114SMiklos Szeredi spin_lock(&fc->lock); 3461e9a4ed9SMiklos Szeredi if (fc->connected) { 347334f485dSMiklos Szeredi queue_request(fc, req); 348d7133114SMiklos Szeredi spin_unlock(&fc->lock); 349334f485dSMiklos Szeredi } else { 350334f485dSMiklos Szeredi req->out.h.error = -ENOTCONN; 351334f485dSMiklos Szeredi request_end(fc, req); 352334f485dSMiklos Szeredi } 353334f485dSMiklos Szeredi } 354334f485dSMiklos Szeredi 355334f485dSMiklos Szeredi void request_send_noreply(struct fuse_conn *fc, struct fuse_req *req) 356334f485dSMiklos Szeredi { 357334f485dSMiklos Szeredi req->isreply = 0; 358334f485dSMiklos Szeredi request_send_nowait(fc, req); 359334f485dSMiklos Szeredi } 360334f485dSMiklos Szeredi 361334f485dSMiklos Szeredi void request_send_background(struct fuse_conn *fc, struct fuse_req *req) 362334f485dSMiklos Szeredi { 363334f485dSMiklos Szeredi req->isreply = 1; 364d7133114SMiklos Szeredi spin_lock(&fc->lock); 3651e9a4ed9SMiklos Szeredi background_request(fc, req); 366d7133114SMiklos Szeredi spin_unlock(&fc->lock); 367334f485dSMiklos Szeredi request_send_nowait(fc, req); 368334f485dSMiklos Szeredi } 369334f485dSMiklos Szeredi 370334f485dSMiklos Szeredi /* 371334f485dSMiklos Szeredi * Lock the request. Up to the next unlock_request() there mustn't be 372334f485dSMiklos Szeredi * anything that could cause a page-fault. If the request was already 373334f485dSMiklos Szeredi * interrupted bail out. 374334f485dSMiklos Szeredi */ 375d7133114SMiklos Szeredi static int lock_request(struct fuse_conn *fc, struct fuse_req *req) 376334f485dSMiklos Szeredi { 377334f485dSMiklos Szeredi int err = 0; 378334f485dSMiklos Szeredi if (req) { 379d7133114SMiklos Szeredi spin_lock(&fc->lock); 380334f485dSMiklos Szeredi if (req->interrupted) 381334f485dSMiklos Szeredi err = -ENOENT; 382334f485dSMiklos Szeredi else 383334f485dSMiklos Szeredi req->locked = 1; 384d7133114SMiklos Szeredi spin_unlock(&fc->lock); 385334f485dSMiklos Szeredi } 386334f485dSMiklos Szeredi return err; 387334f485dSMiklos Szeredi } 388334f485dSMiklos Szeredi 389334f485dSMiklos Szeredi /* 390334f485dSMiklos Szeredi * Unlock request. If it was interrupted during being locked, the 391334f485dSMiklos Szeredi * requester thread is currently waiting for it to be unlocked, so 392334f485dSMiklos Szeredi * wake it up. 393334f485dSMiklos Szeredi */ 394d7133114SMiklos Szeredi static void unlock_request(struct fuse_conn *fc, struct fuse_req *req) 395334f485dSMiklos Szeredi { 396334f485dSMiklos Szeredi if (req) { 397d7133114SMiklos Szeredi spin_lock(&fc->lock); 398334f485dSMiklos Szeredi req->locked = 0; 399334f485dSMiklos Szeredi if (req->interrupted) 400334f485dSMiklos Szeredi wake_up(&req->waitq); 401d7133114SMiklos Szeredi spin_unlock(&fc->lock); 402334f485dSMiklos Szeredi } 403334f485dSMiklos Szeredi } 404334f485dSMiklos Szeredi 405334f485dSMiklos Szeredi struct fuse_copy_state { 406d7133114SMiklos Szeredi struct fuse_conn *fc; 407334f485dSMiklos Szeredi int write; 408334f485dSMiklos Szeredi struct fuse_req *req; 409334f485dSMiklos Szeredi const struct iovec *iov; 410334f485dSMiklos Szeredi unsigned long nr_segs; 411334f485dSMiklos Szeredi unsigned long seglen; 412334f485dSMiklos Szeredi unsigned long addr; 413334f485dSMiklos Szeredi struct page *pg; 414334f485dSMiklos Szeredi void *mapaddr; 415334f485dSMiklos Szeredi void *buf; 416334f485dSMiklos Szeredi unsigned len; 417334f485dSMiklos Szeredi }; 418334f485dSMiklos Szeredi 419d7133114SMiklos Szeredi static void fuse_copy_init(struct fuse_copy_state *cs, struct fuse_conn *fc, 420d7133114SMiklos Szeredi int write, struct fuse_req *req, 421d7133114SMiklos Szeredi const struct iovec *iov, unsigned long nr_segs) 422334f485dSMiklos Szeredi { 423334f485dSMiklos Szeredi memset(cs, 0, sizeof(*cs)); 424d7133114SMiklos Szeredi cs->fc = fc; 425334f485dSMiklos Szeredi cs->write = write; 426334f485dSMiklos Szeredi cs->req = req; 427334f485dSMiklos Szeredi cs->iov = iov; 428334f485dSMiklos Szeredi cs->nr_segs = nr_segs; 429334f485dSMiklos Szeredi } 430334f485dSMiklos Szeredi 431334f485dSMiklos Szeredi /* Unmap and put previous page of userspace buffer */ 4328bfc016dSMiklos Szeredi static void fuse_copy_finish(struct fuse_copy_state *cs) 433334f485dSMiklos Szeredi { 434334f485dSMiklos Szeredi if (cs->mapaddr) { 435334f485dSMiklos Szeredi kunmap_atomic(cs->mapaddr, KM_USER0); 436334f485dSMiklos Szeredi if (cs->write) { 437334f485dSMiklos Szeredi flush_dcache_page(cs->pg); 438334f485dSMiklos Szeredi set_page_dirty_lock(cs->pg); 439334f485dSMiklos Szeredi } 440334f485dSMiklos Szeredi put_page(cs->pg); 441334f485dSMiklos Szeredi cs->mapaddr = NULL; 442334f485dSMiklos Szeredi } 443334f485dSMiklos Szeredi } 444334f485dSMiklos Szeredi 445334f485dSMiklos Szeredi /* 446334f485dSMiklos Szeredi * Get another pagefull of userspace buffer, and map it to kernel 447334f485dSMiklos Szeredi * address space, and lock request 448334f485dSMiklos Szeredi */ 449334f485dSMiklos Szeredi static int fuse_copy_fill(struct fuse_copy_state *cs) 450334f485dSMiklos Szeredi { 451334f485dSMiklos Szeredi unsigned long offset; 452334f485dSMiklos Szeredi int err; 453334f485dSMiklos Szeredi 454d7133114SMiklos Szeredi unlock_request(cs->fc, cs->req); 455334f485dSMiklos Szeredi fuse_copy_finish(cs); 456334f485dSMiklos Szeredi if (!cs->seglen) { 457334f485dSMiklos Szeredi BUG_ON(!cs->nr_segs); 458334f485dSMiklos Szeredi cs->seglen = cs->iov[0].iov_len; 459334f485dSMiklos Szeredi cs->addr = (unsigned long) cs->iov[0].iov_base; 460334f485dSMiklos Szeredi cs->iov ++; 461334f485dSMiklos Szeredi cs->nr_segs --; 462334f485dSMiklos Szeredi } 463334f485dSMiklos Szeredi down_read(¤t->mm->mmap_sem); 464334f485dSMiklos Szeredi err = get_user_pages(current, current->mm, cs->addr, 1, cs->write, 0, 465334f485dSMiklos Szeredi &cs->pg, NULL); 466334f485dSMiklos Szeredi up_read(¤t->mm->mmap_sem); 467334f485dSMiklos Szeredi if (err < 0) 468334f485dSMiklos Szeredi return err; 469334f485dSMiklos Szeredi BUG_ON(err != 1); 470334f485dSMiklos Szeredi offset = cs->addr % PAGE_SIZE; 471334f485dSMiklos Szeredi cs->mapaddr = kmap_atomic(cs->pg, KM_USER0); 472334f485dSMiklos Szeredi cs->buf = cs->mapaddr + offset; 473334f485dSMiklos Szeredi cs->len = min(PAGE_SIZE - offset, cs->seglen); 474334f485dSMiklos Szeredi cs->seglen -= cs->len; 475334f485dSMiklos Szeredi cs->addr += cs->len; 476334f485dSMiklos Szeredi 477d7133114SMiklos Szeredi return lock_request(cs->fc, cs->req); 478334f485dSMiklos Szeredi } 479334f485dSMiklos Szeredi 480334f485dSMiklos Szeredi /* Do as much copy to/from userspace buffer as we can */ 4818bfc016dSMiklos Szeredi static int fuse_copy_do(struct fuse_copy_state *cs, void **val, unsigned *size) 482334f485dSMiklos Szeredi { 483334f485dSMiklos Szeredi unsigned ncpy = min(*size, cs->len); 484334f485dSMiklos Szeredi if (val) { 485334f485dSMiklos Szeredi if (cs->write) 486334f485dSMiklos Szeredi memcpy(cs->buf, *val, ncpy); 487334f485dSMiklos Szeredi else 488334f485dSMiklos Szeredi memcpy(*val, cs->buf, ncpy); 489334f485dSMiklos Szeredi *val += ncpy; 490334f485dSMiklos Szeredi } 491334f485dSMiklos Szeredi *size -= ncpy; 492334f485dSMiklos Szeredi cs->len -= ncpy; 493334f485dSMiklos Szeredi cs->buf += ncpy; 494334f485dSMiklos Szeredi return ncpy; 495334f485dSMiklos Szeredi } 496334f485dSMiklos Szeredi 497334f485dSMiklos Szeredi /* 498334f485dSMiklos Szeredi * Copy a page in the request to/from the userspace buffer. Must be 499334f485dSMiklos Szeredi * done atomically 500334f485dSMiklos Szeredi */ 5018bfc016dSMiklos Szeredi static int fuse_copy_page(struct fuse_copy_state *cs, struct page *page, 502334f485dSMiklos Szeredi unsigned offset, unsigned count, int zeroing) 503334f485dSMiklos Szeredi { 504334f485dSMiklos Szeredi if (page && zeroing && count < PAGE_SIZE) { 505334f485dSMiklos Szeredi void *mapaddr = kmap_atomic(page, KM_USER1); 506334f485dSMiklos Szeredi memset(mapaddr, 0, PAGE_SIZE); 507334f485dSMiklos Szeredi kunmap_atomic(mapaddr, KM_USER1); 508334f485dSMiklos Szeredi } 509334f485dSMiklos Szeredi while (count) { 510334f485dSMiklos Szeredi int err; 511334f485dSMiklos Szeredi if (!cs->len && (err = fuse_copy_fill(cs))) 512334f485dSMiklos Szeredi return err; 513334f485dSMiklos Szeredi if (page) { 514334f485dSMiklos Szeredi void *mapaddr = kmap_atomic(page, KM_USER1); 515334f485dSMiklos Szeredi void *buf = mapaddr + offset; 516334f485dSMiklos Szeredi offset += fuse_copy_do(cs, &buf, &count); 517334f485dSMiklos Szeredi kunmap_atomic(mapaddr, KM_USER1); 518334f485dSMiklos Szeredi } else 519334f485dSMiklos Szeredi offset += fuse_copy_do(cs, NULL, &count); 520334f485dSMiklos Szeredi } 521334f485dSMiklos Szeredi if (page && !cs->write) 522334f485dSMiklos Szeredi flush_dcache_page(page); 523334f485dSMiklos Szeredi return 0; 524334f485dSMiklos Szeredi } 525334f485dSMiklos Szeredi 526334f485dSMiklos Szeredi /* Copy pages in the request to/from userspace buffer */ 527334f485dSMiklos Szeredi static int fuse_copy_pages(struct fuse_copy_state *cs, unsigned nbytes, 528334f485dSMiklos Szeredi int zeroing) 529334f485dSMiklos Szeredi { 530334f485dSMiklos Szeredi unsigned i; 531334f485dSMiklos Szeredi struct fuse_req *req = cs->req; 532334f485dSMiklos Szeredi unsigned offset = req->page_offset; 533334f485dSMiklos Szeredi unsigned count = min(nbytes, (unsigned) PAGE_SIZE - offset); 534334f485dSMiklos Szeredi 535334f485dSMiklos Szeredi for (i = 0; i < req->num_pages && (nbytes || zeroing); i++) { 536334f485dSMiklos Szeredi struct page *page = req->pages[i]; 537334f485dSMiklos Szeredi int err = fuse_copy_page(cs, page, offset, count, zeroing); 538334f485dSMiklos Szeredi if (err) 539334f485dSMiklos Szeredi return err; 540334f485dSMiklos Szeredi 541334f485dSMiklos Szeredi nbytes -= count; 542334f485dSMiklos Szeredi count = min(nbytes, (unsigned) PAGE_SIZE); 543334f485dSMiklos Szeredi offset = 0; 544334f485dSMiklos Szeredi } 545334f485dSMiklos Szeredi return 0; 546334f485dSMiklos Szeredi } 547334f485dSMiklos Szeredi 548334f485dSMiklos Szeredi /* Copy a single argument in the request to/from userspace buffer */ 549334f485dSMiklos Szeredi static int fuse_copy_one(struct fuse_copy_state *cs, void *val, unsigned size) 550334f485dSMiklos Szeredi { 551334f485dSMiklos Szeredi while (size) { 552334f485dSMiklos Szeredi int err; 553334f485dSMiklos Szeredi if (!cs->len && (err = fuse_copy_fill(cs))) 554334f485dSMiklos Szeredi return err; 555334f485dSMiklos Szeredi fuse_copy_do(cs, &val, &size); 556334f485dSMiklos Szeredi } 557334f485dSMiklos Szeredi return 0; 558334f485dSMiklos Szeredi } 559334f485dSMiklos Szeredi 560334f485dSMiklos Szeredi /* Copy request arguments to/from userspace buffer */ 561334f485dSMiklos Szeredi static int fuse_copy_args(struct fuse_copy_state *cs, unsigned numargs, 562334f485dSMiklos Szeredi unsigned argpages, struct fuse_arg *args, 563334f485dSMiklos Szeredi int zeroing) 564334f485dSMiklos Szeredi { 565334f485dSMiklos Szeredi int err = 0; 566334f485dSMiklos Szeredi unsigned i; 567334f485dSMiklos Szeredi 568334f485dSMiklos Szeredi for (i = 0; !err && i < numargs; i++) { 569334f485dSMiklos Szeredi struct fuse_arg *arg = &args[i]; 570334f485dSMiklos Szeredi if (i == numargs - 1 && argpages) 571334f485dSMiklos Szeredi err = fuse_copy_pages(cs, arg->size, zeroing); 572334f485dSMiklos Szeredi else 573334f485dSMiklos Szeredi err = fuse_copy_one(cs, arg->value, arg->size); 574334f485dSMiklos Szeredi } 575334f485dSMiklos Szeredi return err; 576334f485dSMiklos Szeredi } 577334f485dSMiklos Szeredi 578334f485dSMiklos Szeredi /* Wait until a request is available on the pending list */ 579334f485dSMiklos Szeredi static void request_wait(struct fuse_conn *fc) 580334f485dSMiklos Szeredi { 581334f485dSMiklos Szeredi DECLARE_WAITQUEUE(wait, current); 582334f485dSMiklos Szeredi 583334f485dSMiklos Szeredi add_wait_queue_exclusive(&fc->waitq, &wait); 5849ba7cbbaSMiklos Szeredi while (fc->connected && list_empty(&fc->pending)) { 585334f485dSMiklos Szeredi set_current_state(TASK_INTERRUPTIBLE); 586334f485dSMiklos Szeredi if (signal_pending(current)) 587334f485dSMiklos Szeredi break; 588334f485dSMiklos Szeredi 589d7133114SMiklos Szeredi spin_unlock(&fc->lock); 590334f485dSMiklos Szeredi schedule(); 591d7133114SMiklos Szeredi spin_lock(&fc->lock); 592334f485dSMiklos Szeredi } 593334f485dSMiklos Szeredi set_current_state(TASK_RUNNING); 594334f485dSMiklos Szeredi remove_wait_queue(&fc->waitq, &wait); 595334f485dSMiklos Szeredi } 596334f485dSMiklos Szeredi 597334f485dSMiklos Szeredi /* 598334f485dSMiklos Szeredi * Read a single request into the userspace filesystem's buffer. This 599334f485dSMiklos Szeredi * function waits until a request is available, then removes it from 600334f485dSMiklos Szeredi * the pending list and copies request data to userspace buffer. If 601334f485dSMiklos Szeredi * no reply is needed (FORGET) or request has been interrupted or 602334f485dSMiklos Szeredi * there was an error during the copying then it's finished by calling 603334f485dSMiklos Szeredi * request_end(). Otherwise add it to the processing list, and set 604334f485dSMiklos Szeredi * the 'sent' flag. 605334f485dSMiklos Szeredi */ 606334f485dSMiklos Szeredi static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov, 607334f485dSMiklos Szeredi unsigned long nr_segs, loff_t *off) 608334f485dSMiklos Szeredi { 609334f485dSMiklos Szeredi int err; 610334f485dSMiklos Szeredi struct fuse_req *req; 611334f485dSMiklos Szeredi struct fuse_in *in; 612334f485dSMiklos Szeredi struct fuse_copy_state cs; 613334f485dSMiklos Szeredi unsigned reqsize; 6140720b315SMiklos Szeredi struct fuse_conn *fc = fuse_get_conn(file); 6150720b315SMiklos Szeredi if (!fc) 6160720b315SMiklos Szeredi return -EPERM; 617334f485dSMiklos Szeredi 6181d3d752bSMiklos Szeredi restart: 619d7133114SMiklos Szeredi spin_lock(&fc->lock); 620e5ac1d1eSJeff Dike err = -EAGAIN; 621e5ac1d1eSJeff Dike if ((file->f_flags & O_NONBLOCK) && fc->connected && 622e5ac1d1eSJeff Dike list_empty(&fc->pending)) 623e5ac1d1eSJeff Dike goto err_unlock; 624e5ac1d1eSJeff Dike 625334f485dSMiklos Szeredi request_wait(fc); 626334f485dSMiklos Szeredi err = -ENODEV; 6279ba7cbbaSMiklos Szeredi if (!fc->connected) 628334f485dSMiklos Szeredi goto err_unlock; 629334f485dSMiklos Szeredi err = -ERESTARTSYS; 630334f485dSMiklos Szeredi if (list_empty(&fc->pending)) 631334f485dSMiklos Szeredi goto err_unlock; 632334f485dSMiklos Szeredi 633334f485dSMiklos Szeredi req = list_entry(fc->pending.next, struct fuse_req, list); 63483cfd493SMiklos Szeredi req->state = FUSE_REQ_READING; 635d77a1d5bSMiklos Szeredi list_move(&req->list, &fc->io); 636334f485dSMiklos Szeredi 637334f485dSMiklos Szeredi in = &req->in; 6381d3d752bSMiklos Szeredi reqsize = in->h.len; 6391d3d752bSMiklos Szeredi /* If request is too large, reply with an error and restart the read */ 6401d3d752bSMiklos Szeredi if (iov_length(iov, nr_segs) < reqsize) { 6411d3d752bSMiklos Szeredi req->out.h.error = -EIO; 6421d3d752bSMiklos Szeredi /* SETXATTR is special, since it may contain too large data */ 6431d3d752bSMiklos Szeredi if (in->h.opcode == FUSE_SETXATTR) 6441d3d752bSMiklos Szeredi req->out.h.error = -E2BIG; 6451d3d752bSMiklos Szeredi request_end(fc, req); 6461d3d752bSMiklos Szeredi goto restart; 6471d3d752bSMiklos Szeredi } 648d7133114SMiklos Szeredi spin_unlock(&fc->lock); 649d7133114SMiklos Szeredi fuse_copy_init(&cs, fc, 1, req, iov, nr_segs); 650334f485dSMiklos Szeredi err = fuse_copy_one(&cs, &in->h, sizeof(in->h)); 651334f485dSMiklos Szeredi if (!err) 652334f485dSMiklos Szeredi err = fuse_copy_args(&cs, in->numargs, in->argpages, 653334f485dSMiklos Szeredi (struct fuse_arg *) in->args, 0); 654334f485dSMiklos Szeredi fuse_copy_finish(&cs); 655d7133114SMiklos Szeredi spin_lock(&fc->lock); 656334f485dSMiklos Szeredi req->locked = 0; 657334f485dSMiklos Szeredi if (!err && req->interrupted) 658334f485dSMiklos Szeredi err = -ENOENT; 659334f485dSMiklos Szeredi if (err) { 660334f485dSMiklos Szeredi if (!req->interrupted) 661334f485dSMiklos Szeredi req->out.h.error = -EIO; 662334f485dSMiklos Szeredi request_end(fc, req); 663334f485dSMiklos Szeredi return err; 664334f485dSMiklos Szeredi } 665334f485dSMiklos Szeredi if (!req->isreply) 666334f485dSMiklos Szeredi request_end(fc, req); 667334f485dSMiklos Szeredi else { 66883cfd493SMiklos Szeredi req->state = FUSE_REQ_SENT; 669d77a1d5bSMiklos Szeredi list_move_tail(&req->list, &fc->processing); 670d7133114SMiklos Szeredi spin_unlock(&fc->lock); 671334f485dSMiklos Szeredi } 672334f485dSMiklos Szeredi return reqsize; 673334f485dSMiklos Szeredi 674334f485dSMiklos Szeredi err_unlock: 675d7133114SMiklos Szeredi spin_unlock(&fc->lock); 676334f485dSMiklos Szeredi return err; 677334f485dSMiklos Szeredi } 678334f485dSMiklos Szeredi 679334f485dSMiklos Szeredi static ssize_t fuse_dev_read(struct file *file, char __user *buf, 680334f485dSMiklos Szeredi size_t nbytes, loff_t *off) 681334f485dSMiklos Szeredi { 682334f485dSMiklos Szeredi struct iovec iov; 683334f485dSMiklos Szeredi iov.iov_len = nbytes; 684334f485dSMiklos Szeredi iov.iov_base = buf; 685334f485dSMiklos Szeredi return fuse_dev_readv(file, &iov, 1, off); 686334f485dSMiklos Szeredi } 687334f485dSMiklos Szeredi 688334f485dSMiklos Szeredi /* Look up request on processing list by unique ID */ 689334f485dSMiklos Szeredi static struct fuse_req *request_find(struct fuse_conn *fc, u64 unique) 690334f485dSMiklos Szeredi { 691334f485dSMiklos Szeredi struct list_head *entry; 692334f485dSMiklos Szeredi 693334f485dSMiklos Szeredi list_for_each(entry, &fc->processing) { 694334f485dSMiklos Szeredi struct fuse_req *req; 695334f485dSMiklos Szeredi req = list_entry(entry, struct fuse_req, list); 696334f485dSMiklos Szeredi if (req->in.h.unique == unique) 697334f485dSMiklos Szeredi return req; 698334f485dSMiklos Szeredi } 699334f485dSMiklos Szeredi return NULL; 700334f485dSMiklos Szeredi } 701334f485dSMiklos Szeredi 702334f485dSMiklos Szeredi static int copy_out_args(struct fuse_copy_state *cs, struct fuse_out *out, 703334f485dSMiklos Szeredi unsigned nbytes) 704334f485dSMiklos Szeredi { 705334f485dSMiklos Szeredi unsigned reqsize = sizeof(struct fuse_out_header); 706334f485dSMiklos Szeredi 707334f485dSMiklos Szeredi if (out->h.error) 708334f485dSMiklos Szeredi return nbytes != reqsize ? -EINVAL : 0; 709334f485dSMiklos Szeredi 710334f485dSMiklos Szeredi reqsize += len_args(out->numargs, out->args); 711334f485dSMiklos Szeredi 712334f485dSMiklos Szeredi if (reqsize < nbytes || (reqsize > nbytes && !out->argvar)) 713334f485dSMiklos Szeredi return -EINVAL; 714334f485dSMiklos Szeredi else if (reqsize > nbytes) { 715334f485dSMiklos Szeredi struct fuse_arg *lastarg = &out->args[out->numargs-1]; 716334f485dSMiklos Szeredi unsigned diffsize = reqsize - nbytes; 717334f485dSMiklos Szeredi if (diffsize > lastarg->size) 718334f485dSMiklos Szeredi return -EINVAL; 719334f485dSMiklos Szeredi lastarg->size -= diffsize; 720334f485dSMiklos Szeredi } 721334f485dSMiklos Szeredi return fuse_copy_args(cs, out->numargs, out->argpages, out->args, 722334f485dSMiklos Szeredi out->page_zeroing); 723334f485dSMiklos Szeredi } 724334f485dSMiklos Szeredi 725334f485dSMiklos Szeredi /* 726334f485dSMiklos Szeredi * Write a single reply to a request. First the header is copied from 727334f485dSMiklos Szeredi * the write buffer. The request is then searched on the processing 728334f485dSMiklos Szeredi * list by the unique ID found in the header. If found, then remove 729334f485dSMiklos Szeredi * it from the list and copy the rest of the buffer to the request. 730334f485dSMiklos Szeredi * The request is finished by calling request_end() 731334f485dSMiklos Szeredi */ 732334f485dSMiklos Szeredi static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov, 733334f485dSMiklos Szeredi unsigned long nr_segs, loff_t *off) 734334f485dSMiklos Szeredi { 735334f485dSMiklos Szeredi int err; 736334f485dSMiklos Szeredi unsigned nbytes = iov_length(iov, nr_segs); 737334f485dSMiklos Szeredi struct fuse_req *req; 738334f485dSMiklos Szeredi struct fuse_out_header oh; 739334f485dSMiklos Szeredi struct fuse_copy_state cs; 740334f485dSMiklos Szeredi struct fuse_conn *fc = fuse_get_conn(file); 741334f485dSMiklos Szeredi if (!fc) 742334f485dSMiklos Szeredi return -ENODEV; 743334f485dSMiklos Szeredi 744d7133114SMiklos Szeredi fuse_copy_init(&cs, fc, 0, NULL, iov, nr_segs); 745334f485dSMiklos Szeredi if (nbytes < sizeof(struct fuse_out_header)) 746334f485dSMiklos Szeredi return -EINVAL; 747334f485dSMiklos Szeredi 748334f485dSMiklos Szeredi err = fuse_copy_one(&cs, &oh, sizeof(oh)); 749334f485dSMiklos Szeredi if (err) 750334f485dSMiklos Szeredi goto err_finish; 751334f485dSMiklos Szeredi err = -EINVAL; 752334f485dSMiklos Szeredi if (!oh.unique || oh.error <= -1000 || oh.error > 0 || 753334f485dSMiklos Szeredi oh.len != nbytes) 754334f485dSMiklos Szeredi goto err_finish; 755334f485dSMiklos Szeredi 756d7133114SMiklos Szeredi spin_lock(&fc->lock); 75769a53bf2SMiklos Szeredi err = -ENOENT; 75869a53bf2SMiklos Szeredi if (!fc->connected) 75969a53bf2SMiklos Szeredi goto err_unlock; 76069a53bf2SMiklos Szeredi 761334f485dSMiklos Szeredi req = request_find(fc, oh.unique); 762334f485dSMiklos Szeredi err = -EINVAL; 763334f485dSMiklos Szeredi if (!req) 764334f485dSMiklos Szeredi goto err_unlock; 765334f485dSMiklos Szeredi 766334f485dSMiklos Szeredi if (req->interrupted) { 767d7133114SMiklos Szeredi spin_unlock(&fc->lock); 768334f485dSMiklos Szeredi fuse_copy_finish(&cs); 769d7133114SMiklos Szeredi spin_lock(&fc->lock); 770222f1d69SMiklos Szeredi request_end(fc, req); 771334f485dSMiklos Szeredi return -ENOENT; 772334f485dSMiklos Szeredi } 773d77a1d5bSMiklos Szeredi list_move(&req->list, &fc->io); 774334f485dSMiklos Szeredi req->out.h = oh; 775334f485dSMiklos Szeredi req->locked = 1; 776334f485dSMiklos Szeredi cs.req = req; 777d7133114SMiklos Szeredi spin_unlock(&fc->lock); 778334f485dSMiklos Szeredi 779334f485dSMiklos Szeredi err = copy_out_args(&cs, &req->out, nbytes); 780334f485dSMiklos Szeredi fuse_copy_finish(&cs); 781334f485dSMiklos Szeredi 782d7133114SMiklos Szeredi spin_lock(&fc->lock); 783334f485dSMiklos Szeredi req->locked = 0; 784334f485dSMiklos Szeredi if (!err) { 785334f485dSMiklos Szeredi if (req->interrupted) 786334f485dSMiklos Szeredi err = -ENOENT; 787334f485dSMiklos Szeredi } else if (!req->interrupted) 788334f485dSMiklos Szeredi req->out.h.error = -EIO; 789334f485dSMiklos Szeredi request_end(fc, req); 790334f485dSMiklos Szeredi 791334f485dSMiklos Szeredi return err ? err : nbytes; 792334f485dSMiklos Szeredi 793334f485dSMiklos Szeredi err_unlock: 794d7133114SMiklos Szeredi spin_unlock(&fc->lock); 795334f485dSMiklos Szeredi err_finish: 796334f485dSMiklos Szeredi fuse_copy_finish(&cs); 797334f485dSMiklos Szeredi return err; 798334f485dSMiklos Szeredi } 799334f485dSMiklos Szeredi 800334f485dSMiklos Szeredi static ssize_t fuse_dev_write(struct file *file, const char __user *buf, 801334f485dSMiklos Szeredi size_t nbytes, loff_t *off) 802334f485dSMiklos Szeredi { 803334f485dSMiklos Szeredi struct iovec iov; 804334f485dSMiklos Szeredi iov.iov_len = nbytes; 805334f485dSMiklos Szeredi iov.iov_base = (char __user *) buf; 806334f485dSMiklos Szeredi return fuse_dev_writev(file, &iov, 1, off); 807334f485dSMiklos Szeredi } 808334f485dSMiklos Szeredi 809334f485dSMiklos Szeredi static unsigned fuse_dev_poll(struct file *file, poll_table *wait) 810334f485dSMiklos Szeredi { 811334f485dSMiklos Szeredi unsigned mask = POLLOUT | POLLWRNORM; 8127025d9adSMiklos Szeredi struct fuse_conn *fc = fuse_get_conn(file); 813334f485dSMiklos Szeredi if (!fc) 8147025d9adSMiklos Szeredi return POLLERR; 815334f485dSMiklos Szeredi 816334f485dSMiklos Szeredi poll_wait(file, &fc->waitq, wait); 817334f485dSMiklos Szeredi 818d7133114SMiklos Szeredi spin_lock(&fc->lock); 8197025d9adSMiklos Szeredi if (!fc->connected) 8207025d9adSMiklos Szeredi mask = POLLERR; 8217025d9adSMiklos Szeredi else if (!list_empty(&fc->pending)) 822334f485dSMiklos Szeredi mask |= POLLIN | POLLRDNORM; 823d7133114SMiklos Szeredi spin_unlock(&fc->lock); 824334f485dSMiklos Szeredi 825334f485dSMiklos Szeredi return mask; 826334f485dSMiklos Szeredi } 827334f485dSMiklos Szeredi 82869a53bf2SMiklos Szeredi /* 82969a53bf2SMiklos Szeredi * Abort all requests on the given list (pending or processing) 83069a53bf2SMiklos Szeredi * 831d7133114SMiklos Szeredi * This function releases and reacquires fc->lock 83269a53bf2SMiklos Szeredi */ 833334f485dSMiklos Szeredi static void end_requests(struct fuse_conn *fc, struct list_head *head) 834334f485dSMiklos Szeredi { 835334f485dSMiklos Szeredi while (!list_empty(head)) { 836334f485dSMiklos Szeredi struct fuse_req *req; 837334f485dSMiklos Szeredi req = list_entry(head->next, struct fuse_req, list); 838334f485dSMiklos Szeredi req->out.h.error = -ECONNABORTED; 839334f485dSMiklos Szeredi request_end(fc, req); 840d7133114SMiklos Szeredi spin_lock(&fc->lock); 841334f485dSMiklos Szeredi } 842334f485dSMiklos Szeredi } 843334f485dSMiklos Szeredi 84469a53bf2SMiklos Szeredi /* 84569a53bf2SMiklos Szeredi * Abort requests under I/O 84669a53bf2SMiklos Szeredi * 84769a53bf2SMiklos Szeredi * The requests are set to interrupted and finished, and the request 84869a53bf2SMiklos Szeredi * waiter is woken up. This will make request_wait_answer() wait 84969a53bf2SMiklos Szeredi * until the request is unlocked and then return. 85064c6d8edSMiklos Szeredi * 85164c6d8edSMiklos Szeredi * If the request is asynchronous, then the end function needs to be 85264c6d8edSMiklos Szeredi * called after waiting for the request to be unlocked (if it was 85364c6d8edSMiklos Szeredi * locked). 85469a53bf2SMiklos Szeredi */ 85569a53bf2SMiklos Szeredi static void end_io_requests(struct fuse_conn *fc) 85669a53bf2SMiklos Szeredi { 85769a53bf2SMiklos Szeredi while (!list_empty(&fc->io)) { 85864c6d8edSMiklos Szeredi struct fuse_req *req = 85964c6d8edSMiklos Szeredi list_entry(fc->io.next, struct fuse_req, list); 86064c6d8edSMiklos Szeredi void (*end) (struct fuse_conn *, struct fuse_req *) = req->end; 86164c6d8edSMiklos Szeredi 86269a53bf2SMiklos Szeredi req->interrupted = 1; 86369a53bf2SMiklos Szeredi req->out.h.error = -ECONNABORTED; 86469a53bf2SMiklos Szeredi req->state = FUSE_REQ_FINISHED; 86569a53bf2SMiklos Szeredi list_del_init(&req->list); 86669a53bf2SMiklos Szeredi wake_up(&req->waitq); 86764c6d8edSMiklos Szeredi if (end) { 86864c6d8edSMiklos Szeredi req->end = NULL; 86964c6d8edSMiklos Szeredi /* The end function will consume this reference */ 87064c6d8edSMiklos Szeredi __fuse_get_request(req); 871d7133114SMiklos Szeredi spin_unlock(&fc->lock); 87264c6d8edSMiklos Szeredi wait_event(req->waitq, !req->locked); 87364c6d8edSMiklos Szeredi end(fc, req); 874d7133114SMiklos Szeredi spin_lock(&fc->lock); 87564c6d8edSMiklos Szeredi } 87669a53bf2SMiklos Szeredi } 87769a53bf2SMiklos Szeredi } 87869a53bf2SMiklos Szeredi 87969a53bf2SMiklos Szeredi /* 88069a53bf2SMiklos Szeredi * Abort all requests. 88169a53bf2SMiklos Szeredi * 88269a53bf2SMiklos Szeredi * Emergency exit in case of a malicious or accidental deadlock, or 88369a53bf2SMiklos Szeredi * just a hung filesystem. 88469a53bf2SMiklos Szeredi * 88569a53bf2SMiklos Szeredi * The same effect is usually achievable through killing the 88669a53bf2SMiklos Szeredi * filesystem daemon and all users of the filesystem. The exception 88769a53bf2SMiklos Szeredi * is the combination of an asynchronous request and the tricky 88869a53bf2SMiklos Szeredi * deadlock (see Documentation/filesystems/fuse.txt). 88969a53bf2SMiklos Szeredi * 89069a53bf2SMiklos Szeredi * During the aborting, progression of requests from the pending and 89169a53bf2SMiklos Szeredi * processing lists onto the io list, and progression of new requests 89269a53bf2SMiklos Szeredi * onto the pending list is prevented by req->connected being false. 89369a53bf2SMiklos Szeredi * 89469a53bf2SMiklos Szeredi * Progression of requests under I/O to the processing list is 89569a53bf2SMiklos Szeredi * prevented by the req->interrupted flag being true for these 89669a53bf2SMiklos Szeredi * requests. For this reason requests on the io list must be aborted 89769a53bf2SMiklos Szeredi * first. 89869a53bf2SMiklos Szeredi */ 89969a53bf2SMiklos Szeredi void fuse_abort_conn(struct fuse_conn *fc) 90069a53bf2SMiklos Szeredi { 901d7133114SMiklos Szeredi spin_lock(&fc->lock); 90269a53bf2SMiklos Szeredi if (fc->connected) { 90369a53bf2SMiklos Szeredi fc->connected = 0; 90469a53bf2SMiklos Szeredi end_io_requests(fc); 90569a53bf2SMiklos Szeredi end_requests(fc, &fc->pending); 90669a53bf2SMiklos Szeredi end_requests(fc, &fc->processing); 90769a53bf2SMiklos Szeredi wake_up_all(&fc->waitq); 908385a17bfSJeff Dike kill_fasync(&fc->fasync, SIGIO, POLL_IN); 90969a53bf2SMiklos Szeredi } 910d7133114SMiklos Szeredi spin_unlock(&fc->lock); 91169a53bf2SMiklos Szeredi } 91269a53bf2SMiklos Szeredi 913334f485dSMiklos Szeredi static int fuse_dev_release(struct inode *inode, struct file *file) 914334f485dSMiklos Szeredi { 9150720b315SMiklos Szeredi struct fuse_conn *fc = fuse_get_conn(file); 916334f485dSMiklos Szeredi if (fc) { 917d7133114SMiklos Szeredi spin_lock(&fc->lock); 9181e9a4ed9SMiklos Szeredi fc->connected = 0; 919334f485dSMiklos Szeredi end_requests(fc, &fc->pending); 920334f485dSMiklos Szeredi end_requests(fc, &fc->processing); 921d7133114SMiklos Szeredi spin_unlock(&fc->lock); 922385a17bfSJeff Dike fasync_helper(-1, file, 0, &fc->fasync); 923f543f253SMiklos Szeredi kobject_put(&fc->kobj); 924385a17bfSJeff Dike } 925f543f253SMiklos Szeredi 926334f485dSMiklos Szeredi return 0; 927334f485dSMiklos Szeredi } 928334f485dSMiklos Szeredi 929385a17bfSJeff Dike static int fuse_dev_fasync(int fd, struct file *file, int on) 930385a17bfSJeff Dike { 931385a17bfSJeff Dike struct fuse_conn *fc = fuse_get_conn(file); 932385a17bfSJeff Dike if (!fc) 933385a17bfSJeff Dike return -ENODEV; 934385a17bfSJeff Dike 935385a17bfSJeff Dike /* No locking - fasync_helper does its own locking */ 936385a17bfSJeff Dike return fasync_helper(fd, file, on, &fc->fasync); 937385a17bfSJeff Dike } 938385a17bfSJeff Dike 9394b6f5d20SArjan van de Ven const struct file_operations fuse_dev_operations = { 940334f485dSMiklos Szeredi .owner = THIS_MODULE, 941334f485dSMiklos Szeredi .llseek = no_llseek, 942334f485dSMiklos Szeredi .read = fuse_dev_read, 943334f485dSMiklos Szeredi .readv = fuse_dev_readv, 944334f485dSMiklos Szeredi .write = fuse_dev_write, 945334f485dSMiklos Szeredi .writev = fuse_dev_writev, 946334f485dSMiklos Szeredi .poll = fuse_dev_poll, 947334f485dSMiklos Szeredi .release = fuse_dev_release, 948385a17bfSJeff Dike .fasync = fuse_dev_fasync, 949334f485dSMiklos Szeredi }; 950334f485dSMiklos Szeredi 951334f485dSMiklos Szeredi static struct miscdevice fuse_miscdevice = { 952334f485dSMiklos Szeredi .minor = FUSE_MINOR, 953334f485dSMiklos Szeredi .name = "fuse", 954334f485dSMiklos Szeredi .fops = &fuse_dev_operations, 955334f485dSMiklos Szeredi }; 956334f485dSMiklos Szeredi 957334f485dSMiklos Szeredi int __init fuse_dev_init(void) 958334f485dSMiklos Szeredi { 959334f485dSMiklos Szeredi int err = -ENOMEM; 960334f485dSMiklos Szeredi fuse_req_cachep = kmem_cache_create("fuse_request", 961334f485dSMiklos Szeredi sizeof(struct fuse_req), 962334f485dSMiklos Szeredi 0, 0, NULL, NULL); 963334f485dSMiklos Szeredi if (!fuse_req_cachep) 964334f485dSMiklos Szeredi goto out; 965334f485dSMiklos Szeredi 966334f485dSMiklos Szeredi err = misc_register(&fuse_miscdevice); 967334f485dSMiklos Szeredi if (err) 968334f485dSMiklos Szeredi goto out_cache_clean; 969334f485dSMiklos Szeredi 970334f485dSMiklos Szeredi return 0; 971334f485dSMiklos Szeredi 972334f485dSMiklos Szeredi out_cache_clean: 973334f485dSMiklos Szeredi kmem_cache_destroy(fuse_req_cachep); 974334f485dSMiklos Szeredi out: 975334f485dSMiklos Szeredi return err; 976334f485dSMiklos Szeredi } 977334f485dSMiklos Szeredi 978334f485dSMiklos Szeredi void fuse_dev_cleanup(void) 979334f485dSMiklos Szeredi { 980334f485dSMiklos Szeredi misc_deregister(&fuse_miscdevice); 981334f485dSMiklos Szeredi kmem_cache_destroy(fuse_req_cachep); 982334f485dSMiklos Szeredi } 983