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); 37a4d27e75SMiklos Szeredi INIT_LIST_HEAD(&req->intr_entry); 38334f485dSMiklos Szeredi init_waitqueue_head(&req->waitq); 39334f485dSMiklos Szeredi atomic_set(&req->count, 1); 40334f485dSMiklos Szeredi } 41334f485dSMiklos Szeredi 42334f485dSMiklos Szeredi struct fuse_req *fuse_request_alloc(void) 43334f485dSMiklos Szeredi { 44e94b1766SChristoph Lameter struct fuse_req *req = kmem_cache_alloc(fuse_req_cachep, GFP_KERNEL); 45334f485dSMiklos Szeredi if (req) 46334f485dSMiklos Szeredi fuse_request_init(req); 47334f485dSMiklos Szeredi return req; 48334f485dSMiklos Szeredi } 49334f485dSMiklos Szeredi 50334f485dSMiklos Szeredi void fuse_request_free(struct fuse_req *req) 51334f485dSMiklos Szeredi { 52334f485dSMiklos Szeredi kmem_cache_free(fuse_req_cachep, req); 53334f485dSMiklos Szeredi } 54334f485dSMiklos Szeredi 558bfc016dSMiklos Szeredi static void block_sigs(sigset_t *oldset) 56334f485dSMiklos Szeredi { 57334f485dSMiklos Szeredi sigset_t mask; 58334f485dSMiklos Szeredi 59334f485dSMiklos Szeredi siginitsetinv(&mask, sigmask(SIGKILL)); 60334f485dSMiklos Szeredi sigprocmask(SIG_BLOCK, &mask, oldset); 61334f485dSMiklos Szeredi } 62334f485dSMiklos Szeredi 638bfc016dSMiklos Szeredi static void restore_sigs(sigset_t *oldset) 64334f485dSMiklos Szeredi { 65334f485dSMiklos Szeredi sigprocmask(SIG_SETMASK, oldset, NULL); 66334f485dSMiklos Szeredi } 67334f485dSMiklos Szeredi 68334f485dSMiklos Szeredi static void __fuse_get_request(struct fuse_req *req) 69334f485dSMiklos Szeredi { 70334f485dSMiklos Szeredi atomic_inc(&req->count); 71334f485dSMiklos Szeredi } 72334f485dSMiklos Szeredi 73334f485dSMiklos Szeredi /* Must be called with > 1 refcount */ 74334f485dSMiklos Szeredi static void __fuse_put_request(struct fuse_req *req) 75334f485dSMiklos Szeredi { 76334f485dSMiklos Szeredi BUG_ON(atomic_read(&req->count) < 2); 77334f485dSMiklos Szeredi atomic_dec(&req->count); 78334f485dSMiklos Szeredi } 79334f485dSMiklos Szeredi 8033649c91SMiklos Szeredi static void fuse_req_init_context(struct fuse_req *req) 8133649c91SMiklos Szeredi { 8233649c91SMiklos Szeredi req->in.h.uid = current->fsuid; 8333649c91SMiklos Szeredi req->in.h.gid = current->fsgid; 8433649c91SMiklos Szeredi req->in.h.pid = current->pid; 8533649c91SMiklos Szeredi } 8633649c91SMiklos Szeredi 87ce1d5a49SMiklos Szeredi struct fuse_req *fuse_get_req(struct fuse_conn *fc) 88334f485dSMiklos Szeredi { 8908a53cdcSMiklos Szeredi struct fuse_req *req; 9008a53cdcSMiklos Szeredi sigset_t oldset; 919bc5dddaSMiklos Szeredi int intr; 9208a53cdcSMiklos Szeredi int err; 9308a53cdcSMiklos Szeredi 949bc5dddaSMiklos Szeredi atomic_inc(&fc->num_waiting); 9508a53cdcSMiklos Szeredi block_sigs(&oldset); 969bc5dddaSMiklos Szeredi intr = wait_event_interruptible(fc->blocked_waitq, !fc->blocked); 9708a53cdcSMiklos Szeredi restore_sigs(&oldset); 989bc5dddaSMiklos Szeredi err = -EINTR; 999bc5dddaSMiklos Szeredi if (intr) 1009bc5dddaSMiklos Szeredi goto out; 10108a53cdcSMiklos Szeredi 10251eb01e7SMiklos Szeredi err = -ENOTCONN; 10351eb01e7SMiklos Szeredi if (!fc->connected) 10451eb01e7SMiklos Szeredi goto out; 10551eb01e7SMiklos Szeredi 10608a53cdcSMiklos Szeredi req = fuse_request_alloc(); 1079bc5dddaSMiklos Szeredi err = -ENOMEM; 108ce1d5a49SMiklos Szeredi if (!req) 1099bc5dddaSMiklos Szeredi goto out; 110334f485dSMiklos Szeredi 11133649c91SMiklos Szeredi fuse_req_init_context(req); 1129bc5dddaSMiklos Szeredi req->waiting = 1; 113334f485dSMiklos Szeredi return req; 1149bc5dddaSMiklos Szeredi 1159bc5dddaSMiklos Szeredi out: 1169bc5dddaSMiklos Szeredi atomic_dec(&fc->num_waiting); 1179bc5dddaSMiklos Szeredi return ERR_PTR(err); 118334f485dSMiklos Szeredi } 119334f485dSMiklos Szeredi 12033649c91SMiklos Szeredi /* 12133649c91SMiklos Szeredi * Return request in fuse_file->reserved_req. However that may 12233649c91SMiklos Szeredi * currently be in use. If that is the case, wait for it to become 12333649c91SMiklos Szeredi * available. 12433649c91SMiklos Szeredi */ 12533649c91SMiklos Szeredi static struct fuse_req *get_reserved_req(struct fuse_conn *fc, 12633649c91SMiklos Szeredi struct file *file) 12733649c91SMiklos Szeredi { 12833649c91SMiklos Szeredi struct fuse_req *req = NULL; 12933649c91SMiklos Szeredi struct fuse_file *ff = file->private_data; 13033649c91SMiklos Szeredi 13133649c91SMiklos Szeredi do { 13233649c91SMiklos Szeredi wait_event(fc->blocked_waitq, ff->reserved_req); 13333649c91SMiklos Szeredi spin_lock(&fc->lock); 13433649c91SMiklos Szeredi if (ff->reserved_req) { 13533649c91SMiklos Szeredi req = ff->reserved_req; 13633649c91SMiklos Szeredi ff->reserved_req = NULL; 13733649c91SMiklos Szeredi get_file(file); 13833649c91SMiklos Szeredi req->stolen_file = file; 13933649c91SMiklos Szeredi } 14033649c91SMiklos Szeredi spin_unlock(&fc->lock); 14133649c91SMiklos Szeredi } while (!req); 14233649c91SMiklos Szeredi 14333649c91SMiklos Szeredi return req; 14433649c91SMiklos Szeredi } 14533649c91SMiklos Szeredi 14633649c91SMiklos Szeredi /* 14733649c91SMiklos Szeredi * Put stolen request back into fuse_file->reserved_req 14833649c91SMiklos Szeredi */ 14933649c91SMiklos Szeredi static void put_reserved_req(struct fuse_conn *fc, struct fuse_req *req) 15033649c91SMiklos Szeredi { 15133649c91SMiklos Szeredi struct file *file = req->stolen_file; 15233649c91SMiklos Szeredi struct fuse_file *ff = file->private_data; 15333649c91SMiklos Szeredi 15433649c91SMiklos Szeredi spin_lock(&fc->lock); 15533649c91SMiklos Szeredi fuse_request_init(req); 15633649c91SMiklos Szeredi BUG_ON(ff->reserved_req); 15733649c91SMiklos Szeredi ff->reserved_req = req; 15833649c91SMiklos Szeredi wake_up(&fc->blocked_waitq); 15933649c91SMiklos Szeredi spin_unlock(&fc->lock); 16033649c91SMiklos Szeredi fput(file); 16133649c91SMiklos Szeredi } 16233649c91SMiklos Szeredi 16333649c91SMiklos Szeredi /* 16433649c91SMiklos Szeredi * Gets a requests for a file operation, always succeeds 16533649c91SMiklos Szeredi * 16633649c91SMiklos Szeredi * This is used for sending the FLUSH request, which must get to 16733649c91SMiklos Szeredi * userspace, due to POSIX locks which may need to be unlocked. 16833649c91SMiklos Szeredi * 16933649c91SMiklos Szeredi * If allocation fails due to OOM, use the reserved request in 17033649c91SMiklos Szeredi * fuse_file. 17133649c91SMiklos Szeredi * 17233649c91SMiklos Szeredi * This is very unlikely to deadlock accidentally, since the 17333649c91SMiklos Szeredi * filesystem should not have it's own file open. If deadlock is 17433649c91SMiklos Szeredi * intentional, it can still be broken by "aborting" the filesystem. 17533649c91SMiklos Szeredi */ 17633649c91SMiklos Szeredi struct fuse_req *fuse_get_req_nofail(struct fuse_conn *fc, struct file *file) 17733649c91SMiklos Szeredi { 17833649c91SMiklos Szeredi struct fuse_req *req; 17933649c91SMiklos Szeredi 18033649c91SMiklos Szeredi atomic_inc(&fc->num_waiting); 18133649c91SMiklos Szeredi wait_event(fc->blocked_waitq, !fc->blocked); 18233649c91SMiklos Szeredi req = fuse_request_alloc(); 18333649c91SMiklos Szeredi if (!req) 18433649c91SMiklos Szeredi req = get_reserved_req(fc, file); 18533649c91SMiklos Szeredi 18633649c91SMiklos Szeredi fuse_req_init_context(req); 18733649c91SMiklos Szeredi req->waiting = 1; 18833649c91SMiklos Szeredi return req; 18933649c91SMiklos Szeredi } 19033649c91SMiklos Szeredi 191334f485dSMiklos Szeredi void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req) 192334f485dSMiklos Szeredi { 1937128ec2aSMiklos Szeredi if (atomic_dec_and_test(&req->count)) { 1949bc5dddaSMiklos Szeredi if (req->waiting) 195ce1d5a49SMiklos Szeredi atomic_dec(&fc->num_waiting); 19633649c91SMiklos Szeredi 19733649c91SMiklos Szeredi if (req->stolen_file) 19833649c91SMiklos Szeredi put_reserved_req(fc, req); 19933649c91SMiklos Szeredi else 200ce1d5a49SMiklos Szeredi fuse_request_free(req); 2017128ec2aSMiklos Szeredi } 2027128ec2aSMiklos Szeredi } 2037128ec2aSMiklos Szeredi 2046dbbcb12SMiklos Szeredi /* 205334f485dSMiklos Szeredi * This function is called when a request is finished. Either a reply 206f9a2842eSMiklos Szeredi * has arrived or it was aborted (and not yet sent) or some error 207f43b155aSMiklos Szeredi * occurred during communication with userspace, or the device file 20851eb01e7SMiklos Szeredi * was closed. The requester thread is woken up (if still waiting), 20951eb01e7SMiklos Szeredi * the 'end' callback is called if given, else the reference to the 21051eb01e7SMiklos Szeredi * request is released 2117128ec2aSMiklos Szeredi * 212d7133114SMiklos Szeredi * Called with fc->lock, unlocks it 213334f485dSMiklos Szeredi */ 214334f485dSMiklos Szeredi static void request_end(struct fuse_conn *fc, struct fuse_req *req) 215105f4d7aSJosh Triplett __releases(fc->lock) 216334f485dSMiklos Szeredi { 2177128ec2aSMiklos Szeredi void (*end) (struct fuse_conn *, struct fuse_req *) = req->end; 2187128ec2aSMiklos Szeredi req->end = NULL; 21951eb01e7SMiklos Szeredi list_del(&req->list); 220a4d27e75SMiklos Szeredi list_del(&req->intr_entry); 22151eb01e7SMiklos Szeredi req->state = FUSE_REQ_FINISHED; 22251eb01e7SMiklos Szeredi if (req->background) { 22351eb01e7SMiklos Szeredi if (fc->num_background == FUSE_MAX_BACKGROUND) { 22451eb01e7SMiklos Szeredi fc->blocked = 0; 22551eb01e7SMiklos Szeredi wake_up_all(&fc->blocked_waitq); 22651eb01e7SMiklos Szeredi } 22751eb01e7SMiklos Szeredi fc->num_background--; 22851eb01e7SMiklos Szeredi } 229d7133114SMiklos Szeredi spin_unlock(&fc->lock); 23051eb01e7SMiklos Szeredi dput(req->dentry); 23151eb01e7SMiklos Szeredi mntput(req->vfsmount); 2326dbbcb12SMiklos Szeredi if (req->file) 2336dbbcb12SMiklos Szeredi fput(req->file); 23451eb01e7SMiklos Szeredi wake_up(&req->waitq); 23564c6d8edSMiklos Szeredi if (end) 23664c6d8edSMiklos Szeredi end(fc, req); 23764c6d8edSMiklos Szeredi else 238f43b155aSMiklos Szeredi fuse_put_request(fc, req); 239334f485dSMiklos Szeredi } 240334f485dSMiklos Szeredi 241a4d27e75SMiklos Szeredi static void wait_answer_interruptible(struct fuse_conn *fc, 242a4d27e75SMiklos Szeredi struct fuse_req *req) 243a4d27e75SMiklos Szeredi { 244a4d27e75SMiklos Szeredi if (signal_pending(current)) 245a4d27e75SMiklos Szeredi return; 246a4d27e75SMiklos Szeredi 247a4d27e75SMiklos Szeredi spin_unlock(&fc->lock); 248a4d27e75SMiklos Szeredi wait_event_interruptible(req->waitq, req->state == FUSE_REQ_FINISHED); 249a4d27e75SMiklos Szeredi spin_lock(&fc->lock); 250a4d27e75SMiklos Szeredi } 251a4d27e75SMiklos Szeredi 252a4d27e75SMiklos Szeredi static void queue_interrupt(struct fuse_conn *fc, struct fuse_req *req) 253a4d27e75SMiklos Szeredi { 254a4d27e75SMiklos Szeredi list_add_tail(&req->intr_entry, &fc->interrupts); 255a4d27e75SMiklos Szeredi wake_up(&fc->waitq); 256a4d27e75SMiklos Szeredi kill_fasync(&fc->fasync, SIGIO, POLL_IN); 257a4d27e75SMiklos Szeredi } 258a4d27e75SMiklos Szeredi 259d7133114SMiklos Szeredi /* Called with fc->lock held. Releases, and then reacquires it. */ 2607c352bdfSMiklos Szeredi static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req) 261334f485dSMiklos Szeredi { 262a4d27e75SMiklos Szeredi if (!fc->no_interrupt) { 263a4d27e75SMiklos Szeredi /* Any signal may interrupt this */ 264a4d27e75SMiklos Szeredi wait_answer_interruptible(fc, req); 265334f485dSMiklos Szeredi 266a4d27e75SMiklos Szeredi if (req->aborted) 267a4d27e75SMiklos Szeredi goto aborted; 268a4d27e75SMiklos Szeredi if (req->state == FUSE_REQ_FINISHED) 269334f485dSMiklos Szeredi return; 270334f485dSMiklos Szeredi 271a4d27e75SMiklos Szeredi req->interrupted = 1; 272a4d27e75SMiklos Szeredi if (req->state == FUSE_REQ_SENT) 273a4d27e75SMiklos Szeredi queue_interrupt(fc, req); 274a4d27e75SMiklos Szeredi } 275a4d27e75SMiklos Szeredi 276a4d27e75SMiklos Szeredi if (req->force) { 277a4d27e75SMiklos Szeredi spin_unlock(&fc->lock); 278a4d27e75SMiklos Szeredi wait_event(req->waitq, req->state == FUSE_REQ_FINISHED); 279a4d27e75SMiklos Szeredi spin_lock(&fc->lock); 280a4d27e75SMiklos Szeredi } else { 281a4d27e75SMiklos Szeredi sigset_t oldset; 282a4d27e75SMiklos Szeredi 283a4d27e75SMiklos Szeredi /* Only fatal signals may interrupt this */ 284a4d27e75SMiklos Szeredi block_sigs(&oldset); 285a4d27e75SMiklos Szeredi wait_answer_interruptible(fc, req); 286a4d27e75SMiklos Szeredi restore_sigs(&oldset); 287a4d27e75SMiklos Szeredi } 288a4d27e75SMiklos Szeredi 289a4d27e75SMiklos Szeredi if (req->aborted) 290a4d27e75SMiklos Szeredi goto aborted; 291a4d27e75SMiklos Szeredi if (req->state == FUSE_REQ_FINISHED) 292a4d27e75SMiklos Szeredi return; 293a4d27e75SMiklos Szeredi 294334f485dSMiklos Szeredi req->out.h.error = -EINTR; 295f9a2842eSMiklos Szeredi req->aborted = 1; 296a4d27e75SMiklos Szeredi 297a4d27e75SMiklos Szeredi aborted: 298334f485dSMiklos Szeredi if (req->locked) { 299334f485dSMiklos Szeredi /* This is uninterruptible sleep, because data is 300334f485dSMiklos Szeredi being copied to/from the buffers of req. During 301334f485dSMiklos Szeredi locked state, there mustn't be any filesystem 302334f485dSMiklos Szeredi operation (e.g. page fault), since that could lead 303334f485dSMiklos Szeredi to deadlock */ 304d7133114SMiklos Szeredi spin_unlock(&fc->lock); 305334f485dSMiklos Szeredi wait_event(req->waitq, !req->locked); 306d7133114SMiklos Szeredi spin_lock(&fc->lock); 307334f485dSMiklos Szeredi } 30883cfd493SMiklos Szeredi if (req->state == FUSE_REQ_PENDING) { 309334f485dSMiklos Szeredi list_del(&req->list); 310334f485dSMiklos Szeredi __fuse_put_request(req); 31151eb01e7SMiklos Szeredi } else if (req->state == FUSE_REQ_SENT) { 31251eb01e7SMiklos Szeredi spin_unlock(&fc->lock); 31351eb01e7SMiklos Szeredi wait_event(req->waitq, req->state == FUSE_REQ_FINISHED); 31451eb01e7SMiklos Szeredi spin_lock(&fc->lock); 31551eb01e7SMiklos Szeredi } 316334f485dSMiklos Szeredi } 317334f485dSMiklos Szeredi 318334f485dSMiklos Szeredi static unsigned len_args(unsigned numargs, struct fuse_arg *args) 319334f485dSMiklos Szeredi { 320334f485dSMiklos Szeredi unsigned nbytes = 0; 321334f485dSMiklos Szeredi unsigned i; 322334f485dSMiklos Szeredi 323334f485dSMiklos Szeredi for (i = 0; i < numargs; i++) 324334f485dSMiklos Szeredi nbytes += args[i].size; 325334f485dSMiklos Szeredi 326334f485dSMiklos Szeredi return nbytes; 327334f485dSMiklos Szeredi } 328334f485dSMiklos Szeredi 329a4d27e75SMiklos Szeredi static u64 fuse_get_unique(struct fuse_conn *fc) 330334f485dSMiklos Szeredi { 331334f485dSMiklos Szeredi fc->reqctr++; 332334f485dSMiklos Szeredi /* zero is special */ 333334f485dSMiklos Szeredi if (fc->reqctr == 0) 334334f485dSMiklos Szeredi fc->reqctr = 1; 335a4d27e75SMiklos Szeredi 336a4d27e75SMiklos Szeredi return fc->reqctr; 337a4d27e75SMiklos Szeredi } 338a4d27e75SMiklos Szeredi 339a4d27e75SMiklos Szeredi static void queue_request(struct fuse_conn *fc, struct fuse_req *req) 340a4d27e75SMiklos Szeredi { 341a4d27e75SMiklos Szeredi req->in.h.unique = fuse_get_unique(fc); 342334f485dSMiklos Szeredi req->in.h.len = sizeof(struct fuse_in_header) + 343334f485dSMiklos Szeredi len_args(req->in.numargs, (struct fuse_arg *) req->in.args); 344334f485dSMiklos Szeredi list_add_tail(&req->list, &fc->pending); 34583cfd493SMiklos Szeredi req->state = FUSE_REQ_PENDING; 3469bc5dddaSMiklos Szeredi if (!req->waiting) { 3479bc5dddaSMiklos Szeredi req->waiting = 1; 3489bc5dddaSMiklos Szeredi atomic_inc(&fc->num_waiting); 3499bc5dddaSMiklos Szeredi } 350334f485dSMiklos Szeredi wake_up(&fc->waitq); 351385a17bfSJeff Dike kill_fasync(&fc->fasync, SIGIO, POLL_IN); 352334f485dSMiklos Szeredi } 353334f485dSMiklos Szeredi 3547c352bdfSMiklos Szeredi void request_send(struct fuse_conn *fc, struct fuse_req *req) 355334f485dSMiklos Szeredi { 356334f485dSMiklos Szeredi req->isreply = 1; 357d7133114SMiklos Szeredi spin_lock(&fc->lock); 3581e9a4ed9SMiklos Szeredi if (!fc->connected) 359334f485dSMiklos Szeredi req->out.h.error = -ENOTCONN; 360334f485dSMiklos Szeredi else if (fc->conn_error) 361334f485dSMiklos Szeredi req->out.h.error = -ECONNREFUSED; 362334f485dSMiklos Szeredi else { 363334f485dSMiklos Szeredi queue_request(fc, req); 364334f485dSMiklos Szeredi /* acquire extra reference, since request is still needed 365334f485dSMiklos Szeredi after request_end() */ 366334f485dSMiklos Szeredi __fuse_get_request(req); 367334f485dSMiklos Szeredi 3687c352bdfSMiklos Szeredi request_wait_answer(fc, req); 369334f485dSMiklos Szeredi } 370d7133114SMiklos Szeredi spin_unlock(&fc->lock); 371334f485dSMiklos Szeredi } 372334f485dSMiklos Szeredi 373334f485dSMiklos Szeredi static void request_send_nowait(struct fuse_conn *fc, struct fuse_req *req) 374334f485dSMiklos Szeredi { 375d7133114SMiklos Szeredi spin_lock(&fc->lock); 3761e9a4ed9SMiklos Szeredi if (fc->connected) { 37751eb01e7SMiklos Szeredi req->background = 1; 37851eb01e7SMiklos Szeredi fc->num_background++; 37951eb01e7SMiklos Szeredi if (fc->num_background == FUSE_MAX_BACKGROUND) 38051eb01e7SMiklos Szeredi fc->blocked = 1; 38151eb01e7SMiklos Szeredi 382334f485dSMiklos Szeredi queue_request(fc, req); 383d7133114SMiklos Szeredi spin_unlock(&fc->lock); 384334f485dSMiklos Szeredi } else { 385334f485dSMiklos Szeredi req->out.h.error = -ENOTCONN; 386334f485dSMiklos Szeredi request_end(fc, req); 387334f485dSMiklos Szeredi } 388334f485dSMiklos Szeredi } 389334f485dSMiklos Szeredi 390334f485dSMiklos Szeredi void request_send_noreply(struct fuse_conn *fc, struct fuse_req *req) 391334f485dSMiklos Szeredi { 392334f485dSMiklos Szeredi req->isreply = 0; 393334f485dSMiklos Szeredi request_send_nowait(fc, req); 394334f485dSMiklos Szeredi } 395334f485dSMiklos Szeredi 396334f485dSMiklos Szeredi void request_send_background(struct fuse_conn *fc, struct fuse_req *req) 397334f485dSMiklos Szeredi { 398334f485dSMiklos Szeredi req->isreply = 1; 399334f485dSMiklos Szeredi request_send_nowait(fc, req); 400334f485dSMiklos Szeredi } 401334f485dSMiklos Szeredi 402334f485dSMiklos Szeredi /* 403334f485dSMiklos Szeredi * Lock the request. Up to the next unlock_request() there mustn't be 404334f485dSMiklos Szeredi * anything that could cause a page-fault. If the request was already 405f9a2842eSMiklos Szeredi * aborted bail out. 406334f485dSMiklos Szeredi */ 407d7133114SMiklos Szeredi static int lock_request(struct fuse_conn *fc, struct fuse_req *req) 408334f485dSMiklos Szeredi { 409334f485dSMiklos Szeredi int err = 0; 410334f485dSMiklos Szeredi if (req) { 411d7133114SMiklos Szeredi spin_lock(&fc->lock); 412f9a2842eSMiklos Szeredi if (req->aborted) 413334f485dSMiklos Szeredi err = -ENOENT; 414334f485dSMiklos Szeredi else 415334f485dSMiklos Szeredi req->locked = 1; 416d7133114SMiklos Szeredi spin_unlock(&fc->lock); 417334f485dSMiklos Szeredi } 418334f485dSMiklos Szeredi return err; 419334f485dSMiklos Szeredi } 420334f485dSMiklos Szeredi 421334f485dSMiklos Szeredi /* 422f9a2842eSMiklos Szeredi * Unlock request. If it was aborted during being locked, the 423334f485dSMiklos Szeredi * requester thread is currently waiting for it to be unlocked, so 424334f485dSMiklos Szeredi * wake it up. 425334f485dSMiklos Szeredi */ 426d7133114SMiklos Szeredi static void unlock_request(struct fuse_conn *fc, struct fuse_req *req) 427334f485dSMiklos Szeredi { 428334f485dSMiklos Szeredi if (req) { 429d7133114SMiklos Szeredi spin_lock(&fc->lock); 430334f485dSMiklos Szeredi req->locked = 0; 431f9a2842eSMiklos Szeredi if (req->aborted) 432334f485dSMiklos Szeredi wake_up(&req->waitq); 433d7133114SMiklos Szeredi spin_unlock(&fc->lock); 434334f485dSMiklos Szeredi } 435334f485dSMiklos Szeredi } 436334f485dSMiklos Szeredi 437334f485dSMiklos Szeredi struct fuse_copy_state { 438d7133114SMiklos Szeredi struct fuse_conn *fc; 439334f485dSMiklos Szeredi int write; 440334f485dSMiklos Szeredi struct fuse_req *req; 441334f485dSMiklos Szeredi const struct iovec *iov; 442334f485dSMiklos Szeredi unsigned long nr_segs; 443334f485dSMiklos Szeredi unsigned long seglen; 444334f485dSMiklos Szeredi unsigned long addr; 445334f485dSMiklos Szeredi struct page *pg; 446334f485dSMiklos Szeredi void *mapaddr; 447334f485dSMiklos Szeredi void *buf; 448334f485dSMiklos Szeredi unsigned len; 449334f485dSMiklos Szeredi }; 450334f485dSMiklos Szeredi 451d7133114SMiklos Szeredi static void fuse_copy_init(struct fuse_copy_state *cs, struct fuse_conn *fc, 452d7133114SMiklos Szeredi int write, struct fuse_req *req, 453d7133114SMiklos Szeredi const struct iovec *iov, unsigned long nr_segs) 454334f485dSMiklos Szeredi { 455334f485dSMiklos Szeredi memset(cs, 0, sizeof(*cs)); 456d7133114SMiklos Szeredi cs->fc = fc; 457334f485dSMiklos Szeredi cs->write = write; 458334f485dSMiklos Szeredi cs->req = req; 459334f485dSMiklos Szeredi cs->iov = iov; 460334f485dSMiklos Szeredi cs->nr_segs = nr_segs; 461334f485dSMiklos Szeredi } 462334f485dSMiklos Szeredi 463334f485dSMiklos Szeredi /* Unmap and put previous page of userspace buffer */ 4648bfc016dSMiklos Szeredi static void fuse_copy_finish(struct fuse_copy_state *cs) 465334f485dSMiklos Szeredi { 466334f485dSMiklos Szeredi if (cs->mapaddr) { 467334f485dSMiklos Szeredi kunmap_atomic(cs->mapaddr, KM_USER0); 468334f485dSMiklos Szeredi if (cs->write) { 469334f485dSMiklos Szeredi flush_dcache_page(cs->pg); 470334f485dSMiklos Szeredi set_page_dirty_lock(cs->pg); 471334f485dSMiklos Szeredi } 472334f485dSMiklos Szeredi put_page(cs->pg); 473334f485dSMiklos Szeredi cs->mapaddr = NULL; 474334f485dSMiklos Szeredi } 475334f485dSMiklos Szeredi } 476334f485dSMiklos Szeredi 477334f485dSMiklos Szeredi /* 478334f485dSMiklos Szeredi * Get another pagefull of userspace buffer, and map it to kernel 479334f485dSMiklos Szeredi * address space, and lock request 480334f485dSMiklos Szeredi */ 481334f485dSMiklos Szeredi static int fuse_copy_fill(struct fuse_copy_state *cs) 482334f485dSMiklos Szeredi { 483334f485dSMiklos Szeredi unsigned long offset; 484334f485dSMiklos Szeredi int err; 485334f485dSMiklos Szeredi 486d7133114SMiklos Szeredi unlock_request(cs->fc, cs->req); 487334f485dSMiklos Szeredi fuse_copy_finish(cs); 488334f485dSMiklos Szeredi if (!cs->seglen) { 489334f485dSMiklos Szeredi BUG_ON(!cs->nr_segs); 490334f485dSMiklos Szeredi cs->seglen = cs->iov[0].iov_len; 491334f485dSMiklos Szeredi cs->addr = (unsigned long) cs->iov[0].iov_base; 492334f485dSMiklos Szeredi cs->iov ++; 493334f485dSMiklos Szeredi cs->nr_segs --; 494334f485dSMiklos Szeredi } 495334f485dSMiklos Szeredi down_read(¤t->mm->mmap_sem); 496334f485dSMiklos Szeredi err = get_user_pages(current, current->mm, cs->addr, 1, cs->write, 0, 497334f485dSMiklos Szeredi &cs->pg, NULL); 498334f485dSMiklos Szeredi up_read(¤t->mm->mmap_sem); 499334f485dSMiklos Szeredi if (err < 0) 500334f485dSMiklos Szeredi return err; 501334f485dSMiklos Szeredi BUG_ON(err != 1); 502334f485dSMiklos Szeredi offset = cs->addr % PAGE_SIZE; 503334f485dSMiklos Szeredi cs->mapaddr = kmap_atomic(cs->pg, KM_USER0); 504334f485dSMiklos Szeredi cs->buf = cs->mapaddr + offset; 505334f485dSMiklos Szeredi cs->len = min(PAGE_SIZE - offset, cs->seglen); 506334f485dSMiklos Szeredi cs->seglen -= cs->len; 507334f485dSMiklos Szeredi cs->addr += cs->len; 508334f485dSMiklos Szeredi 509d7133114SMiklos Szeredi return lock_request(cs->fc, cs->req); 510334f485dSMiklos Szeredi } 511334f485dSMiklos Szeredi 512334f485dSMiklos Szeredi /* Do as much copy to/from userspace buffer as we can */ 5138bfc016dSMiklos Szeredi static int fuse_copy_do(struct fuse_copy_state *cs, void **val, unsigned *size) 514334f485dSMiklos Szeredi { 515334f485dSMiklos Szeredi unsigned ncpy = min(*size, cs->len); 516334f485dSMiklos Szeredi if (val) { 517334f485dSMiklos Szeredi if (cs->write) 518334f485dSMiklos Szeredi memcpy(cs->buf, *val, ncpy); 519334f485dSMiklos Szeredi else 520334f485dSMiklos Szeredi memcpy(*val, cs->buf, ncpy); 521334f485dSMiklos Szeredi *val += ncpy; 522334f485dSMiklos Szeredi } 523334f485dSMiklos Szeredi *size -= ncpy; 524334f485dSMiklos Szeredi cs->len -= ncpy; 525334f485dSMiklos Szeredi cs->buf += ncpy; 526334f485dSMiklos Szeredi return ncpy; 527334f485dSMiklos Szeredi } 528334f485dSMiklos Szeredi 529334f485dSMiklos Szeredi /* 530334f485dSMiklos Szeredi * Copy a page in the request to/from the userspace buffer. Must be 531334f485dSMiklos Szeredi * done atomically 532334f485dSMiklos Szeredi */ 5338bfc016dSMiklos Szeredi static int fuse_copy_page(struct fuse_copy_state *cs, struct page *page, 534334f485dSMiklos Szeredi unsigned offset, unsigned count, int zeroing) 535334f485dSMiklos Szeredi { 536334f485dSMiklos Szeredi if (page && zeroing && count < PAGE_SIZE) { 537334f485dSMiklos Szeredi void *mapaddr = kmap_atomic(page, KM_USER1); 538334f485dSMiklos Szeredi memset(mapaddr, 0, PAGE_SIZE); 539334f485dSMiklos Szeredi kunmap_atomic(mapaddr, KM_USER1); 540334f485dSMiklos Szeredi } 541334f485dSMiklos Szeredi while (count) { 542334f485dSMiklos Szeredi int err; 543334f485dSMiklos Szeredi if (!cs->len && (err = fuse_copy_fill(cs))) 544334f485dSMiklos Szeredi return err; 545334f485dSMiklos Szeredi if (page) { 546334f485dSMiklos Szeredi void *mapaddr = kmap_atomic(page, KM_USER1); 547334f485dSMiklos Szeredi void *buf = mapaddr + offset; 548334f485dSMiklos Szeredi offset += fuse_copy_do(cs, &buf, &count); 549334f485dSMiklos Szeredi kunmap_atomic(mapaddr, KM_USER1); 550334f485dSMiklos Szeredi } else 551334f485dSMiklos Szeredi offset += fuse_copy_do(cs, NULL, &count); 552334f485dSMiklos Szeredi } 553334f485dSMiklos Szeredi if (page && !cs->write) 554334f485dSMiklos Szeredi flush_dcache_page(page); 555334f485dSMiklos Szeredi return 0; 556334f485dSMiklos Szeredi } 557334f485dSMiklos Szeredi 558334f485dSMiklos Szeredi /* Copy pages in the request to/from userspace buffer */ 559334f485dSMiklos Szeredi static int fuse_copy_pages(struct fuse_copy_state *cs, unsigned nbytes, 560334f485dSMiklos Szeredi int zeroing) 561334f485dSMiklos Szeredi { 562334f485dSMiklos Szeredi unsigned i; 563334f485dSMiklos Szeredi struct fuse_req *req = cs->req; 564334f485dSMiklos Szeredi unsigned offset = req->page_offset; 565334f485dSMiklos Szeredi unsigned count = min(nbytes, (unsigned) PAGE_SIZE - offset); 566334f485dSMiklos Szeredi 567334f485dSMiklos Szeredi for (i = 0; i < req->num_pages && (nbytes || zeroing); i++) { 568334f485dSMiklos Szeredi struct page *page = req->pages[i]; 569334f485dSMiklos Szeredi int err = fuse_copy_page(cs, page, offset, count, zeroing); 570334f485dSMiklos Szeredi if (err) 571334f485dSMiklos Szeredi return err; 572334f485dSMiklos Szeredi 573334f485dSMiklos Szeredi nbytes -= count; 574334f485dSMiklos Szeredi count = min(nbytes, (unsigned) PAGE_SIZE); 575334f485dSMiklos Szeredi offset = 0; 576334f485dSMiklos Szeredi } 577334f485dSMiklos Szeredi return 0; 578334f485dSMiklos Szeredi } 579334f485dSMiklos Szeredi 580334f485dSMiklos Szeredi /* Copy a single argument in the request to/from userspace buffer */ 581334f485dSMiklos Szeredi static int fuse_copy_one(struct fuse_copy_state *cs, void *val, unsigned size) 582334f485dSMiklos Szeredi { 583334f485dSMiklos Szeredi while (size) { 584334f485dSMiklos Szeredi int err; 585334f485dSMiklos Szeredi if (!cs->len && (err = fuse_copy_fill(cs))) 586334f485dSMiklos Szeredi return err; 587334f485dSMiklos Szeredi fuse_copy_do(cs, &val, &size); 588334f485dSMiklos Szeredi } 589334f485dSMiklos Szeredi return 0; 590334f485dSMiklos Szeredi } 591334f485dSMiklos Szeredi 592334f485dSMiklos Szeredi /* Copy request arguments to/from userspace buffer */ 593334f485dSMiklos Szeredi static int fuse_copy_args(struct fuse_copy_state *cs, unsigned numargs, 594334f485dSMiklos Szeredi unsigned argpages, struct fuse_arg *args, 595334f485dSMiklos Szeredi int zeroing) 596334f485dSMiklos Szeredi { 597334f485dSMiklos Szeredi int err = 0; 598334f485dSMiklos Szeredi unsigned i; 599334f485dSMiklos Szeredi 600334f485dSMiklos Szeredi for (i = 0; !err && i < numargs; i++) { 601334f485dSMiklos Szeredi struct fuse_arg *arg = &args[i]; 602334f485dSMiklos Szeredi if (i == numargs - 1 && argpages) 603334f485dSMiklos Szeredi err = fuse_copy_pages(cs, arg->size, zeroing); 604334f485dSMiklos Szeredi else 605334f485dSMiklos Szeredi err = fuse_copy_one(cs, arg->value, arg->size); 606334f485dSMiklos Szeredi } 607334f485dSMiklos Szeredi return err; 608334f485dSMiklos Szeredi } 609334f485dSMiklos Szeredi 610a4d27e75SMiklos Szeredi static int request_pending(struct fuse_conn *fc) 611a4d27e75SMiklos Szeredi { 612a4d27e75SMiklos Szeredi return !list_empty(&fc->pending) || !list_empty(&fc->interrupts); 613a4d27e75SMiklos Szeredi } 614a4d27e75SMiklos Szeredi 615334f485dSMiklos Szeredi /* Wait until a request is available on the pending list */ 616334f485dSMiklos Szeredi static void request_wait(struct fuse_conn *fc) 617334f485dSMiklos Szeredi { 618334f485dSMiklos Szeredi DECLARE_WAITQUEUE(wait, current); 619334f485dSMiklos Szeredi 620334f485dSMiklos Szeredi add_wait_queue_exclusive(&fc->waitq, &wait); 621a4d27e75SMiklos Szeredi while (fc->connected && !request_pending(fc)) { 622334f485dSMiklos Szeredi set_current_state(TASK_INTERRUPTIBLE); 623334f485dSMiklos Szeredi if (signal_pending(current)) 624334f485dSMiklos Szeredi break; 625334f485dSMiklos Szeredi 626d7133114SMiklos Szeredi spin_unlock(&fc->lock); 627334f485dSMiklos Szeredi schedule(); 628d7133114SMiklos Szeredi spin_lock(&fc->lock); 629334f485dSMiklos Szeredi } 630334f485dSMiklos Szeredi set_current_state(TASK_RUNNING); 631334f485dSMiklos Szeredi remove_wait_queue(&fc->waitq, &wait); 632334f485dSMiklos Szeredi } 633334f485dSMiklos Szeredi 634334f485dSMiklos Szeredi /* 635a4d27e75SMiklos Szeredi * Transfer an interrupt request to userspace 636a4d27e75SMiklos Szeredi * 637a4d27e75SMiklos Szeredi * Unlike other requests this is assembled on demand, without a need 638a4d27e75SMiklos Szeredi * to allocate a separate fuse_req structure. 639a4d27e75SMiklos Szeredi * 640a4d27e75SMiklos Szeredi * Called with fc->lock held, releases it 641a4d27e75SMiklos Szeredi */ 642a4d27e75SMiklos Szeredi static int fuse_read_interrupt(struct fuse_conn *fc, struct fuse_req *req, 643a4d27e75SMiklos Szeredi const struct iovec *iov, unsigned long nr_segs) 644105f4d7aSJosh Triplett __releases(fc->lock) 645a4d27e75SMiklos Szeredi { 646a4d27e75SMiklos Szeredi struct fuse_copy_state cs; 647a4d27e75SMiklos Szeredi struct fuse_in_header ih; 648a4d27e75SMiklos Szeredi struct fuse_interrupt_in arg; 649a4d27e75SMiklos Szeredi unsigned reqsize = sizeof(ih) + sizeof(arg); 650a4d27e75SMiklos Szeredi int err; 651a4d27e75SMiklos Szeredi 652a4d27e75SMiklos Szeredi list_del_init(&req->intr_entry); 653a4d27e75SMiklos Szeredi req->intr_unique = fuse_get_unique(fc); 654a4d27e75SMiklos Szeredi memset(&ih, 0, sizeof(ih)); 655a4d27e75SMiklos Szeredi memset(&arg, 0, sizeof(arg)); 656a4d27e75SMiklos Szeredi ih.len = reqsize; 657a4d27e75SMiklos Szeredi ih.opcode = FUSE_INTERRUPT; 658a4d27e75SMiklos Szeredi ih.unique = req->intr_unique; 659a4d27e75SMiklos Szeredi arg.unique = req->in.h.unique; 660a4d27e75SMiklos Szeredi 661a4d27e75SMiklos Szeredi spin_unlock(&fc->lock); 662a4d27e75SMiklos Szeredi if (iov_length(iov, nr_segs) < reqsize) 663a4d27e75SMiklos Szeredi return -EINVAL; 664a4d27e75SMiklos Szeredi 665a4d27e75SMiklos Szeredi fuse_copy_init(&cs, fc, 1, NULL, iov, nr_segs); 666a4d27e75SMiklos Szeredi err = fuse_copy_one(&cs, &ih, sizeof(ih)); 667a4d27e75SMiklos Szeredi if (!err) 668a4d27e75SMiklos Szeredi err = fuse_copy_one(&cs, &arg, sizeof(arg)); 669a4d27e75SMiklos Szeredi fuse_copy_finish(&cs); 670a4d27e75SMiklos Szeredi 671a4d27e75SMiklos Szeredi return err ? err : reqsize; 672a4d27e75SMiklos Szeredi } 673a4d27e75SMiklos Szeredi 674a4d27e75SMiklos Szeredi /* 675334f485dSMiklos Szeredi * Read a single request into the userspace filesystem's buffer. This 676334f485dSMiklos Szeredi * function waits until a request is available, then removes it from 677334f485dSMiklos Szeredi * the pending list and copies request data to userspace buffer. If 678f9a2842eSMiklos Szeredi * no reply is needed (FORGET) or request has been aborted or there 679f9a2842eSMiklos Szeredi * was an error during the copying then it's finished by calling 680334f485dSMiklos Szeredi * request_end(). Otherwise add it to the processing list, and set 681334f485dSMiklos Szeredi * the 'sent' flag. 682334f485dSMiklos Szeredi */ 683ee0b3e67SBadari Pulavarty static ssize_t fuse_dev_read(struct kiocb *iocb, const struct iovec *iov, 684ee0b3e67SBadari Pulavarty unsigned long nr_segs, loff_t pos) 685334f485dSMiklos Szeredi { 686334f485dSMiklos Szeredi int err; 687334f485dSMiklos Szeredi struct fuse_req *req; 688334f485dSMiklos Szeredi struct fuse_in *in; 689334f485dSMiklos Szeredi struct fuse_copy_state cs; 690334f485dSMiklos Szeredi unsigned reqsize; 691ee0b3e67SBadari Pulavarty struct file *file = iocb->ki_filp; 6920720b315SMiklos Szeredi struct fuse_conn *fc = fuse_get_conn(file); 6930720b315SMiklos Szeredi if (!fc) 6940720b315SMiklos Szeredi return -EPERM; 695334f485dSMiklos Szeredi 6961d3d752bSMiklos Szeredi restart: 697d7133114SMiklos Szeredi spin_lock(&fc->lock); 698e5ac1d1eSJeff Dike err = -EAGAIN; 699e5ac1d1eSJeff Dike if ((file->f_flags & O_NONBLOCK) && fc->connected && 700a4d27e75SMiklos Szeredi !request_pending(fc)) 701e5ac1d1eSJeff Dike goto err_unlock; 702e5ac1d1eSJeff Dike 703334f485dSMiklos Szeredi request_wait(fc); 704334f485dSMiklos Szeredi err = -ENODEV; 7059ba7cbbaSMiklos Szeredi if (!fc->connected) 706334f485dSMiklos Szeredi goto err_unlock; 707334f485dSMiklos Szeredi err = -ERESTARTSYS; 708a4d27e75SMiklos Szeredi if (!request_pending(fc)) 709334f485dSMiklos Szeredi goto err_unlock; 710334f485dSMiklos Szeredi 711a4d27e75SMiklos Szeredi if (!list_empty(&fc->interrupts)) { 712a4d27e75SMiklos Szeredi req = list_entry(fc->interrupts.next, struct fuse_req, 713a4d27e75SMiklos Szeredi intr_entry); 714a4d27e75SMiklos Szeredi return fuse_read_interrupt(fc, req, iov, nr_segs); 715a4d27e75SMiklos Szeredi } 716a4d27e75SMiklos Szeredi 717334f485dSMiklos Szeredi req = list_entry(fc->pending.next, struct fuse_req, list); 71883cfd493SMiklos Szeredi req->state = FUSE_REQ_READING; 719d77a1d5bSMiklos Szeredi list_move(&req->list, &fc->io); 720334f485dSMiklos Szeredi 721334f485dSMiklos Szeredi in = &req->in; 7221d3d752bSMiklos Szeredi reqsize = in->h.len; 7231d3d752bSMiklos Szeredi /* If request is too large, reply with an error and restart the read */ 7241d3d752bSMiklos Szeredi if (iov_length(iov, nr_segs) < reqsize) { 7251d3d752bSMiklos Szeredi req->out.h.error = -EIO; 7261d3d752bSMiklos Szeredi /* SETXATTR is special, since it may contain too large data */ 7271d3d752bSMiklos Szeredi if (in->h.opcode == FUSE_SETXATTR) 7281d3d752bSMiklos Szeredi req->out.h.error = -E2BIG; 7291d3d752bSMiklos Szeredi request_end(fc, req); 7301d3d752bSMiklos Szeredi goto restart; 7311d3d752bSMiklos Szeredi } 732d7133114SMiklos Szeredi spin_unlock(&fc->lock); 733d7133114SMiklos Szeredi fuse_copy_init(&cs, fc, 1, req, iov, nr_segs); 734334f485dSMiklos Szeredi err = fuse_copy_one(&cs, &in->h, sizeof(in->h)); 735334f485dSMiklos Szeredi if (!err) 736334f485dSMiklos Szeredi err = fuse_copy_args(&cs, in->numargs, in->argpages, 737334f485dSMiklos Szeredi (struct fuse_arg *) in->args, 0); 738334f485dSMiklos Szeredi fuse_copy_finish(&cs); 739d7133114SMiklos Szeredi spin_lock(&fc->lock); 740334f485dSMiklos Szeredi req->locked = 0; 741f9a2842eSMiklos Szeredi if (!err && req->aborted) 742334f485dSMiklos Szeredi err = -ENOENT; 743334f485dSMiklos Szeredi if (err) { 744f9a2842eSMiklos Szeredi if (!req->aborted) 745334f485dSMiklos Szeredi req->out.h.error = -EIO; 746334f485dSMiklos Szeredi request_end(fc, req); 747334f485dSMiklos Szeredi return err; 748334f485dSMiklos Szeredi } 749334f485dSMiklos Szeredi if (!req->isreply) 750334f485dSMiklos Szeredi request_end(fc, req); 751334f485dSMiklos Szeredi else { 75283cfd493SMiklos Szeredi req->state = FUSE_REQ_SENT; 753d77a1d5bSMiklos Szeredi list_move_tail(&req->list, &fc->processing); 754a4d27e75SMiklos Szeredi if (req->interrupted) 755a4d27e75SMiklos Szeredi queue_interrupt(fc, req); 756d7133114SMiklos Szeredi spin_unlock(&fc->lock); 757334f485dSMiklos Szeredi } 758334f485dSMiklos Szeredi return reqsize; 759334f485dSMiklos Szeredi 760334f485dSMiklos Szeredi err_unlock: 761d7133114SMiklos Szeredi spin_unlock(&fc->lock); 762334f485dSMiklos Szeredi return err; 763334f485dSMiklos Szeredi } 764334f485dSMiklos Szeredi 765334f485dSMiklos Szeredi /* Look up request on processing list by unique ID */ 766334f485dSMiklos Szeredi static struct fuse_req *request_find(struct fuse_conn *fc, u64 unique) 767334f485dSMiklos Szeredi { 768334f485dSMiklos Szeredi struct list_head *entry; 769334f485dSMiklos Szeredi 770334f485dSMiklos Szeredi list_for_each(entry, &fc->processing) { 771334f485dSMiklos Szeredi struct fuse_req *req; 772334f485dSMiklos Szeredi req = list_entry(entry, struct fuse_req, list); 773a4d27e75SMiklos Szeredi if (req->in.h.unique == unique || req->intr_unique == unique) 774334f485dSMiklos Szeredi return req; 775334f485dSMiklos Szeredi } 776334f485dSMiklos Szeredi return NULL; 777334f485dSMiklos Szeredi } 778334f485dSMiklos Szeredi 779334f485dSMiklos Szeredi static int copy_out_args(struct fuse_copy_state *cs, struct fuse_out *out, 780334f485dSMiklos Szeredi unsigned nbytes) 781334f485dSMiklos Szeredi { 782334f485dSMiklos Szeredi unsigned reqsize = sizeof(struct fuse_out_header); 783334f485dSMiklos Szeredi 784334f485dSMiklos Szeredi if (out->h.error) 785334f485dSMiklos Szeredi return nbytes != reqsize ? -EINVAL : 0; 786334f485dSMiklos Szeredi 787334f485dSMiklos Szeredi reqsize += len_args(out->numargs, out->args); 788334f485dSMiklos Szeredi 789334f485dSMiklos Szeredi if (reqsize < nbytes || (reqsize > nbytes && !out->argvar)) 790334f485dSMiklos Szeredi return -EINVAL; 791334f485dSMiklos Szeredi else if (reqsize > nbytes) { 792334f485dSMiklos Szeredi struct fuse_arg *lastarg = &out->args[out->numargs-1]; 793334f485dSMiklos Szeredi unsigned diffsize = reqsize - nbytes; 794334f485dSMiklos Szeredi if (diffsize > lastarg->size) 795334f485dSMiklos Szeredi return -EINVAL; 796334f485dSMiklos Szeredi lastarg->size -= diffsize; 797334f485dSMiklos Szeredi } 798334f485dSMiklos Szeredi return fuse_copy_args(cs, out->numargs, out->argpages, out->args, 799334f485dSMiklos Szeredi out->page_zeroing); 800334f485dSMiklos Szeredi } 801334f485dSMiklos Szeredi 802334f485dSMiklos Szeredi /* 803334f485dSMiklos Szeredi * Write a single reply to a request. First the header is copied from 804334f485dSMiklos Szeredi * the write buffer. The request is then searched on the processing 805334f485dSMiklos Szeredi * list by the unique ID found in the header. If found, then remove 806334f485dSMiklos Szeredi * it from the list and copy the rest of the buffer to the request. 807334f485dSMiklos Szeredi * The request is finished by calling request_end() 808334f485dSMiklos Szeredi */ 809ee0b3e67SBadari Pulavarty static ssize_t fuse_dev_write(struct kiocb *iocb, const struct iovec *iov, 810ee0b3e67SBadari Pulavarty unsigned long nr_segs, loff_t pos) 811334f485dSMiklos Szeredi { 812334f485dSMiklos Szeredi int err; 813334f485dSMiklos Szeredi unsigned nbytes = iov_length(iov, nr_segs); 814334f485dSMiklos Szeredi struct fuse_req *req; 815334f485dSMiklos Szeredi struct fuse_out_header oh; 816334f485dSMiklos Szeredi struct fuse_copy_state cs; 817ee0b3e67SBadari Pulavarty struct fuse_conn *fc = fuse_get_conn(iocb->ki_filp); 818334f485dSMiklos Szeredi if (!fc) 819a87046d8SMiklos Szeredi return -EPERM; 820334f485dSMiklos Szeredi 821d7133114SMiklos Szeredi fuse_copy_init(&cs, fc, 0, NULL, iov, nr_segs); 822334f485dSMiklos Szeredi if (nbytes < sizeof(struct fuse_out_header)) 823334f485dSMiklos Szeredi return -EINVAL; 824334f485dSMiklos Szeredi 825334f485dSMiklos Szeredi err = fuse_copy_one(&cs, &oh, sizeof(oh)); 826334f485dSMiklos Szeredi if (err) 827334f485dSMiklos Szeredi goto err_finish; 828334f485dSMiklos Szeredi err = -EINVAL; 829334f485dSMiklos Szeredi if (!oh.unique || oh.error <= -1000 || oh.error > 0 || 830334f485dSMiklos Szeredi oh.len != nbytes) 831334f485dSMiklos Szeredi goto err_finish; 832334f485dSMiklos Szeredi 833d7133114SMiklos Szeredi spin_lock(&fc->lock); 83469a53bf2SMiklos Szeredi err = -ENOENT; 83569a53bf2SMiklos Szeredi if (!fc->connected) 83669a53bf2SMiklos Szeredi goto err_unlock; 83769a53bf2SMiklos Szeredi 838334f485dSMiklos Szeredi req = request_find(fc, oh.unique); 839334f485dSMiklos Szeredi if (!req) 840334f485dSMiklos Szeredi goto err_unlock; 841334f485dSMiklos Szeredi 842f9a2842eSMiklos Szeredi if (req->aborted) { 843d7133114SMiklos Szeredi spin_unlock(&fc->lock); 844334f485dSMiklos Szeredi fuse_copy_finish(&cs); 845d7133114SMiklos Szeredi spin_lock(&fc->lock); 846222f1d69SMiklos Szeredi request_end(fc, req); 847334f485dSMiklos Szeredi return -ENOENT; 848334f485dSMiklos Szeredi } 849a4d27e75SMiklos Szeredi /* Is it an interrupt reply? */ 850a4d27e75SMiklos Szeredi if (req->intr_unique == oh.unique) { 851a4d27e75SMiklos Szeredi err = -EINVAL; 852a4d27e75SMiklos Szeredi if (nbytes != sizeof(struct fuse_out_header)) 853a4d27e75SMiklos Szeredi goto err_unlock; 854a4d27e75SMiklos Szeredi 855a4d27e75SMiklos Szeredi if (oh.error == -ENOSYS) 856a4d27e75SMiklos Szeredi fc->no_interrupt = 1; 857a4d27e75SMiklos Szeredi else if (oh.error == -EAGAIN) 858a4d27e75SMiklos Szeredi queue_interrupt(fc, req); 859a4d27e75SMiklos Szeredi 860a4d27e75SMiklos Szeredi spin_unlock(&fc->lock); 861a4d27e75SMiklos Szeredi fuse_copy_finish(&cs); 862a4d27e75SMiklos Szeredi return nbytes; 863a4d27e75SMiklos Szeredi } 864a4d27e75SMiklos Szeredi 865a4d27e75SMiklos Szeredi req->state = FUSE_REQ_WRITING; 866d77a1d5bSMiklos Szeredi list_move(&req->list, &fc->io); 867334f485dSMiklos Szeredi req->out.h = oh; 868334f485dSMiklos Szeredi req->locked = 1; 869334f485dSMiklos Szeredi cs.req = req; 870d7133114SMiklos Szeredi spin_unlock(&fc->lock); 871334f485dSMiklos Szeredi 872334f485dSMiklos Szeredi err = copy_out_args(&cs, &req->out, nbytes); 873334f485dSMiklos Szeredi fuse_copy_finish(&cs); 874334f485dSMiklos Szeredi 875d7133114SMiklos Szeredi spin_lock(&fc->lock); 876334f485dSMiklos Szeredi req->locked = 0; 877334f485dSMiklos Szeredi if (!err) { 878f9a2842eSMiklos Szeredi if (req->aborted) 879334f485dSMiklos Szeredi err = -ENOENT; 880f9a2842eSMiklos Szeredi } else if (!req->aborted) 881334f485dSMiklos Szeredi req->out.h.error = -EIO; 882334f485dSMiklos Szeredi request_end(fc, req); 883334f485dSMiklos Szeredi 884334f485dSMiklos Szeredi return err ? err : nbytes; 885334f485dSMiklos Szeredi 886334f485dSMiklos Szeredi err_unlock: 887d7133114SMiklos Szeredi spin_unlock(&fc->lock); 888334f485dSMiklos Szeredi err_finish: 889334f485dSMiklos Szeredi fuse_copy_finish(&cs); 890334f485dSMiklos Szeredi return err; 891334f485dSMiklos Szeredi } 892334f485dSMiklos Szeredi 893334f485dSMiklos Szeredi static unsigned fuse_dev_poll(struct file *file, poll_table *wait) 894334f485dSMiklos Szeredi { 895334f485dSMiklos Szeredi unsigned mask = POLLOUT | POLLWRNORM; 8967025d9adSMiklos Szeredi struct fuse_conn *fc = fuse_get_conn(file); 897334f485dSMiklos Szeredi if (!fc) 8987025d9adSMiklos Szeredi return POLLERR; 899334f485dSMiklos Szeredi 900334f485dSMiklos Szeredi poll_wait(file, &fc->waitq, wait); 901334f485dSMiklos Szeredi 902d7133114SMiklos Szeredi spin_lock(&fc->lock); 9037025d9adSMiklos Szeredi if (!fc->connected) 9047025d9adSMiklos Szeredi mask = POLLERR; 905a4d27e75SMiklos Szeredi else if (request_pending(fc)) 906334f485dSMiklos Szeredi mask |= POLLIN | POLLRDNORM; 907d7133114SMiklos Szeredi spin_unlock(&fc->lock); 908334f485dSMiklos Szeredi 909334f485dSMiklos Szeredi return mask; 910334f485dSMiklos Szeredi } 911334f485dSMiklos Szeredi 91269a53bf2SMiklos Szeredi /* 91369a53bf2SMiklos Szeredi * Abort all requests on the given list (pending or processing) 91469a53bf2SMiklos Szeredi * 915d7133114SMiklos Szeredi * This function releases and reacquires fc->lock 91669a53bf2SMiklos Szeredi */ 917334f485dSMiklos Szeredi static void end_requests(struct fuse_conn *fc, struct list_head *head) 918334f485dSMiklos Szeredi { 919334f485dSMiklos Szeredi while (!list_empty(head)) { 920334f485dSMiklos Szeredi struct fuse_req *req; 921334f485dSMiklos Szeredi req = list_entry(head->next, struct fuse_req, list); 922334f485dSMiklos Szeredi req->out.h.error = -ECONNABORTED; 923334f485dSMiklos Szeredi request_end(fc, req); 924d7133114SMiklos Szeredi spin_lock(&fc->lock); 925334f485dSMiklos Szeredi } 926334f485dSMiklos Szeredi } 927334f485dSMiklos Szeredi 92869a53bf2SMiklos Szeredi /* 92969a53bf2SMiklos Szeredi * Abort requests under I/O 93069a53bf2SMiklos Szeredi * 931f9a2842eSMiklos Szeredi * The requests are set to aborted and finished, and the request 93269a53bf2SMiklos Szeredi * waiter is woken up. This will make request_wait_answer() wait 93369a53bf2SMiklos Szeredi * until the request is unlocked and then return. 93464c6d8edSMiklos Szeredi * 93564c6d8edSMiklos Szeredi * If the request is asynchronous, then the end function needs to be 93664c6d8edSMiklos Szeredi * called after waiting for the request to be unlocked (if it was 93764c6d8edSMiklos Szeredi * locked). 93869a53bf2SMiklos Szeredi */ 93969a53bf2SMiklos Szeredi static void end_io_requests(struct fuse_conn *fc) 94069a53bf2SMiklos Szeredi { 94169a53bf2SMiklos Szeredi while (!list_empty(&fc->io)) { 94264c6d8edSMiklos Szeredi struct fuse_req *req = 94364c6d8edSMiklos Szeredi list_entry(fc->io.next, struct fuse_req, list); 94464c6d8edSMiklos Szeredi void (*end) (struct fuse_conn *, struct fuse_req *) = req->end; 94564c6d8edSMiklos Szeredi 946f9a2842eSMiklos Szeredi req->aborted = 1; 94769a53bf2SMiklos Szeredi req->out.h.error = -ECONNABORTED; 94869a53bf2SMiklos Szeredi req->state = FUSE_REQ_FINISHED; 94969a53bf2SMiklos Szeredi list_del_init(&req->list); 95069a53bf2SMiklos Szeredi wake_up(&req->waitq); 95164c6d8edSMiklos Szeredi if (end) { 95264c6d8edSMiklos Szeredi req->end = NULL; 95364c6d8edSMiklos Szeredi /* The end function will consume this reference */ 95464c6d8edSMiklos Szeredi __fuse_get_request(req); 955d7133114SMiklos Szeredi spin_unlock(&fc->lock); 95664c6d8edSMiklos Szeredi wait_event(req->waitq, !req->locked); 95764c6d8edSMiklos Szeredi end(fc, req); 958d7133114SMiklos Szeredi spin_lock(&fc->lock); 95964c6d8edSMiklos Szeredi } 96069a53bf2SMiklos Szeredi } 96169a53bf2SMiklos Szeredi } 96269a53bf2SMiklos Szeredi 96369a53bf2SMiklos Szeredi /* 96469a53bf2SMiklos Szeredi * Abort all requests. 96569a53bf2SMiklos Szeredi * 96669a53bf2SMiklos Szeredi * Emergency exit in case of a malicious or accidental deadlock, or 96769a53bf2SMiklos Szeredi * just a hung filesystem. 96869a53bf2SMiklos Szeredi * 96969a53bf2SMiklos Szeredi * The same effect is usually achievable through killing the 97069a53bf2SMiklos Szeredi * filesystem daemon and all users of the filesystem. The exception 97169a53bf2SMiklos Szeredi * is the combination of an asynchronous request and the tricky 97269a53bf2SMiklos Szeredi * deadlock (see Documentation/filesystems/fuse.txt). 97369a53bf2SMiklos Szeredi * 97469a53bf2SMiklos Szeredi * During the aborting, progression of requests from the pending and 97569a53bf2SMiklos Szeredi * processing lists onto the io list, and progression of new requests 97669a53bf2SMiklos Szeredi * onto the pending list is prevented by req->connected being false. 97769a53bf2SMiklos Szeredi * 97869a53bf2SMiklos Szeredi * Progression of requests under I/O to the processing list is 979f9a2842eSMiklos Szeredi * prevented by the req->aborted flag being true for these requests. 980f9a2842eSMiklos Szeredi * For this reason requests on the io list must be aborted first. 98169a53bf2SMiklos Szeredi */ 98269a53bf2SMiklos Szeredi void fuse_abort_conn(struct fuse_conn *fc) 98369a53bf2SMiklos Szeredi { 984d7133114SMiklos Szeredi spin_lock(&fc->lock); 98569a53bf2SMiklos Szeredi if (fc->connected) { 98669a53bf2SMiklos Szeredi fc->connected = 0; 98751eb01e7SMiklos Szeredi fc->blocked = 0; 98869a53bf2SMiklos Szeredi end_io_requests(fc); 98969a53bf2SMiklos Szeredi end_requests(fc, &fc->pending); 99069a53bf2SMiklos Szeredi end_requests(fc, &fc->processing); 99169a53bf2SMiklos Szeredi wake_up_all(&fc->waitq); 99251eb01e7SMiklos Szeredi wake_up_all(&fc->blocked_waitq); 993385a17bfSJeff Dike kill_fasync(&fc->fasync, SIGIO, POLL_IN); 99469a53bf2SMiklos Szeredi } 995d7133114SMiklos Szeredi spin_unlock(&fc->lock); 99669a53bf2SMiklos Szeredi } 99769a53bf2SMiklos Szeredi 998334f485dSMiklos Szeredi static int fuse_dev_release(struct inode *inode, struct file *file) 999334f485dSMiklos Szeredi { 10000720b315SMiklos Szeredi struct fuse_conn *fc = fuse_get_conn(file); 1001334f485dSMiklos Szeredi if (fc) { 1002d7133114SMiklos Szeredi spin_lock(&fc->lock); 10031e9a4ed9SMiklos Szeredi fc->connected = 0; 1004334f485dSMiklos Szeredi end_requests(fc, &fc->pending); 1005334f485dSMiklos Szeredi end_requests(fc, &fc->processing); 1006d7133114SMiklos Szeredi spin_unlock(&fc->lock); 1007385a17bfSJeff Dike fasync_helper(-1, file, 0, &fc->fasync); 1008bafa9654SMiklos Szeredi fuse_conn_put(fc); 1009385a17bfSJeff Dike } 1010f543f253SMiklos Szeredi 1011334f485dSMiklos Szeredi return 0; 1012334f485dSMiklos Szeredi } 1013334f485dSMiklos Szeredi 1014385a17bfSJeff Dike static int fuse_dev_fasync(int fd, struct file *file, int on) 1015385a17bfSJeff Dike { 1016385a17bfSJeff Dike struct fuse_conn *fc = fuse_get_conn(file); 1017385a17bfSJeff Dike if (!fc) 1018a87046d8SMiklos Szeredi return -EPERM; 1019385a17bfSJeff Dike 1020385a17bfSJeff Dike /* No locking - fasync_helper does its own locking */ 1021385a17bfSJeff Dike return fasync_helper(fd, file, on, &fc->fasync); 1022385a17bfSJeff Dike } 1023385a17bfSJeff Dike 10244b6f5d20SArjan van de Ven const struct file_operations fuse_dev_operations = { 1025334f485dSMiklos Szeredi .owner = THIS_MODULE, 1026334f485dSMiklos Szeredi .llseek = no_llseek, 1027ee0b3e67SBadari Pulavarty .read = do_sync_read, 1028ee0b3e67SBadari Pulavarty .aio_read = fuse_dev_read, 1029ee0b3e67SBadari Pulavarty .write = do_sync_write, 1030ee0b3e67SBadari Pulavarty .aio_write = fuse_dev_write, 1031334f485dSMiklos Szeredi .poll = fuse_dev_poll, 1032334f485dSMiklos Szeredi .release = fuse_dev_release, 1033385a17bfSJeff Dike .fasync = fuse_dev_fasync, 1034334f485dSMiklos Szeredi }; 1035334f485dSMiklos Szeredi 1036334f485dSMiklos Szeredi static struct miscdevice fuse_miscdevice = { 1037334f485dSMiklos Szeredi .minor = FUSE_MINOR, 1038334f485dSMiklos Szeredi .name = "fuse", 1039334f485dSMiklos Szeredi .fops = &fuse_dev_operations, 1040334f485dSMiklos Szeredi }; 1041334f485dSMiklos Szeredi 1042334f485dSMiklos Szeredi int __init fuse_dev_init(void) 1043334f485dSMiklos Szeredi { 1044334f485dSMiklos Szeredi int err = -ENOMEM; 1045334f485dSMiklos Szeredi fuse_req_cachep = kmem_cache_create("fuse_request", 1046334f485dSMiklos Szeredi sizeof(struct fuse_req), 1047334f485dSMiklos Szeredi 0, 0, NULL, NULL); 1048334f485dSMiklos Szeredi if (!fuse_req_cachep) 1049334f485dSMiklos Szeredi goto out; 1050334f485dSMiklos Szeredi 1051334f485dSMiklos Szeredi err = misc_register(&fuse_miscdevice); 1052334f485dSMiklos Szeredi if (err) 1053334f485dSMiklos Szeredi goto out_cache_clean; 1054334f485dSMiklos Szeredi 1055334f485dSMiklos Szeredi return 0; 1056334f485dSMiklos Szeredi 1057334f485dSMiklos Szeredi out_cache_clean: 1058334f485dSMiklos Szeredi kmem_cache_destroy(fuse_req_cachep); 1059334f485dSMiklos Szeredi out: 1060334f485dSMiklos Szeredi return err; 1061334f485dSMiklos Szeredi } 1062334f485dSMiklos Szeredi 1063334f485dSMiklos Szeredi void fuse_dev_cleanup(void) 1064334f485dSMiklos Szeredi { 1065334f485dSMiklos Szeredi misc_deregister(&fuse_miscdevice); 1066334f485dSMiklos Szeredi kmem_cache_destroy(fuse_req_cachep); 1067334f485dSMiklos Szeredi } 1068