1334f485dSMiklos Szeredi /* 2334f485dSMiklos Szeredi FUSE: Filesystem in Userspace 31729a16cSMiklos Szeredi Copyright (C) 2001-2008 Miklos Szeredi <miklos@szeredi.hu> 4334f485dSMiklos Szeredi 5334f485dSMiklos Szeredi This program can be distributed under the terms of the GNU GPL. 6334f485dSMiklos Szeredi See the file COPYING. 7334f485dSMiklos Szeredi */ 8334f485dSMiklos Szeredi 9334f485dSMiklos Szeredi #include "fuse_i.h" 10334f485dSMiklos Szeredi 11334f485dSMiklos Szeredi #include <linux/init.h> 12334f485dSMiklos Szeredi #include <linux/module.h> 13334f485dSMiklos Szeredi #include <linux/poll.h> 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 22e18b890bSChristoph Lameter static struct kmem_cache *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 503be5a52bSMiklos Szeredi struct fuse_req *fuse_request_alloc_nofs(void) 513be5a52bSMiklos Szeredi { 523be5a52bSMiklos Szeredi struct fuse_req *req = kmem_cache_alloc(fuse_req_cachep, GFP_NOFS); 533be5a52bSMiklos Szeredi if (req) 543be5a52bSMiklos Szeredi fuse_request_init(req); 553be5a52bSMiklos Szeredi return req; 563be5a52bSMiklos Szeredi } 573be5a52bSMiklos Szeredi 58334f485dSMiklos Szeredi void fuse_request_free(struct fuse_req *req) 59334f485dSMiklos Szeredi { 60334f485dSMiklos Szeredi kmem_cache_free(fuse_req_cachep, req); 61334f485dSMiklos Szeredi } 62334f485dSMiklos Szeredi 638bfc016dSMiklos Szeredi static void block_sigs(sigset_t *oldset) 64334f485dSMiklos Szeredi { 65334f485dSMiklos Szeredi sigset_t mask; 66334f485dSMiklos Szeredi 67334f485dSMiklos Szeredi siginitsetinv(&mask, sigmask(SIGKILL)); 68334f485dSMiklos Szeredi sigprocmask(SIG_BLOCK, &mask, oldset); 69334f485dSMiklos Szeredi } 70334f485dSMiklos Szeredi 718bfc016dSMiklos Szeredi static void restore_sigs(sigset_t *oldset) 72334f485dSMiklos Szeredi { 73334f485dSMiklos Szeredi sigprocmask(SIG_SETMASK, oldset, NULL); 74334f485dSMiklos Szeredi } 75334f485dSMiklos Szeredi 76334f485dSMiklos Szeredi static void __fuse_get_request(struct fuse_req *req) 77334f485dSMiklos Szeredi { 78334f485dSMiklos Szeredi atomic_inc(&req->count); 79334f485dSMiklos Szeredi } 80334f485dSMiklos Szeredi 81334f485dSMiklos Szeredi /* Must be called with > 1 refcount */ 82334f485dSMiklos Szeredi static void __fuse_put_request(struct fuse_req *req) 83334f485dSMiklos Szeredi { 84334f485dSMiklos Szeredi BUG_ON(atomic_read(&req->count) < 2); 85334f485dSMiklos Szeredi atomic_dec(&req->count); 86334f485dSMiklos Szeredi } 87334f485dSMiklos Szeredi 8833649c91SMiklos Szeredi static void fuse_req_init_context(struct fuse_req *req) 8933649c91SMiklos Szeredi { 9033649c91SMiklos Szeredi req->in.h.uid = current->fsuid; 9133649c91SMiklos Szeredi req->in.h.gid = current->fsgid; 9233649c91SMiklos Szeredi req->in.h.pid = current->pid; 9333649c91SMiklos Szeredi } 9433649c91SMiklos Szeredi 95ce1d5a49SMiklos Szeredi struct fuse_req *fuse_get_req(struct fuse_conn *fc) 96334f485dSMiklos Szeredi { 9708a53cdcSMiklos Szeredi struct fuse_req *req; 9808a53cdcSMiklos Szeredi sigset_t oldset; 999bc5dddaSMiklos Szeredi int intr; 10008a53cdcSMiklos Szeredi int err; 10108a53cdcSMiklos Szeredi 1029bc5dddaSMiklos Szeredi atomic_inc(&fc->num_waiting); 10308a53cdcSMiklos Szeredi block_sigs(&oldset); 1049bc5dddaSMiklos Szeredi intr = wait_event_interruptible(fc->blocked_waitq, !fc->blocked); 10508a53cdcSMiklos Szeredi restore_sigs(&oldset); 1069bc5dddaSMiklos Szeredi err = -EINTR; 1079bc5dddaSMiklos Szeredi if (intr) 1089bc5dddaSMiklos Szeredi goto out; 10908a53cdcSMiklos Szeredi 11051eb01e7SMiklos Szeredi err = -ENOTCONN; 11151eb01e7SMiklos Szeredi if (!fc->connected) 11251eb01e7SMiklos Szeredi goto out; 11351eb01e7SMiklos Szeredi 11408a53cdcSMiklos Szeredi req = fuse_request_alloc(); 1159bc5dddaSMiklos Szeredi err = -ENOMEM; 116ce1d5a49SMiklos Szeredi if (!req) 1179bc5dddaSMiklos Szeredi goto out; 118334f485dSMiklos Szeredi 11933649c91SMiklos Szeredi fuse_req_init_context(req); 1209bc5dddaSMiklos Szeredi req->waiting = 1; 121334f485dSMiklos Szeredi return req; 1229bc5dddaSMiklos Szeredi 1239bc5dddaSMiklos Szeredi out: 1249bc5dddaSMiklos Szeredi atomic_dec(&fc->num_waiting); 1259bc5dddaSMiklos Szeredi return ERR_PTR(err); 126334f485dSMiklos Szeredi } 127334f485dSMiklos Szeredi 12833649c91SMiklos Szeredi /* 12933649c91SMiklos Szeredi * Return request in fuse_file->reserved_req. However that may 13033649c91SMiklos Szeredi * currently be in use. If that is the case, wait for it to become 13133649c91SMiklos Szeredi * available. 13233649c91SMiklos Szeredi */ 13333649c91SMiklos Szeredi static struct fuse_req *get_reserved_req(struct fuse_conn *fc, 13433649c91SMiklos Szeredi struct file *file) 13533649c91SMiklos Szeredi { 13633649c91SMiklos Szeredi struct fuse_req *req = NULL; 13733649c91SMiklos Szeredi struct fuse_file *ff = file->private_data; 13833649c91SMiklos Szeredi 13933649c91SMiklos Szeredi do { 140de5e3decSMiklos Szeredi wait_event(fc->reserved_req_waitq, ff->reserved_req); 14133649c91SMiklos Szeredi spin_lock(&fc->lock); 14233649c91SMiklos Szeredi if (ff->reserved_req) { 14333649c91SMiklos Szeredi req = ff->reserved_req; 14433649c91SMiklos Szeredi ff->reserved_req = NULL; 14533649c91SMiklos Szeredi get_file(file); 14633649c91SMiklos Szeredi req->stolen_file = file; 14733649c91SMiklos Szeredi } 14833649c91SMiklos Szeredi spin_unlock(&fc->lock); 14933649c91SMiklos Szeredi } while (!req); 15033649c91SMiklos Szeredi 15133649c91SMiklos Szeredi return req; 15233649c91SMiklos Szeredi } 15333649c91SMiklos Szeredi 15433649c91SMiklos Szeredi /* 15533649c91SMiklos Szeredi * Put stolen request back into fuse_file->reserved_req 15633649c91SMiklos Szeredi */ 15733649c91SMiklos Szeredi static void put_reserved_req(struct fuse_conn *fc, struct fuse_req *req) 15833649c91SMiklos Szeredi { 15933649c91SMiklos Szeredi struct file *file = req->stolen_file; 16033649c91SMiklos Szeredi struct fuse_file *ff = file->private_data; 16133649c91SMiklos Szeredi 16233649c91SMiklos Szeredi spin_lock(&fc->lock); 16333649c91SMiklos Szeredi fuse_request_init(req); 16433649c91SMiklos Szeredi BUG_ON(ff->reserved_req); 16533649c91SMiklos Szeredi ff->reserved_req = req; 166de5e3decSMiklos Szeredi wake_up_all(&fc->reserved_req_waitq); 16733649c91SMiklos Szeredi spin_unlock(&fc->lock); 16833649c91SMiklos Szeredi fput(file); 16933649c91SMiklos Szeredi } 17033649c91SMiklos Szeredi 17133649c91SMiklos Szeredi /* 17233649c91SMiklos Szeredi * Gets a requests for a file operation, always succeeds 17333649c91SMiklos Szeredi * 17433649c91SMiklos Szeredi * This is used for sending the FLUSH request, which must get to 17533649c91SMiklos Szeredi * userspace, due to POSIX locks which may need to be unlocked. 17633649c91SMiklos Szeredi * 17733649c91SMiklos Szeredi * If allocation fails due to OOM, use the reserved request in 17833649c91SMiklos Szeredi * fuse_file. 17933649c91SMiklos Szeredi * 18033649c91SMiklos Szeredi * This is very unlikely to deadlock accidentally, since the 18133649c91SMiklos Szeredi * filesystem should not have it's own file open. If deadlock is 18233649c91SMiklos Szeredi * intentional, it can still be broken by "aborting" the filesystem. 18333649c91SMiklos Szeredi */ 18433649c91SMiklos Szeredi struct fuse_req *fuse_get_req_nofail(struct fuse_conn *fc, struct file *file) 18533649c91SMiklos Szeredi { 18633649c91SMiklos Szeredi struct fuse_req *req; 18733649c91SMiklos Szeredi 18833649c91SMiklos Szeredi atomic_inc(&fc->num_waiting); 18933649c91SMiklos Szeredi wait_event(fc->blocked_waitq, !fc->blocked); 19033649c91SMiklos Szeredi req = fuse_request_alloc(); 19133649c91SMiklos Szeredi if (!req) 19233649c91SMiklos Szeredi req = get_reserved_req(fc, file); 19333649c91SMiklos Szeredi 19433649c91SMiklos Szeredi fuse_req_init_context(req); 19533649c91SMiklos Szeredi req->waiting = 1; 19633649c91SMiklos Szeredi return req; 19733649c91SMiklos Szeredi } 19833649c91SMiklos Szeredi 199334f485dSMiklos Szeredi void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req) 200334f485dSMiklos Szeredi { 2017128ec2aSMiklos Szeredi if (atomic_dec_and_test(&req->count)) { 2029bc5dddaSMiklos Szeredi if (req->waiting) 203ce1d5a49SMiklos Szeredi atomic_dec(&fc->num_waiting); 20433649c91SMiklos Szeredi 20533649c91SMiklos Szeredi if (req->stolen_file) 20633649c91SMiklos Szeredi put_reserved_req(fc, req); 20733649c91SMiklos Szeredi else 208ce1d5a49SMiklos Szeredi fuse_request_free(req); 2097128ec2aSMiklos Szeredi } 2107128ec2aSMiklos Szeredi } 2117128ec2aSMiklos Szeredi 212d12def1bSMiklos Szeredi static unsigned len_args(unsigned numargs, struct fuse_arg *args) 213d12def1bSMiklos Szeredi { 214d12def1bSMiklos Szeredi unsigned nbytes = 0; 215d12def1bSMiklos Szeredi unsigned i; 216d12def1bSMiklos Szeredi 217d12def1bSMiklos Szeredi for (i = 0; i < numargs; i++) 218d12def1bSMiklos Szeredi nbytes += args[i].size; 219d12def1bSMiklos Szeredi 220d12def1bSMiklos Szeredi return nbytes; 221d12def1bSMiklos Szeredi } 222d12def1bSMiklos Szeredi 223d12def1bSMiklos Szeredi static u64 fuse_get_unique(struct fuse_conn *fc) 224d12def1bSMiklos Szeredi { 225d12def1bSMiklos Szeredi fc->reqctr++; 226d12def1bSMiklos Szeredi /* zero is special */ 227d12def1bSMiklos Szeredi if (fc->reqctr == 0) 228d12def1bSMiklos Szeredi fc->reqctr = 1; 229d12def1bSMiklos Szeredi 230d12def1bSMiklos Szeredi return fc->reqctr; 231d12def1bSMiklos Szeredi } 232d12def1bSMiklos Szeredi 233d12def1bSMiklos Szeredi static void queue_request(struct fuse_conn *fc, struct fuse_req *req) 234d12def1bSMiklos Szeredi { 235d12def1bSMiklos Szeredi req->in.h.unique = fuse_get_unique(fc); 236d12def1bSMiklos Szeredi req->in.h.len = sizeof(struct fuse_in_header) + 237d12def1bSMiklos Szeredi len_args(req->in.numargs, (struct fuse_arg *) req->in.args); 238d12def1bSMiklos Szeredi list_add_tail(&req->list, &fc->pending); 239d12def1bSMiklos Szeredi req->state = FUSE_REQ_PENDING; 240d12def1bSMiklos Szeredi if (!req->waiting) { 241d12def1bSMiklos Szeredi req->waiting = 1; 242d12def1bSMiklos Szeredi atomic_inc(&fc->num_waiting); 243d12def1bSMiklos Szeredi } 244d12def1bSMiklos Szeredi wake_up(&fc->waitq); 245d12def1bSMiklos Szeredi kill_fasync(&fc->fasync, SIGIO, POLL_IN); 246d12def1bSMiklos Szeredi } 247d12def1bSMiklos Szeredi 248d12def1bSMiklos Szeredi static void flush_bg_queue(struct fuse_conn *fc) 249d12def1bSMiklos Szeredi { 250d12def1bSMiklos Szeredi while (fc->active_background < FUSE_MAX_BACKGROUND && 251d12def1bSMiklos Szeredi !list_empty(&fc->bg_queue)) { 252d12def1bSMiklos Szeredi struct fuse_req *req; 253d12def1bSMiklos Szeredi 254d12def1bSMiklos Szeredi req = list_entry(fc->bg_queue.next, struct fuse_req, list); 255d12def1bSMiklos Szeredi list_del(&req->list); 256d12def1bSMiklos Szeredi fc->active_background++; 257d12def1bSMiklos Szeredi queue_request(fc, req); 258d12def1bSMiklos Szeredi } 259d12def1bSMiklos Szeredi } 260d12def1bSMiklos Szeredi 2616dbbcb12SMiklos Szeredi /* 262334f485dSMiklos Szeredi * This function is called when a request is finished. Either a reply 263f9a2842eSMiklos Szeredi * has arrived or it was aborted (and not yet sent) or some error 264f43b155aSMiklos Szeredi * occurred during communication with userspace, or the device file 26551eb01e7SMiklos Szeredi * was closed. The requester thread is woken up (if still waiting), 26651eb01e7SMiklos Szeredi * the 'end' callback is called if given, else the reference to the 26751eb01e7SMiklos Szeredi * request is released 2687128ec2aSMiklos Szeredi * 269d7133114SMiklos Szeredi * Called with fc->lock, unlocks it 270334f485dSMiklos Szeredi */ 271334f485dSMiklos Szeredi static void request_end(struct fuse_conn *fc, struct fuse_req *req) 272105f4d7aSJosh Triplett __releases(fc->lock) 273334f485dSMiklos Szeredi { 2747128ec2aSMiklos Szeredi void (*end) (struct fuse_conn *, struct fuse_req *) = req->end; 2757128ec2aSMiklos Szeredi req->end = NULL; 27651eb01e7SMiklos Szeredi list_del(&req->list); 277a4d27e75SMiklos Szeredi list_del(&req->intr_entry); 27851eb01e7SMiklos Szeredi req->state = FUSE_REQ_FINISHED; 27951eb01e7SMiklos Szeredi if (req->background) { 28051eb01e7SMiklos Szeredi if (fc->num_background == FUSE_MAX_BACKGROUND) { 28151eb01e7SMiklos Szeredi fc->blocked = 0; 28251eb01e7SMiklos Szeredi wake_up_all(&fc->blocked_waitq); 28351eb01e7SMiklos Szeredi } 284f92b99b9SMiklos Szeredi if (fc->num_background == FUSE_CONGESTION_THRESHOLD) { 285f92b99b9SMiklos Szeredi clear_bdi_congested(&fc->bdi, READ); 286f92b99b9SMiklos Szeredi clear_bdi_congested(&fc->bdi, WRITE); 287f92b99b9SMiklos Szeredi } 28851eb01e7SMiklos Szeredi fc->num_background--; 289d12def1bSMiklos Szeredi fc->active_background--; 290d12def1bSMiklos Szeredi flush_bg_queue(fc); 29151eb01e7SMiklos Szeredi } 292d7133114SMiklos Szeredi spin_unlock(&fc->lock); 29351eb01e7SMiklos Szeredi wake_up(&req->waitq); 29464c6d8edSMiklos Szeredi if (end) 29564c6d8edSMiklos Szeredi end(fc, req); 296f43b155aSMiklos Szeredi fuse_put_request(fc, req); 297334f485dSMiklos Szeredi } 298334f485dSMiklos Szeredi 299a4d27e75SMiklos Szeredi static void wait_answer_interruptible(struct fuse_conn *fc, 300a4d27e75SMiklos Szeredi struct fuse_req *req) 3014dbf930eSMiklos Szeredi __releases(fc->lock) __acquires(fc->lock) 302a4d27e75SMiklos Szeredi { 303a4d27e75SMiklos Szeredi if (signal_pending(current)) 304a4d27e75SMiklos Szeredi return; 305a4d27e75SMiklos Szeredi 306a4d27e75SMiklos Szeredi spin_unlock(&fc->lock); 307a4d27e75SMiklos Szeredi wait_event_interruptible(req->waitq, req->state == FUSE_REQ_FINISHED); 308a4d27e75SMiklos Szeredi spin_lock(&fc->lock); 309a4d27e75SMiklos Szeredi } 310a4d27e75SMiklos Szeredi 311a4d27e75SMiklos Szeredi static void queue_interrupt(struct fuse_conn *fc, struct fuse_req *req) 312a4d27e75SMiklos Szeredi { 313a4d27e75SMiklos Szeredi list_add_tail(&req->intr_entry, &fc->interrupts); 314a4d27e75SMiklos Szeredi wake_up(&fc->waitq); 315a4d27e75SMiklos Szeredi kill_fasync(&fc->fasync, SIGIO, POLL_IN); 316a4d27e75SMiklos Szeredi } 317a4d27e75SMiklos Szeredi 3187c352bdfSMiklos Szeredi static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req) 3194dbf930eSMiklos Szeredi __releases(fc->lock) __acquires(fc->lock) 320334f485dSMiklos Szeredi { 321a4d27e75SMiklos Szeredi if (!fc->no_interrupt) { 322a4d27e75SMiklos Szeredi /* Any signal may interrupt this */ 323a4d27e75SMiklos Szeredi wait_answer_interruptible(fc, req); 324334f485dSMiklos Szeredi 325a4d27e75SMiklos Szeredi if (req->aborted) 326a4d27e75SMiklos Szeredi goto aborted; 327a4d27e75SMiklos Szeredi if (req->state == FUSE_REQ_FINISHED) 328334f485dSMiklos Szeredi return; 329334f485dSMiklos Szeredi 330a4d27e75SMiklos Szeredi req->interrupted = 1; 331a4d27e75SMiklos Szeredi if (req->state == FUSE_REQ_SENT) 332a4d27e75SMiklos Szeredi queue_interrupt(fc, req); 333a4d27e75SMiklos Szeredi } 334a4d27e75SMiklos Szeredi 335a131de0aSMiklos Szeredi if (!req->force) { 336a4d27e75SMiklos Szeredi sigset_t oldset; 337a4d27e75SMiklos Szeredi 338a4d27e75SMiklos Szeredi /* Only fatal signals may interrupt this */ 339a4d27e75SMiklos Szeredi block_sigs(&oldset); 340a4d27e75SMiklos Szeredi wait_answer_interruptible(fc, req); 341a4d27e75SMiklos Szeredi restore_sigs(&oldset); 342a4d27e75SMiklos Szeredi 343a4d27e75SMiklos Szeredi if (req->aborted) 344a4d27e75SMiklos Szeredi goto aborted; 345a4d27e75SMiklos Szeredi if (req->state == FUSE_REQ_FINISHED) 346a4d27e75SMiklos Szeredi return; 347a4d27e75SMiklos Szeredi 348a131de0aSMiklos Szeredi /* Request is not yet in userspace, bail out */ 349a131de0aSMiklos Szeredi if (req->state == FUSE_REQ_PENDING) { 350a131de0aSMiklos Szeredi list_del(&req->list); 351a131de0aSMiklos Szeredi __fuse_put_request(req); 352334f485dSMiklos Szeredi req->out.h.error = -EINTR; 353a131de0aSMiklos Szeredi return; 354a131de0aSMiklos Szeredi } 355a131de0aSMiklos Szeredi } 356a131de0aSMiklos Szeredi 357a131de0aSMiklos Szeredi /* 358a131de0aSMiklos Szeredi * Either request is already in userspace, or it was forced. 359a131de0aSMiklos Szeredi * Wait it out. 360a131de0aSMiklos Szeredi */ 361a131de0aSMiklos Szeredi spin_unlock(&fc->lock); 362a131de0aSMiklos Szeredi wait_event(req->waitq, req->state == FUSE_REQ_FINISHED); 363a131de0aSMiklos Szeredi spin_lock(&fc->lock); 364a131de0aSMiklos Szeredi 365a131de0aSMiklos Szeredi if (!req->aborted) 366a131de0aSMiklos Szeredi return; 367a4d27e75SMiklos Szeredi 368a4d27e75SMiklos Szeredi aborted: 369a131de0aSMiklos Szeredi BUG_ON(req->state != FUSE_REQ_FINISHED); 370334f485dSMiklos Szeredi if (req->locked) { 371334f485dSMiklos Szeredi /* This is uninterruptible sleep, because data is 372334f485dSMiklos Szeredi being copied to/from the buffers of req. During 373334f485dSMiklos Szeredi locked state, there mustn't be any filesystem 374334f485dSMiklos Szeredi operation (e.g. page fault), since that could lead 375334f485dSMiklos Szeredi to deadlock */ 376d7133114SMiklos Szeredi spin_unlock(&fc->lock); 377334f485dSMiklos Szeredi wait_event(req->waitq, !req->locked); 378d7133114SMiklos Szeredi spin_lock(&fc->lock); 379334f485dSMiklos Szeredi } 380334f485dSMiklos Szeredi } 381334f485dSMiklos Szeredi 3827c352bdfSMiklos Szeredi void request_send(struct fuse_conn *fc, struct fuse_req *req) 383334f485dSMiklos Szeredi { 384334f485dSMiklos Szeredi req->isreply = 1; 385d7133114SMiklos Szeredi spin_lock(&fc->lock); 3861e9a4ed9SMiklos Szeredi if (!fc->connected) 387334f485dSMiklos Szeredi req->out.h.error = -ENOTCONN; 388334f485dSMiklos Szeredi else if (fc->conn_error) 389334f485dSMiklos Szeredi req->out.h.error = -ECONNREFUSED; 390334f485dSMiklos Szeredi else { 391334f485dSMiklos Szeredi queue_request(fc, req); 392334f485dSMiklos Szeredi /* acquire extra reference, since request is still needed 393334f485dSMiklos Szeredi after request_end() */ 394334f485dSMiklos Szeredi __fuse_get_request(req); 395334f485dSMiklos Szeredi 3967c352bdfSMiklos Szeredi request_wait_answer(fc, req); 397334f485dSMiklos Szeredi } 398d7133114SMiklos Szeredi spin_unlock(&fc->lock); 399334f485dSMiklos Szeredi } 400334f485dSMiklos Szeredi 401d12def1bSMiklos Szeredi static void request_send_nowait_locked(struct fuse_conn *fc, 402d12def1bSMiklos Szeredi struct fuse_req *req) 403334f485dSMiklos Szeredi { 40451eb01e7SMiklos Szeredi req->background = 1; 40551eb01e7SMiklos Szeredi fc->num_background++; 40651eb01e7SMiklos Szeredi if (fc->num_background == FUSE_MAX_BACKGROUND) 40751eb01e7SMiklos Szeredi fc->blocked = 1; 408f92b99b9SMiklos Szeredi if (fc->num_background == FUSE_CONGESTION_THRESHOLD) { 409f92b99b9SMiklos Szeredi set_bdi_congested(&fc->bdi, READ); 410f92b99b9SMiklos Szeredi set_bdi_congested(&fc->bdi, WRITE); 411f92b99b9SMiklos Szeredi } 412d12def1bSMiklos Szeredi list_add_tail(&req->list, &fc->bg_queue); 413d12def1bSMiklos Szeredi flush_bg_queue(fc); 414d12def1bSMiklos Szeredi } 41551eb01e7SMiklos Szeredi 416d12def1bSMiklos Szeredi static void request_send_nowait(struct fuse_conn *fc, struct fuse_req *req) 417d12def1bSMiklos Szeredi { 418d12def1bSMiklos Szeredi spin_lock(&fc->lock); 419d12def1bSMiklos Szeredi if (fc->connected) { 420d12def1bSMiklos Szeredi request_send_nowait_locked(fc, req); 421d7133114SMiklos Szeredi spin_unlock(&fc->lock); 422334f485dSMiklos Szeredi } else { 423334f485dSMiklos Szeredi req->out.h.error = -ENOTCONN; 424334f485dSMiklos Szeredi request_end(fc, req); 425334f485dSMiklos Szeredi } 426334f485dSMiklos Szeredi } 427334f485dSMiklos Szeredi 428334f485dSMiklos Szeredi void request_send_noreply(struct fuse_conn *fc, struct fuse_req *req) 429334f485dSMiklos Szeredi { 430334f485dSMiklos Szeredi req->isreply = 0; 431334f485dSMiklos Szeredi request_send_nowait(fc, req); 432334f485dSMiklos Szeredi } 433334f485dSMiklos Szeredi 434334f485dSMiklos Szeredi void request_send_background(struct fuse_conn *fc, struct fuse_req *req) 435334f485dSMiklos Szeredi { 436334f485dSMiklos Szeredi req->isreply = 1; 437334f485dSMiklos Szeredi request_send_nowait(fc, req); 438334f485dSMiklos Szeredi } 439334f485dSMiklos Szeredi 440334f485dSMiklos Szeredi /* 4413be5a52bSMiklos Szeredi * Called under fc->lock 4423be5a52bSMiklos Szeredi * 4433be5a52bSMiklos Szeredi * fc->connected must have been checked previously 4443be5a52bSMiklos Szeredi */ 4453be5a52bSMiklos Szeredi void request_send_background_locked(struct fuse_conn *fc, struct fuse_req *req) 4463be5a52bSMiklos Szeredi { 4473be5a52bSMiklos Szeredi req->isreply = 1; 4483be5a52bSMiklos Szeredi request_send_nowait_locked(fc, req); 4493be5a52bSMiklos Szeredi } 4503be5a52bSMiklos Szeredi 4513be5a52bSMiklos Szeredi /* 452334f485dSMiklos Szeredi * Lock the request. Up to the next unlock_request() there mustn't be 453334f485dSMiklos Szeredi * anything that could cause a page-fault. If the request was already 454f9a2842eSMiklos Szeredi * aborted bail out. 455334f485dSMiklos Szeredi */ 456d7133114SMiklos Szeredi static int lock_request(struct fuse_conn *fc, struct fuse_req *req) 457334f485dSMiklos Szeredi { 458334f485dSMiklos Szeredi int err = 0; 459334f485dSMiklos Szeredi if (req) { 460d7133114SMiklos Szeredi spin_lock(&fc->lock); 461f9a2842eSMiklos Szeredi if (req->aborted) 462334f485dSMiklos Szeredi err = -ENOENT; 463334f485dSMiklos Szeredi else 464334f485dSMiklos Szeredi req->locked = 1; 465d7133114SMiklos Szeredi spin_unlock(&fc->lock); 466334f485dSMiklos Szeredi } 467334f485dSMiklos Szeredi return err; 468334f485dSMiklos Szeredi } 469334f485dSMiklos Szeredi 470334f485dSMiklos Szeredi /* 471f9a2842eSMiklos Szeredi * Unlock request. If it was aborted during being locked, the 472334f485dSMiklos Szeredi * requester thread is currently waiting for it to be unlocked, so 473334f485dSMiklos Szeredi * wake it up. 474334f485dSMiklos Szeredi */ 475d7133114SMiklos Szeredi static void unlock_request(struct fuse_conn *fc, struct fuse_req *req) 476334f485dSMiklos Szeredi { 477334f485dSMiklos Szeredi if (req) { 478d7133114SMiklos Szeredi spin_lock(&fc->lock); 479334f485dSMiklos Szeredi req->locked = 0; 480f9a2842eSMiklos Szeredi if (req->aborted) 481334f485dSMiklos Szeredi wake_up(&req->waitq); 482d7133114SMiklos Szeredi spin_unlock(&fc->lock); 483334f485dSMiklos Szeredi } 484334f485dSMiklos Szeredi } 485334f485dSMiklos Szeredi 486334f485dSMiklos Szeredi struct fuse_copy_state { 487d7133114SMiklos Szeredi struct fuse_conn *fc; 488334f485dSMiklos Szeredi int write; 489334f485dSMiklos Szeredi struct fuse_req *req; 490334f485dSMiklos Szeredi const struct iovec *iov; 491334f485dSMiklos Szeredi unsigned long nr_segs; 492334f485dSMiklos Szeredi unsigned long seglen; 493334f485dSMiklos Szeredi unsigned long addr; 494334f485dSMiklos Szeredi struct page *pg; 495334f485dSMiklos Szeredi void *mapaddr; 496334f485dSMiklos Szeredi void *buf; 497334f485dSMiklos Szeredi unsigned len; 498334f485dSMiklos Szeredi }; 499334f485dSMiklos Szeredi 500d7133114SMiklos Szeredi static void fuse_copy_init(struct fuse_copy_state *cs, struct fuse_conn *fc, 501d7133114SMiklos Szeredi int write, struct fuse_req *req, 502d7133114SMiklos Szeredi const struct iovec *iov, unsigned long nr_segs) 503334f485dSMiklos Szeredi { 504334f485dSMiklos Szeredi memset(cs, 0, sizeof(*cs)); 505d7133114SMiklos Szeredi cs->fc = fc; 506334f485dSMiklos Szeredi cs->write = write; 507334f485dSMiklos Szeredi cs->req = req; 508334f485dSMiklos Szeredi cs->iov = iov; 509334f485dSMiklos Szeredi cs->nr_segs = nr_segs; 510334f485dSMiklos Szeredi } 511334f485dSMiklos Szeredi 512334f485dSMiklos Szeredi /* Unmap and put previous page of userspace buffer */ 5138bfc016dSMiklos Szeredi static void fuse_copy_finish(struct fuse_copy_state *cs) 514334f485dSMiklos Szeredi { 515334f485dSMiklos Szeredi if (cs->mapaddr) { 516334f485dSMiklos Szeredi kunmap_atomic(cs->mapaddr, KM_USER0); 517334f485dSMiklos Szeredi if (cs->write) { 518334f485dSMiklos Szeredi flush_dcache_page(cs->pg); 519334f485dSMiklos Szeredi set_page_dirty_lock(cs->pg); 520334f485dSMiklos Szeredi } 521334f485dSMiklos Szeredi put_page(cs->pg); 522334f485dSMiklos Szeredi cs->mapaddr = NULL; 523334f485dSMiklos Szeredi } 524334f485dSMiklos Szeredi } 525334f485dSMiklos Szeredi 526334f485dSMiklos Szeredi /* 527334f485dSMiklos Szeredi * Get another pagefull of userspace buffer, and map it to kernel 528334f485dSMiklos Szeredi * address space, and lock request 529334f485dSMiklos Szeredi */ 530334f485dSMiklos Szeredi static int fuse_copy_fill(struct fuse_copy_state *cs) 531334f485dSMiklos Szeredi { 532334f485dSMiklos Szeredi unsigned long offset; 533334f485dSMiklos Szeredi int err; 534334f485dSMiklos Szeredi 535d7133114SMiklos Szeredi unlock_request(cs->fc, cs->req); 536334f485dSMiklos Szeredi fuse_copy_finish(cs); 537334f485dSMiklos Szeredi if (!cs->seglen) { 538334f485dSMiklos Szeredi BUG_ON(!cs->nr_segs); 539334f485dSMiklos Szeredi cs->seglen = cs->iov[0].iov_len; 540334f485dSMiklos Szeredi cs->addr = (unsigned long) cs->iov[0].iov_base; 541334f485dSMiklos Szeredi cs->iov++; 542334f485dSMiklos Szeredi cs->nr_segs--; 543334f485dSMiklos Szeredi } 544334f485dSMiklos Szeredi down_read(¤t->mm->mmap_sem); 545334f485dSMiklos Szeredi err = get_user_pages(current, current->mm, cs->addr, 1, cs->write, 0, 546334f485dSMiklos Szeredi &cs->pg, NULL); 547334f485dSMiklos Szeredi up_read(¤t->mm->mmap_sem); 548334f485dSMiklos Szeredi if (err < 0) 549334f485dSMiklos Szeredi return err; 550334f485dSMiklos Szeredi BUG_ON(err != 1); 551334f485dSMiklos Szeredi offset = cs->addr % PAGE_SIZE; 552334f485dSMiklos Szeredi cs->mapaddr = kmap_atomic(cs->pg, KM_USER0); 553334f485dSMiklos Szeredi cs->buf = cs->mapaddr + offset; 554334f485dSMiklos Szeredi cs->len = min(PAGE_SIZE - offset, cs->seglen); 555334f485dSMiklos Szeredi cs->seglen -= cs->len; 556334f485dSMiklos Szeredi cs->addr += cs->len; 557334f485dSMiklos Szeredi 558d7133114SMiklos Szeredi return lock_request(cs->fc, cs->req); 559334f485dSMiklos Szeredi } 560334f485dSMiklos Szeredi 561334f485dSMiklos Szeredi /* Do as much copy to/from userspace buffer as we can */ 5628bfc016dSMiklos Szeredi static int fuse_copy_do(struct fuse_copy_state *cs, void **val, unsigned *size) 563334f485dSMiklos Szeredi { 564334f485dSMiklos Szeredi unsigned ncpy = min(*size, cs->len); 565334f485dSMiklos Szeredi if (val) { 566334f485dSMiklos Szeredi if (cs->write) 567334f485dSMiklos Szeredi memcpy(cs->buf, *val, ncpy); 568334f485dSMiklos Szeredi else 569334f485dSMiklos Szeredi memcpy(*val, cs->buf, ncpy); 570334f485dSMiklos Szeredi *val += ncpy; 571334f485dSMiklos Szeredi } 572334f485dSMiklos Szeredi *size -= ncpy; 573334f485dSMiklos Szeredi cs->len -= ncpy; 574334f485dSMiklos Szeredi cs->buf += ncpy; 575334f485dSMiklos Szeredi return ncpy; 576334f485dSMiklos Szeredi } 577334f485dSMiklos Szeredi 578334f485dSMiklos Szeredi /* 579334f485dSMiklos Szeredi * Copy a page in the request to/from the userspace buffer. Must be 580334f485dSMiklos Szeredi * done atomically 581334f485dSMiklos Szeredi */ 5828bfc016dSMiklos Szeredi static int fuse_copy_page(struct fuse_copy_state *cs, struct page *page, 583334f485dSMiklos Szeredi unsigned offset, unsigned count, int zeroing) 584334f485dSMiklos Szeredi { 585334f485dSMiklos Szeredi if (page && zeroing && count < PAGE_SIZE) { 586334f485dSMiklos Szeredi void *mapaddr = kmap_atomic(page, KM_USER1); 587334f485dSMiklos Szeredi memset(mapaddr, 0, PAGE_SIZE); 588334f485dSMiklos Szeredi kunmap_atomic(mapaddr, KM_USER1); 589334f485dSMiklos Szeredi } 590334f485dSMiklos Szeredi while (count) { 5911729a16cSMiklos Szeredi if (!cs->len) { 5921729a16cSMiklos Szeredi int err = fuse_copy_fill(cs); 5931729a16cSMiklos Szeredi if (err) 594334f485dSMiklos Szeredi return err; 5951729a16cSMiklos Szeredi } 596334f485dSMiklos Szeredi if (page) { 597334f485dSMiklos Szeredi void *mapaddr = kmap_atomic(page, KM_USER1); 598334f485dSMiklos Szeredi void *buf = mapaddr + offset; 599334f485dSMiklos Szeredi offset += fuse_copy_do(cs, &buf, &count); 600334f485dSMiklos Szeredi kunmap_atomic(mapaddr, KM_USER1); 601334f485dSMiklos Szeredi } else 602334f485dSMiklos Szeredi offset += fuse_copy_do(cs, NULL, &count); 603334f485dSMiklos Szeredi } 604334f485dSMiklos Szeredi if (page && !cs->write) 605334f485dSMiklos Szeredi flush_dcache_page(page); 606334f485dSMiklos Szeredi return 0; 607334f485dSMiklos Szeredi } 608334f485dSMiklos Szeredi 609334f485dSMiklos Szeredi /* Copy pages in the request to/from userspace buffer */ 610334f485dSMiklos Szeredi static int fuse_copy_pages(struct fuse_copy_state *cs, unsigned nbytes, 611334f485dSMiklos Szeredi int zeroing) 612334f485dSMiklos Szeredi { 613334f485dSMiklos Szeredi unsigned i; 614334f485dSMiklos Szeredi struct fuse_req *req = cs->req; 615334f485dSMiklos Szeredi unsigned offset = req->page_offset; 616334f485dSMiklos Szeredi unsigned count = min(nbytes, (unsigned) PAGE_SIZE - offset); 617334f485dSMiklos Szeredi 618334f485dSMiklos Szeredi for (i = 0; i < req->num_pages && (nbytes || zeroing); i++) { 619334f485dSMiklos Szeredi struct page *page = req->pages[i]; 620334f485dSMiklos Szeredi int err = fuse_copy_page(cs, page, offset, count, zeroing); 621334f485dSMiklos Szeredi if (err) 622334f485dSMiklos Szeredi return err; 623334f485dSMiklos Szeredi 624334f485dSMiklos Szeredi nbytes -= count; 625334f485dSMiklos Szeredi count = min(nbytes, (unsigned) PAGE_SIZE); 626334f485dSMiklos Szeredi offset = 0; 627334f485dSMiklos Szeredi } 628334f485dSMiklos Szeredi return 0; 629334f485dSMiklos Szeredi } 630334f485dSMiklos Szeredi 631334f485dSMiklos Szeredi /* Copy a single argument in the request to/from userspace buffer */ 632334f485dSMiklos Szeredi static int fuse_copy_one(struct fuse_copy_state *cs, void *val, unsigned size) 633334f485dSMiklos Szeredi { 634334f485dSMiklos Szeredi while (size) { 6351729a16cSMiklos Szeredi if (!cs->len) { 6361729a16cSMiklos Szeredi int err = fuse_copy_fill(cs); 6371729a16cSMiklos Szeredi if (err) 638334f485dSMiklos Szeredi return err; 6391729a16cSMiklos Szeredi } 640334f485dSMiklos Szeredi fuse_copy_do(cs, &val, &size); 641334f485dSMiklos Szeredi } 642334f485dSMiklos Szeredi return 0; 643334f485dSMiklos Szeredi } 644334f485dSMiklos Szeredi 645334f485dSMiklos Szeredi /* Copy request arguments to/from userspace buffer */ 646334f485dSMiklos Szeredi static int fuse_copy_args(struct fuse_copy_state *cs, unsigned numargs, 647334f485dSMiklos Szeredi unsigned argpages, struct fuse_arg *args, 648334f485dSMiklos Szeredi int zeroing) 649334f485dSMiklos Szeredi { 650334f485dSMiklos Szeredi int err = 0; 651334f485dSMiklos Szeredi unsigned i; 652334f485dSMiklos Szeredi 653334f485dSMiklos Szeredi for (i = 0; !err && i < numargs; i++) { 654334f485dSMiklos Szeredi struct fuse_arg *arg = &args[i]; 655334f485dSMiklos Szeredi if (i == numargs - 1 && argpages) 656334f485dSMiklos Szeredi err = fuse_copy_pages(cs, arg->size, zeroing); 657334f485dSMiklos Szeredi else 658334f485dSMiklos Szeredi err = fuse_copy_one(cs, arg->value, arg->size); 659334f485dSMiklos Szeredi } 660334f485dSMiklos Szeredi return err; 661334f485dSMiklos Szeredi } 662334f485dSMiklos Szeredi 663a4d27e75SMiklos Szeredi static int request_pending(struct fuse_conn *fc) 664a4d27e75SMiklos Szeredi { 665a4d27e75SMiklos Szeredi return !list_empty(&fc->pending) || !list_empty(&fc->interrupts); 666a4d27e75SMiklos Szeredi } 667a4d27e75SMiklos Szeredi 668334f485dSMiklos Szeredi /* Wait until a request is available on the pending list */ 669334f485dSMiklos Szeredi static void request_wait(struct fuse_conn *fc) 670334f485dSMiklos Szeredi { 671334f485dSMiklos Szeredi DECLARE_WAITQUEUE(wait, current); 672334f485dSMiklos Szeredi 673334f485dSMiklos Szeredi add_wait_queue_exclusive(&fc->waitq, &wait); 674a4d27e75SMiklos Szeredi while (fc->connected && !request_pending(fc)) { 675334f485dSMiklos Szeredi set_current_state(TASK_INTERRUPTIBLE); 676334f485dSMiklos Szeredi if (signal_pending(current)) 677334f485dSMiklos Szeredi break; 678334f485dSMiklos Szeredi 679d7133114SMiklos Szeredi spin_unlock(&fc->lock); 680334f485dSMiklos Szeredi schedule(); 681d7133114SMiklos Szeredi spin_lock(&fc->lock); 682334f485dSMiklos Szeredi } 683334f485dSMiklos Szeredi set_current_state(TASK_RUNNING); 684334f485dSMiklos Szeredi remove_wait_queue(&fc->waitq, &wait); 685334f485dSMiklos Szeredi } 686334f485dSMiklos Szeredi 687334f485dSMiklos Szeredi /* 688a4d27e75SMiklos Szeredi * Transfer an interrupt request to userspace 689a4d27e75SMiklos Szeredi * 690a4d27e75SMiklos Szeredi * Unlike other requests this is assembled on demand, without a need 691a4d27e75SMiklos Szeredi * to allocate a separate fuse_req structure. 692a4d27e75SMiklos Szeredi * 693a4d27e75SMiklos Szeredi * Called with fc->lock held, releases it 694a4d27e75SMiklos Szeredi */ 695a4d27e75SMiklos Szeredi static int fuse_read_interrupt(struct fuse_conn *fc, struct fuse_req *req, 696a4d27e75SMiklos Szeredi const struct iovec *iov, unsigned long nr_segs) 697105f4d7aSJosh Triplett __releases(fc->lock) 698a4d27e75SMiklos Szeredi { 699a4d27e75SMiklos Szeredi struct fuse_copy_state cs; 700a4d27e75SMiklos Szeredi struct fuse_in_header ih; 701a4d27e75SMiklos Szeredi struct fuse_interrupt_in arg; 702a4d27e75SMiklos Szeredi unsigned reqsize = sizeof(ih) + sizeof(arg); 703a4d27e75SMiklos Szeredi int err; 704a4d27e75SMiklos Szeredi 705a4d27e75SMiklos Szeredi list_del_init(&req->intr_entry); 706a4d27e75SMiklos Szeredi req->intr_unique = fuse_get_unique(fc); 707a4d27e75SMiklos Szeredi memset(&ih, 0, sizeof(ih)); 708a4d27e75SMiklos Szeredi memset(&arg, 0, sizeof(arg)); 709a4d27e75SMiklos Szeredi ih.len = reqsize; 710a4d27e75SMiklos Szeredi ih.opcode = FUSE_INTERRUPT; 711a4d27e75SMiklos Szeredi ih.unique = req->intr_unique; 712a4d27e75SMiklos Szeredi arg.unique = req->in.h.unique; 713a4d27e75SMiklos Szeredi 714a4d27e75SMiklos Szeredi spin_unlock(&fc->lock); 715a4d27e75SMiklos Szeredi if (iov_length(iov, nr_segs) < reqsize) 716a4d27e75SMiklos Szeredi return -EINVAL; 717a4d27e75SMiklos Szeredi 718a4d27e75SMiklos Szeredi fuse_copy_init(&cs, fc, 1, NULL, iov, nr_segs); 719a4d27e75SMiklos Szeredi err = fuse_copy_one(&cs, &ih, sizeof(ih)); 720a4d27e75SMiklos Szeredi if (!err) 721a4d27e75SMiklos Szeredi err = fuse_copy_one(&cs, &arg, sizeof(arg)); 722a4d27e75SMiklos Szeredi fuse_copy_finish(&cs); 723a4d27e75SMiklos Szeredi 724a4d27e75SMiklos Szeredi return err ? err : reqsize; 725a4d27e75SMiklos Szeredi } 726a4d27e75SMiklos Szeredi 727a4d27e75SMiklos Szeredi /* 728334f485dSMiklos Szeredi * Read a single request into the userspace filesystem's buffer. This 729334f485dSMiklos Szeredi * function waits until a request is available, then removes it from 730334f485dSMiklos Szeredi * the pending list and copies request data to userspace buffer. If 731f9a2842eSMiklos Szeredi * no reply is needed (FORGET) or request has been aborted or there 732f9a2842eSMiklos Szeredi * was an error during the copying then it's finished by calling 733334f485dSMiklos Szeredi * request_end(). Otherwise add it to the processing list, and set 734334f485dSMiklos Szeredi * the 'sent' flag. 735334f485dSMiklos Szeredi */ 736ee0b3e67SBadari Pulavarty static ssize_t fuse_dev_read(struct kiocb *iocb, const struct iovec *iov, 737ee0b3e67SBadari Pulavarty unsigned long nr_segs, loff_t pos) 738334f485dSMiklos Szeredi { 739334f485dSMiklos Szeredi int err; 740334f485dSMiklos Szeredi struct fuse_req *req; 741334f485dSMiklos Szeredi struct fuse_in *in; 742334f485dSMiklos Szeredi struct fuse_copy_state cs; 743334f485dSMiklos Szeredi unsigned reqsize; 744ee0b3e67SBadari Pulavarty struct file *file = iocb->ki_filp; 7450720b315SMiklos Szeredi struct fuse_conn *fc = fuse_get_conn(file); 7460720b315SMiklos Szeredi if (!fc) 7470720b315SMiklos Szeredi return -EPERM; 748334f485dSMiklos Szeredi 7491d3d752bSMiklos Szeredi restart: 750d7133114SMiklos Szeredi spin_lock(&fc->lock); 751e5ac1d1eSJeff Dike err = -EAGAIN; 752e5ac1d1eSJeff Dike if ((file->f_flags & O_NONBLOCK) && fc->connected && 753a4d27e75SMiklos Szeredi !request_pending(fc)) 754e5ac1d1eSJeff Dike goto err_unlock; 755e5ac1d1eSJeff Dike 756334f485dSMiklos Szeredi request_wait(fc); 757334f485dSMiklos Szeredi err = -ENODEV; 7589ba7cbbaSMiklos Szeredi if (!fc->connected) 759334f485dSMiklos Szeredi goto err_unlock; 760334f485dSMiklos Szeredi err = -ERESTARTSYS; 761a4d27e75SMiklos Szeredi if (!request_pending(fc)) 762334f485dSMiklos Szeredi goto err_unlock; 763334f485dSMiklos Szeredi 764a4d27e75SMiklos Szeredi if (!list_empty(&fc->interrupts)) { 765a4d27e75SMiklos Szeredi req = list_entry(fc->interrupts.next, struct fuse_req, 766a4d27e75SMiklos Szeredi intr_entry); 767a4d27e75SMiklos Szeredi return fuse_read_interrupt(fc, req, iov, nr_segs); 768a4d27e75SMiklos Szeredi } 769a4d27e75SMiklos Szeredi 770334f485dSMiklos Szeredi req = list_entry(fc->pending.next, struct fuse_req, list); 77183cfd493SMiklos Szeredi req->state = FUSE_REQ_READING; 772d77a1d5bSMiklos Szeredi list_move(&req->list, &fc->io); 773334f485dSMiklos Szeredi 774334f485dSMiklos Szeredi in = &req->in; 7751d3d752bSMiklos Szeredi reqsize = in->h.len; 7761d3d752bSMiklos Szeredi /* If request is too large, reply with an error and restart the read */ 7771d3d752bSMiklos Szeredi if (iov_length(iov, nr_segs) < reqsize) { 7781d3d752bSMiklos Szeredi req->out.h.error = -EIO; 7791d3d752bSMiklos Szeredi /* SETXATTR is special, since it may contain too large data */ 7801d3d752bSMiklos Szeredi if (in->h.opcode == FUSE_SETXATTR) 7811d3d752bSMiklos Szeredi req->out.h.error = -E2BIG; 7821d3d752bSMiklos Szeredi request_end(fc, req); 7831d3d752bSMiklos Szeredi goto restart; 7841d3d752bSMiklos Szeredi } 785d7133114SMiklos Szeredi spin_unlock(&fc->lock); 786d7133114SMiklos Szeredi fuse_copy_init(&cs, fc, 1, req, iov, nr_segs); 787334f485dSMiklos Szeredi err = fuse_copy_one(&cs, &in->h, sizeof(in->h)); 788334f485dSMiklos Szeredi if (!err) 789334f485dSMiklos Szeredi err = fuse_copy_args(&cs, in->numargs, in->argpages, 790334f485dSMiklos Szeredi (struct fuse_arg *) in->args, 0); 791334f485dSMiklos Szeredi fuse_copy_finish(&cs); 792d7133114SMiklos Szeredi spin_lock(&fc->lock); 793334f485dSMiklos Szeredi req->locked = 0; 794c9c9d7dfSMiklos Szeredi if (req->aborted) { 795c9c9d7dfSMiklos Szeredi request_end(fc, req); 796c9c9d7dfSMiklos Szeredi return -ENODEV; 797c9c9d7dfSMiklos Szeredi } 798334f485dSMiklos Szeredi if (err) { 799334f485dSMiklos Szeredi req->out.h.error = -EIO; 800334f485dSMiklos Szeredi request_end(fc, req); 801334f485dSMiklos Szeredi return err; 802334f485dSMiklos Szeredi } 803334f485dSMiklos Szeredi if (!req->isreply) 804334f485dSMiklos Szeredi request_end(fc, req); 805334f485dSMiklos Szeredi else { 80683cfd493SMiklos Szeredi req->state = FUSE_REQ_SENT; 807d77a1d5bSMiklos Szeredi list_move_tail(&req->list, &fc->processing); 808a4d27e75SMiklos Szeredi if (req->interrupted) 809a4d27e75SMiklos Szeredi queue_interrupt(fc, req); 810d7133114SMiklos Szeredi spin_unlock(&fc->lock); 811334f485dSMiklos Szeredi } 812334f485dSMiklos Szeredi return reqsize; 813334f485dSMiklos Szeredi 814334f485dSMiklos Szeredi err_unlock: 815d7133114SMiklos Szeredi spin_unlock(&fc->lock); 816334f485dSMiklos Szeredi return err; 817334f485dSMiklos Szeredi } 818334f485dSMiklos Szeredi 819334f485dSMiklos Szeredi /* Look up request on processing list by unique ID */ 820334f485dSMiklos Szeredi static struct fuse_req *request_find(struct fuse_conn *fc, u64 unique) 821334f485dSMiklos Szeredi { 822334f485dSMiklos Szeredi struct list_head *entry; 823334f485dSMiklos Szeredi 824334f485dSMiklos Szeredi list_for_each(entry, &fc->processing) { 825334f485dSMiklos Szeredi struct fuse_req *req; 826334f485dSMiklos Szeredi req = list_entry(entry, struct fuse_req, list); 827a4d27e75SMiklos Szeredi if (req->in.h.unique == unique || req->intr_unique == unique) 828334f485dSMiklos Szeredi return req; 829334f485dSMiklos Szeredi } 830334f485dSMiklos Szeredi return NULL; 831334f485dSMiklos Szeredi } 832334f485dSMiklos Szeredi 833334f485dSMiklos Szeredi static int copy_out_args(struct fuse_copy_state *cs, struct fuse_out *out, 834334f485dSMiklos Szeredi unsigned nbytes) 835334f485dSMiklos Szeredi { 836334f485dSMiklos Szeredi unsigned reqsize = sizeof(struct fuse_out_header); 837334f485dSMiklos Szeredi 838334f485dSMiklos Szeredi if (out->h.error) 839334f485dSMiklos Szeredi return nbytes != reqsize ? -EINVAL : 0; 840334f485dSMiklos Szeredi 841334f485dSMiklos Szeredi reqsize += len_args(out->numargs, out->args); 842334f485dSMiklos Szeredi 843334f485dSMiklos Szeredi if (reqsize < nbytes || (reqsize > nbytes && !out->argvar)) 844334f485dSMiklos Szeredi return -EINVAL; 845334f485dSMiklos Szeredi else if (reqsize > nbytes) { 846334f485dSMiklos Szeredi struct fuse_arg *lastarg = &out->args[out->numargs-1]; 847334f485dSMiklos Szeredi unsigned diffsize = reqsize - nbytes; 848334f485dSMiklos Szeredi if (diffsize > lastarg->size) 849334f485dSMiklos Szeredi return -EINVAL; 850334f485dSMiklos Szeredi lastarg->size -= diffsize; 851334f485dSMiklos Szeredi } 852334f485dSMiklos Szeredi return fuse_copy_args(cs, out->numargs, out->argpages, out->args, 853334f485dSMiklos Szeredi out->page_zeroing); 854334f485dSMiklos Szeredi } 855334f485dSMiklos Szeredi 856334f485dSMiklos Szeredi /* 857334f485dSMiklos Szeredi * Write a single reply to a request. First the header is copied from 858334f485dSMiklos Szeredi * the write buffer. The request is then searched on the processing 859334f485dSMiklos Szeredi * list by the unique ID found in the header. If found, then remove 860334f485dSMiklos Szeredi * it from the list and copy the rest of the buffer to the request. 861334f485dSMiklos Szeredi * The request is finished by calling request_end() 862334f485dSMiklos Szeredi */ 863ee0b3e67SBadari Pulavarty static ssize_t fuse_dev_write(struct kiocb *iocb, const struct iovec *iov, 864ee0b3e67SBadari Pulavarty unsigned long nr_segs, loff_t pos) 865334f485dSMiklos Szeredi { 866334f485dSMiklos Szeredi int err; 867334f485dSMiklos Szeredi unsigned nbytes = iov_length(iov, nr_segs); 868334f485dSMiklos Szeredi struct fuse_req *req; 869334f485dSMiklos Szeredi struct fuse_out_header oh; 870334f485dSMiklos Szeredi struct fuse_copy_state cs; 871ee0b3e67SBadari Pulavarty struct fuse_conn *fc = fuse_get_conn(iocb->ki_filp); 872334f485dSMiklos Szeredi if (!fc) 873a87046d8SMiklos Szeredi return -EPERM; 874334f485dSMiklos Szeredi 875d7133114SMiklos Szeredi fuse_copy_init(&cs, fc, 0, NULL, iov, nr_segs); 876334f485dSMiklos Szeredi if (nbytes < sizeof(struct fuse_out_header)) 877334f485dSMiklos Szeredi return -EINVAL; 878334f485dSMiklos Szeredi 879334f485dSMiklos Szeredi err = fuse_copy_one(&cs, &oh, sizeof(oh)); 880334f485dSMiklos Szeredi if (err) 881334f485dSMiklos Szeredi goto err_finish; 882334f485dSMiklos Szeredi err = -EINVAL; 883334f485dSMiklos Szeredi if (!oh.unique || oh.error <= -1000 || oh.error > 0 || 884334f485dSMiklos Szeredi oh.len != nbytes) 885334f485dSMiklos Szeredi goto err_finish; 886334f485dSMiklos Szeredi 887d7133114SMiklos Szeredi spin_lock(&fc->lock); 88869a53bf2SMiklos Szeredi err = -ENOENT; 88969a53bf2SMiklos Szeredi if (!fc->connected) 89069a53bf2SMiklos Szeredi goto err_unlock; 89169a53bf2SMiklos Szeredi 892334f485dSMiklos Szeredi req = request_find(fc, oh.unique); 893334f485dSMiklos Szeredi if (!req) 894334f485dSMiklos Szeredi goto err_unlock; 895334f485dSMiklos Szeredi 896f9a2842eSMiklos Szeredi if (req->aborted) { 897d7133114SMiklos Szeredi spin_unlock(&fc->lock); 898334f485dSMiklos Szeredi fuse_copy_finish(&cs); 899d7133114SMiklos Szeredi spin_lock(&fc->lock); 900222f1d69SMiklos Szeredi request_end(fc, req); 901334f485dSMiklos Szeredi return -ENOENT; 902334f485dSMiklos Szeredi } 903a4d27e75SMiklos Szeredi /* Is it an interrupt reply? */ 904a4d27e75SMiklos Szeredi if (req->intr_unique == oh.unique) { 905a4d27e75SMiklos Szeredi err = -EINVAL; 906a4d27e75SMiklos Szeredi if (nbytes != sizeof(struct fuse_out_header)) 907a4d27e75SMiklos Szeredi goto err_unlock; 908a4d27e75SMiklos Szeredi 909a4d27e75SMiklos Szeredi if (oh.error == -ENOSYS) 910a4d27e75SMiklos Szeredi fc->no_interrupt = 1; 911a4d27e75SMiklos Szeredi else if (oh.error == -EAGAIN) 912a4d27e75SMiklos Szeredi queue_interrupt(fc, req); 913a4d27e75SMiklos Szeredi 914a4d27e75SMiklos Szeredi spin_unlock(&fc->lock); 915a4d27e75SMiklos Szeredi fuse_copy_finish(&cs); 916a4d27e75SMiklos Szeredi return nbytes; 917a4d27e75SMiklos Szeredi } 918a4d27e75SMiklos Szeredi 919a4d27e75SMiklos Szeredi req->state = FUSE_REQ_WRITING; 920d77a1d5bSMiklos Szeredi list_move(&req->list, &fc->io); 921334f485dSMiklos Szeredi req->out.h = oh; 922334f485dSMiklos Szeredi req->locked = 1; 923334f485dSMiklos Szeredi cs.req = req; 924d7133114SMiklos Szeredi spin_unlock(&fc->lock); 925334f485dSMiklos Szeredi 926334f485dSMiklos Szeredi err = copy_out_args(&cs, &req->out, nbytes); 927334f485dSMiklos Szeredi fuse_copy_finish(&cs); 928334f485dSMiklos Szeredi 929d7133114SMiklos Szeredi spin_lock(&fc->lock); 930334f485dSMiklos Szeredi req->locked = 0; 931334f485dSMiklos Szeredi if (!err) { 932f9a2842eSMiklos Szeredi if (req->aborted) 933334f485dSMiklos Szeredi err = -ENOENT; 934f9a2842eSMiklos Szeredi } else if (!req->aborted) 935334f485dSMiklos Szeredi req->out.h.error = -EIO; 936334f485dSMiklos Szeredi request_end(fc, req); 937334f485dSMiklos Szeredi 938334f485dSMiklos Szeredi return err ? err : nbytes; 939334f485dSMiklos Szeredi 940334f485dSMiklos Szeredi err_unlock: 941d7133114SMiklos Szeredi spin_unlock(&fc->lock); 942334f485dSMiklos Szeredi err_finish: 943334f485dSMiklos Szeredi fuse_copy_finish(&cs); 944334f485dSMiklos Szeredi return err; 945334f485dSMiklos Szeredi } 946334f485dSMiklos Szeredi 947334f485dSMiklos Szeredi static unsigned fuse_dev_poll(struct file *file, poll_table *wait) 948334f485dSMiklos Szeredi { 949334f485dSMiklos Szeredi unsigned mask = POLLOUT | POLLWRNORM; 9507025d9adSMiklos Szeredi struct fuse_conn *fc = fuse_get_conn(file); 951334f485dSMiklos Szeredi if (!fc) 9527025d9adSMiklos Szeredi return POLLERR; 953334f485dSMiklos Szeredi 954334f485dSMiklos Szeredi poll_wait(file, &fc->waitq, wait); 955334f485dSMiklos Szeredi 956d7133114SMiklos Szeredi spin_lock(&fc->lock); 9577025d9adSMiklos Szeredi if (!fc->connected) 9587025d9adSMiklos Szeredi mask = POLLERR; 959a4d27e75SMiklos Szeredi else if (request_pending(fc)) 960334f485dSMiklos Szeredi mask |= POLLIN | POLLRDNORM; 961d7133114SMiklos Szeredi spin_unlock(&fc->lock); 962334f485dSMiklos Szeredi 963334f485dSMiklos Szeredi return mask; 964334f485dSMiklos Szeredi } 965334f485dSMiklos Szeredi 96669a53bf2SMiklos Szeredi /* 96769a53bf2SMiklos Szeredi * Abort all requests on the given list (pending or processing) 96869a53bf2SMiklos Szeredi * 969d7133114SMiklos Szeredi * This function releases and reacquires fc->lock 97069a53bf2SMiklos Szeredi */ 971334f485dSMiklos Szeredi static void end_requests(struct fuse_conn *fc, struct list_head *head) 972334f485dSMiklos Szeredi { 973334f485dSMiklos Szeredi while (!list_empty(head)) { 974334f485dSMiklos Szeredi struct fuse_req *req; 975334f485dSMiklos Szeredi req = list_entry(head->next, struct fuse_req, list); 976334f485dSMiklos Szeredi req->out.h.error = -ECONNABORTED; 977334f485dSMiklos Szeredi request_end(fc, req); 978d7133114SMiklos Szeredi spin_lock(&fc->lock); 979334f485dSMiklos Szeredi } 980334f485dSMiklos Szeredi } 981334f485dSMiklos Szeredi 98269a53bf2SMiklos Szeredi /* 98369a53bf2SMiklos Szeredi * Abort requests under I/O 98469a53bf2SMiklos Szeredi * 985f9a2842eSMiklos Szeredi * The requests are set to aborted and finished, and the request 98669a53bf2SMiklos Szeredi * waiter is woken up. This will make request_wait_answer() wait 98769a53bf2SMiklos Szeredi * until the request is unlocked and then return. 98864c6d8edSMiklos Szeredi * 98964c6d8edSMiklos Szeredi * If the request is asynchronous, then the end function needs to be 99064c6d8edSMiklos Szeredi * called after waiting for the request to be unlocked (if it was 99164c6d8edSMiklos Szeredi * locked). 99269a53bf2SMiklos Szeredi */ 99369a53bf2SMiklos Szeredi static void end_io_requests(struct fuse_conn *fc) 9944dbf930eSMiklos Szeredi __releases(fc->lock) __acquires(fc->lock) 99569a53bf2SMiklos Szeredi { 99669a53bf2SMiklos Szeredi while (!list_empty(&fc->io)) { 99764c6d8edSMiklos Szeredi struct fuse_req *req = 99864c6d8edSMiklos Szeredi list_entry(fc->io.next, struct fuse_req, list); 99964c6d8edSMiklos Szeredi void (*end) (struct fuse_conn *, struct fuse_req *) = req->end; 100064c6d8edSMiklos Szeredi 1001f9a2842eSMiklos Szeredi req->aborted = 1; 100269a53bf2SMiklos Szeredi req->out.h.error = -ECONNABORTED; 100369a53bf2SMiklos Szeredi req->state = FUSE_REQ_FINISHED; 100469a53bf2SMiklos Szeredi list_del_init(&req->list); 100569a53bf2SMiklos Szeredi wake_up(&req->waitq); 100664c6d8edSMiklos Szeredi if (end) { 100764c6d8edSMiklos Szeredi req->end = NULL; 100864c6d8edSMiklos Szeredi __fuse_get_request(req); 1009d7133114SMiklos Szeredi spin_unlock(&fc->lock); 101064c6d8edSMiklos Szeredi wait_event(req->waitq, !req->locked); 101164c6d8edSMiklos Szeredi end(fc, req); 1012*e9bb09ddSTejun Heo fuse_put_request(fc, req); 1013d7133114SMiklos Szeredi spin_lock(&fc->lock); 101464c6d8edSMiklos Szeredi } 101569a53bf2SMiklos Szeredi } 101669a53bf2SMiklos Szeredi } 101769a53bf2SMiklos Szeredi 101869a53bf2SMiklos Szeredi /* 101969a53bf2SMiklos Szeredi * Abort all requests. 102069a53bf2SMiklos Szeredi * 102169a53bf2SMiklos Szeredi * Emergency exit in case of a malicious or accidental deadlock, or 102269a53bf2SMiklos Szeredi * just a hung filesystem. 102369a53bf2SMiklos Szeredi * 102469a53bf2SMiklos Szeredi * The same effect is usually achievable through killing the 102569a53bf2SMiklos Szeredi * filesystem daemon and all users of the filesystem. The exception 102669a53bf2SMiklos Szeredi * is the combination of an asynchronous request and the tricky 102769a53bf2SMiklos Szeredi * deadlock (see Documentation/filesystems/fuse.txt). 102869a53bf2SMiklos Szeredi * 102969a53bf2SMiklos Szeredi * During the aborting, progression of requests from the pending and 103069a53bf2SMiklos Szeredi * processing lists onto the io list, and progression of new requests 103169a53bf2SMiklos Szeredi * onto the pending list is prevented by req->connected being false. 103269a53bf2SMiklos Szeredi * 103369a53bf2SMiklos Szeredi * Progression of requests under I/O to the processing list is 1034f9a2842eSMiklos Szeredi * prevented by the req->aborted flag being true for these requests. 1035f9a2842eSMiklos Szeredi * For this reason requests on the io list must be aborted first. 103669a53bf2SMiklos Szeredi */ 103769a53bf2SMiklos Szeredi void fuse_abort_conn(struct fuse_conn *fc) 103869a53bf2SMiklos Szeredi { 1039d7133114SMiklos Szeredi spin_lock(&fc->lock); 104069a53bf2SMiklos Szeredi if (fc->connected) { 104169a53bf2SMiklos Szeredi fc->connected = 0; 104251eb01e7SMiklos Szeredi fc->blocked = 0; 104369a53bf2SMiklos Szeredi end_io_requests(fc); 104469a53bf2SMiklos Szeredi end_requests(fc, &fc->pending); 104569a53bf2SMiklos Szeredi end_requests(fc, &fc->processing); 104669a53bf2SMiklos Szeredi wake_up_all(&fc->waitq); 104751eb01e7SMiklos Szeredi wake_up_all(&fc->blocked_waitq); 1048385a17bfSJeff Dike kill_fasync(&fc->fasync, SIGIO, POLL_IN); 104969a53bf2SMiklos Szeredi } 1050d7133114SMiklos Szeredi spin_unlock(&fc->lock); 105169a53bf2SMiklos Szeredi } 105269a53bf2SMiklos Szeredi 1053334f485dSMiklos Szeredi static int fuse_dev_release(struct inode *inode, struct file *file) 1054334f485dSMiklos Szeredi { 10550720b315SMiklos Szeredi struct fuse_conn *fc = fuse_get_conn(file); 1056334f485dSMiklos Szeredi if (fc) { 1057d7133114SMiklos Szeredi spin_lock(&fc->lock); 10581e9a4ed9SMiklos Szeredi fc->connected = 0; 1059334f485dSMiklos Szeredi end_requests(fc, &fc->pending); 1060334f485dSMiklos Szeredi end_requests(fc, &fc->processing); 1061d7133114SMiklos Szeredi spin_unlock(&fc->lock); 1062bafa9654SMiklos Szeredi fuse_conn_put(fc); 1063385a17bfSJeff Dike } 1064f543f253SMiklos Szeredi 1065334f485dSMiklos Szeredi return 0; 1066334f485dSMiklos Szeredi } 1067334f485dSMiklos Szeredi 1068385a17bfSJeff Dike static int fuse_dev_fasync(int fd, struct file *file, int on) 1069385a17bfSJeff Dike { 1070385a17bfSJeff Dike struct fuse_conn *fc = fuse_get_conn(file); 1071385a17bfSJeff Dike if (!fc) 1072a87046d8SMiklos Szeredi return -EPERM; 1073385a17bfSJeff Dike 1074385a17bfSJeff Dike /* No locking - fasync_helper does its own locking */ 1075385a17bfSJeff Dike return fasync_helper(fd, file, on, &fc->fasync); 1076385a17bfSJeff Dike } 1077385a17bfSJeff Dike 10784b6f5d20SArjan van de Ven const struct file_operations fuse_dev_operations = { 1079334f485dSMiklos Szeredi .owner = THIS_MODULE, 1080334f485dSMiklos Szeredi .llseek = no_llseek, 1081ee0b3e67SBadari Pulavarty .read = do_sync_read, 1082ee0b3e67SBadari Pulavarty .aio_read = fuse_dev_read, 1083ee0b3e67SBadari Pulavarty .write = do_sync_write, 1084ee0b3e67SBadari Pulavarty .aio_write = fuse_dev_write, 1085334f485dSMiklos Szeredi .poll = fuse_dev_poll, 1086334f485dSMiklos Szeredi .release = fuse_dev_release, 1087385a17bfSJeff Dike .fasync = fuse_dev_fasync, 1088334f485dSMiklos Szeredi }; 1089334f485dSMiklos Szeredi 1090334f485dSMiklos Szeredi static struct miscdevice fuse_miscdevice = { 1091334f485dSMiklos Szeredi .minor = FUSE_MINOR, 1092334f485dSMiklos Szeredi .name = "fuse", 1093334f485dSMiklos Szeredi .fops = &fuse_dev_operations, 1094334f485dSMiklos Szeredi }; 1095334f485dSMiklos Szeredi 1096334f485dSMiklos Szeredi int __init fuse_dev_init(void) 1097334f485dSMiklos Szeredi { 1098334f485dSMiklos Szeredi int err = -ENOMEM; 1099334f485dSMiklos Szeredi fuse_req_cachep = kmem_cache_create("fuse_request", 1100334f485dSMiklos Szeredi sizeof(struct fuse_req), 110120c2df83SPaul Mundt 0, 0, NULL); 1102334f485dSMiklos Szeredi if (!fuse_req_cachep) 1103334f485dSMiklos Szeredi goto out; 1104334f485dSMiklos Szeredi 1105334f485dSMiklos Szeredi err = misc_register(&fuse_miscdevice); 1106334f485dSMiklos Szeredi if (err) 1107334f485dSMiklos Szeredi goto out_cache_clean; 1108334f485dSMiklos Szeredi 1109334f485dSMiklos Szeredi return 0; 1110334f485dSMiklos Szeredi 1111334f485dSMiklos Szeredi out_cache_clean: 1112334f485dSMiklos Szeredi kmem_cache_destroy(fuse_req_cachep); 1113334f485dSMiklos Szeredi out: 1114334f485dSMiklos Szeredi return err; 1115334f485dSMiklos Szeredi } 1116334f485dSMiklos Szeredi 1117334f485dSMiklos Szeredi void fuse_dev_cleanup(void) 1118334f485dSMiklos Szeredi { 1119334f485dSMiklos Szeredi misc_deregister(&fuse_miscdevice); 1120334f485dSMiklos Szeredi kmem_cache_destroy(fuse_req_cachep); 1121334f485dSMiklos Szeredi } 1122