1334f485dSMiklos Szeredi /* 2334f485dSMiklos Szeredi FUSE: Filesystem in Userspace 3334f485dSMiklos Szeredi Copyright (C) 2001-2005 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 24334f485dSMiklos Szeredi static inline struct fuse_conn *fuse_get_conn(struct file *file) 25334f485dSMiklos Szeredi { 26334f485dSMiklos Szeredi struct fuse_conn *fc; 27334f485dSMiklos Szeredi spin_lock(&fuse_lock); 28334f485dSMiklos Szeredi fc = file->private_data; 29334f485dSMiklos Szeredi if (fc && !fc->sb) 30334f485dSMiklos Szeredi fc = NULL; 31334f485dSMiklos Szeredi spin_unlock(&fuse_lock); 32334f485dSMiklos Szeredi return fc; 33334f485dSMiklos Szeredi } 34334f485dSMiklos Szeredi 35334f485dSMiklos Szeredi static inline void fuse_request_init(struct fuse_req *req) 36334f485dSMiklos Szeredi { 37334f485dSMiklos Szeredi memset(req, 0, sizeof(*req)); 38334f485dSMiklos Szeredi INIT_LIST_HEAD(&req->list); 39334f485dSMiklos Szeredi init_waitqueue_head(&req->waitq); 40334f485dSMiklos Szeredi atomic_set(&req->count, 1); 41334f485dSMiklos Szeredi } 42334f485dSMiklos Szeredi 43334f485dSMiklos Szeredi struct fuse_req *fuse_request_alloc(void) 44334f485dSMiklos Szeredi { 45334f485dSMiklos Szeredi struct fuse_req *req = kmem_cache_alloc(fuse_req_cachep, SLAB_KERNEL); 46334f485dSMiklos Szeredi if (req) 47334f485dSMiklos Szeredi fuse_request_init(req); 48334f485dSMiklos Szeredi return req; 49334f485dSMiklos Szeredi } 50334f485dSMiklos Szeredi 51334f485dSMiklos Szeredi void fuse_request_free(struct fuse_req *req) 52334f485dSMiklos Szeredi { 53334f485dSMiklos Szeredi kmem_cache_free(fuse_req_cachep, req); 54334f485dSMiklos Szeredi } 55334f485dSMiklos Szeredi 56334f485dSMiklos Szeredi static inline void block_sigs(sigset_t *oldset) 57334f485dSMiklos Szeredi { 58334f485dSMiklos Szeredi sigset_t mask; 59334f485dSMiklos Szeredi 60334f485dSMiklos Szeredi siginitsetinv(&mask, sigmask(SIGKILL)); 61334f485dSMiklos Szeredi sigprocmask(SIG_BLOCK, &mask, oldset); 62334f485dSMiklos Szeredi } 63334f485dSMiklos Szeredi 64334f485dSMiklos Szeredi static inline void restore_sigs(sigset_t *oldset) 65334f485dSMiklos Szeredi { 66334f485dSMiklos Szeredi sigprocmask(SIG_SETMASK, oldset, NULL); 67334f485dSMiklos Szeredi } 68334f485dSMiklos Szeredi 69334f485dSMiklos Szeredi void fuse_reset_request(struct fuse_req *req) 70334f485dSMiklos Szeredi { 71334f485dSMiklos Szeredi int preallocated = req->preallocated; 72334f485dSMiklos Szeredi BUG_ON(atomic_read(&req->count) != 1); 73334f485dSMiklos Szeredi fuse_request_init(req); 74334f485dSMiklos Szeredi req->preallocated = preallocated; 75334f485dSMiklos Szeredi } 76334f485dSMiklos Szeredi 77334f485dSMiklos Szeredi static void __fuse_get_request(struct fuse_req *req) 78334f485dSMiklos Szeredi { 79334f485dSMiklos Szeredi atomic_inc(&req->count); 80334f485dSMiklos Szeredi } 81334f485dSMiklos Szeredi 82334f485dSMiklos Szeredi /* Must be called with > 1 refcount */ 83334f485dSMiklos Szeredi static void __fuse_put_request(struct fuse_req *req) 84334f485dSMiklos Szeredi { 85334f485dSMiklos Szeredi BUG_ON(atomic_read(&req->count) < 2); 86334f485dSMiklos Szeredi atomic_dec(&req->count); 87334f485dSMiklos Szeredi } 88334f485dSMiklos Szeredi 89334f485dSMiklos Szeredi static struct fuse_req *do_get_request(struct fuse_conn *fc) 90334f485dSMiklos Szeredi { 91334f485dSMiklos Szeredi struct fuse_req *req; 92334f485dSMiklos Szeredi 93334f485dSMiklos Szeredi spin_lock(&fuse_lock); 94334f485dSMiklos Szeredi BUG_ON(list_empty(&fc->unused_list)); 95334f485dSMiklos Szeredi req = list_entry(fc->unused_list.next, struct fuse_req, list); 96334f485dSMiklos Szeredi list_del_init(&req->list); 97334f485dSMiklos Szeredi spin_unlock(&fuse_lock); 98334f485dSMiklos Szeredi fuse_request_init(req); 99334f485dSMiklos Szeredi req->preallocated = 1; 100334f485dSMiklos Szeredi req->in.h.uid = current->fsuid; 101334f485dSMiklos Szeredi req->in.h.gid = current->fsgid; 102334f485dSMiklos Szeredi req->in.h.pid = current->pid; 103334f485dSMiklos Szeredi return req; 104334f485dSMiklos Szeredi } 105334f485dSMiklos Szeredi 106334f485dSMiklos Szeredi struct fuse_req *fuse_get_request(struct fuse_conn *fc) 107334f485dSMiklos Szeredi { 108334f485dSMiklos Szeredi if (down_interruptible(&fc->outstanding_sem)) 109334f485dSMiklos Szeredi return NULL; 110334f485dSMiklos Szeredi return do_get_request(fc); 111334f485dSMiklos Szeredi } 112334f485dSMiklos Szeredi 113334f485dSMiklos Szeredi /* 114334f485dSMiklos Szeredi * Non-interruptible version of the above function is for operations 115334f485dSMiklos Szeredi * which can't legally return -ERESTART{SYS,NOINTR}. This can still 116334f485dSMiklos Szeredi * return NULL, but only in case the signal is SIGKILL. 117334f485dSMiklos Szeredi */ 118334f485dSMiklos Szeredi struct fuse_req *fuse_get_request_nonint(struct fuse_conn *fc) 119334f485dSMiklos Szeredi { 120334f485dSMiklos Szeredi int intr; 121334f485dSMiklos Szeredi sigset_t oldset; 122334f485dSMiklos Szeredi 123334f485dSMiklos Szeredi block_sigs(&oldset); 124334f485dSMiklos Szeredi intr = down_interruptible(&fc->outstanding_sem); 125334f485dSMiklos Szeredi restore_sigs(&oldset); 126334f485dSMiklos Szeredi return intr ? NULL : do_get_request(fc); 127334f485dSMiklos Szeredi } 128334f485dSMiklos Szeredi 129334f485dSMiklos Szeredi static void fuse_putback_request(struct fuse_conn *fc, struct fuse_req *req) 130334f485dSMiklos Szeredi { 131334f485dSMiklos Szeredi spin_lock(&fuse_lock); 132334f485dSMiklos Szeredi if (req->preallocated) 133334f485dSMiklos Szeredi list_add(&req->list, &fc->unused_list); 134334f485dSMiklos Szeredi else 135334f485dSMiklos Szeredi fuse_request_free(req); 136334f485dSMiklos Szeredi 137334f485dSMiklos Szeredi /* If we are in debt decrease that first */ 138334f485dSMiklos Szeredi if (fc->outstanding_debt) 139334f485dSMiklos Szeredi fc->outstanding_debt--; 140334f485dSMiklos Szeredi else 141334f485dSMiklos Szeredi up(&fc->outstanding_sem); 142334f485dSMiklos Szeredi spin_unlock(&fuse_lock); 143334f485dSMiklos Szeredi } 144334f485dSMiklos Szeredi 145334f485dSMiklos Szeredi void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req) 146334f485dSMiklos Szeredi { 147334f485dSMiklos Szeredi if (atomic_dec_and_test(&req->count)) 148334f485dSMiklos Szeredi fuse_putback_request(fc, req); 149334f485dSMiklos Szeredi } 150334f485dSMiklos Szeredi 151334f485dSMiklos Szeredi /* 152334f485dSMiklos Szeredi * This function is called when a request is finished. Either a reply 153334f485dSMiklos Szeredi * has arrived or it was interrupted (and not yet sent) or some error 154334f485dSMiklos Szeredi * occured during communication with userspace, or the device file was 155334f485dSMiklos Szeredi * closed. It decreases the referece count for the request. In case 156334f485dSMiklos Szeredi * of a background request the referece to the stored objects are 157334f485dSMiklos Szeredi * released. The requester thread is woken up (if still waiting), and 158334f485dSMiklos Szeredi * finally the request is either freed or put on the unused_list 159334f485dSMiklos Szeredi * 160334f485dSMiklos Szeredi * Called with fuse_lock, unlocks it 161334f485dSMiklos Szeredi */ 162334f485dSMiklos Szeredi static void request_end(struct fuse_conn *fc, struct fuse_req *req) 163334f485dSMiklos Szeredi { 164334f485dSMiklos Szeredi int putback; 165334f485dSMiklos Szeredi req->finished = 1; 166334f485dSMiklos Szeredi putback = atomic_dec_and_test(&req->count); 167334f485dSMiklos Szeredi spin_unlock(&fuse_lock); 168334f485dSMiklos Szeredi if (req->background) { 169334f485dSMiklos Szeredi if (req->inode) 170334f485dSMiklos Szeredi iput(req->inode); 171334f485dSMiklos Szeredi if (req->inode2) 172334f485dSMiklos Szeredi iput(req->inode2); 173334f485dSMiklos Szeredi if (req->file) 174334f485dSMiklos Szeredi fput(req->file); 175334f485dSMiklos Szeredi } 176334f485dSMiklos Szeredi wake_up(&req->waitq); 177334f485dSMiklos Szeredi if (req->in.h.opcode == FUSE_INIT) { 178334f485dSMiklos Szeredi int i; 179334f485dSMiklos Szeredi 180334f485dSMiklos Szeredi if (req->misc.init_in_out.major != FUSE_KERNEL_VERSION) 181334f485dSMiklos Szeredi fc->conn_error = 1; 182334f485dSMiklos Szeredi 183334f485dSMiklos Szeredi /* After INIT reply is received other requests can go 184334f485dSMiklos Szeredi out. So do (FUSE_MAX_OUTSTANDING - 1) number of 185334f485dSMiklos Szeredi up()s on outstanding_sem. The last up() is done in 186334f485dSMiklos Szeredi fuse_putback_request() */ 187334f485dSMiklos Szeredi for (i = 1; i < FUSE_MAX_OUTSTANDING; i++) 188334f485dSMiklos Szeredi up(&fc->outstanding_sem); 189334f485dSMiklos Szeredi } 190334f485dSMiklos Szeredi if (putback) 191334f485dSMiklos Szeredi fuse_putback_request(fc, req); 192334f485dSMiklos Szeredi } 193334f485dSMiklos Szeredi 194334f485dSMiklos Szeredi static void background_request(struct fuse_req *req) 195334f485dSMiklos Szeredi { 196334f485dSMiklos Szeredi /* Need to get hold of the inode(s) and/or file used in the 197334f485dSMiklos Szeredi request, so FORGET and RELEASE are not sent too early */ 198334f485dSMiklos Szeredi req->background = 1; 199334f485dSMiklos Szeredi if (req->inode) 200334f485dSMiklos Szeredi req->inode = igrab(req->inode); 201334f485dSMiklos Szeredi if (req->inode2) 202334f485dSMiklos Szeredi req->inode2 = igrab(req->inode2); 203334f485dSMiklos Szeredi if (req->file) 204334f485dSMiklos Szeredi get_file(req->file); 205334f485dSMiklos Szeredi } 206334f485dSMiklos Szeredi 207334f485dSMiklos Szeredi static int request_wait_answer_nonint(struct fuse_req *req) 208334f485dSMiklos Szeredi { 209334f485dSMiklos Szeredi int err; 210334f485dSMiklos Szeredi sigset_t oldset; 211334f485dSMiklos Szeredi block_sigs(&oldset); 212334f485dSMiklos Szeredi err = wait_event_interruptible(req->waitq, req->finished); 213334f485dSMiklos Szeredi restore_sigs(&oldset); 214334f485dSMiklos Szeredi return err; 215334f485dSMiklos Szeredi } 216334f485dSMiklos Szeredi 217334f485dSMiklos Szeredi /* Called with fuse_lock held. Releases, and then reacquires it. */ 218334f485dSMiklos Szeredi static void request_wait_answer(struct fuse_req *req, int interruptible) 219334f485dSMiklos Szeredi { 220334f485dSMiklos Szeredi int intr; 221334f485dSMiklos Szeredi 222334f485dSMiklos Szeredi spin_unlock(&fuse_lock); 223334f485dSMiklos Szeredi if (interruptible) 224334f485dSMiklos Szeredi intr = wait_event_interruptible(req->waitq, req->finished); 225334f485dSMiklos Szeredi else 226334f485dSMiklos Szeredi intr = request_wait_answer_nonint(req); 227334f485dSMiklos Szeredi spin_lock(&fuse_lock); 228334f485dSMiklos Szeredi if (intr && interruptible && req->sent) { 229334f485dSMiklos Szeredi /* If request is already in userspace, only allow KILL 230334f485dSMiklos Szeredi signal to interrupt */ 231334f485dSMiklos Szeredi spin_unlock(&fuse_lock); 232334f485dSMiklos Szeredi intr = request_wait_answer_nonint(req); 233334f485dSMiklos Szeredi spin_lock(&fuse_lock); 234334f485dSMiklos Szeredi } 235334f485dSMiklos Szeredi if (!intr) 236334f485dSMiklos Szeredi return; 237334f485dSMiklos Szeredi 238334f485dSMiklos Szeredi if (!interruptible || req->sent) 239334f485dSMiklos Szeredi req->out.h.error = -EINTR; 240334f485dSMiklos Szeredi else 241334f485dSMiklos Szeredi req->out.h.error = -ERESTARTNOINTR; 242334f485dSMiklos Szeredi 243334f485dSMiklos Szeredi req->interrupted = 1; 244334f485dSMiklos Szeredi if (req->locked) { 245334f485dSMiklos Szeredi /* This is uninterruptible sleep, because data is 246334f485dSMiklos Szeredi being copied to/from the buffers of req. During 247334f485dSMiklos Szeredi locked state, there mustn't be any filesystem 248334f485dSMiklos Szeredi operation (e.g. page fault), since that could lead 249334f485dSMiklos Szeredi to deadlock */ 250334f485dSMiklos Szeredi spin_unlock(&fuse_lock); 251334f485dSMiklos Szeredi wait_event(req->waitq, !req->locked); 252334f485dSMiklos Szeredi spin_lock(&fuse_lock); 253334f485dSMiklos Szeredi } 254334f485dSMiklos Szeredi if (!req->sent && !list_empty(&req->list)) { 255334f485dSMiklos Szeredi list_del(&req->list); 256334f485dSMiklos Szeredi __fuse_put_request(req); 257334f485dSMiklos Szeredi } else if (!req->finished && req->sent) 258334f485dSMiklos Szeredi background_request(req); 259334f485dSMiklos Szeredi } 260334f485dSMiklos Szeredi 261334f485dSMiklos Szeredi static unsigned len_args(unsigned numargs, struct fuse_arg *args) 262334f485dSMiklos Szeredi { 263334f485dSMiklos Szeredi unsigned nbytes = 0; 264334f485dSMiklos Szeredi unsigned i; 265334f485dSMiklos Szeredi 266334f485dSMiklos Szeredi for (i = 0; i < numargs; i++) 267334f485dSMiklos Szeredi nbytes += args[i].size; 268334f485dSMiklos Szeredi 269334f485dSMiklos Szeredi return nbytes; 270334f485dSMiklos Szeredi } 271334f485dSMiklos Szeredi 272334f485dSMiklos Szeredi static void queue_request(struct fuse_conn *fc, struct fuse_req *req) 273334f485dSMiklos Szeredi { 274334f485dSMiklos Szeredi fc->reqctr++; 275334f485dSMiklos Szeredi /* zero is special */ 276334f485dSMiklos Szeredi if (fc->reqctr == 0) 277334f485dSMiklos Szeredi fc->reqctr = 1; 278334f485dSMiklos Szeredi req->in.h.unique = fc->reqctr; 279334f485dSMiklos Szeredi req->in.h.len = sizeof(struct fuse_in_header) + 280334f485dSMiklos Szeredi len_args(req->in.numargs, (struct fuse_arg *) req->in.args); 281334f485dSMiklos Szeredi if (!req->preallocated) { 282334f485dSMiklos Szeredi /* If request is not preallocated (either FORGET or 283334f485dSMiklos Szeredi RELEASE), then still decrease outstanding_sem, so 284334f485dSMiklos Szeredi user can't open infinite number of files while not 285334f485dSMiklos Szeredi processing the RELEASE requests. However for 286334f485dSMiklos Szeredi efficiency do it without blocking, so if down() 287334f485dSMiklos Szeredi would block, just increase the debt instead */ 288334f485dSMiklos Szeredi if (down_trylock(&fc->outstanding_sem)) 289334f485dSMiklos Szeredi fc->outstanding_debt++; 290334f485dSMiklos Szeredi } 291334f485dSMiklos Szeredi list_add_tail(&req->list, &fc->pending); 292334f485dSMiklos Szeredi wake_up(&fc->waitq); 293334f485dSMiklos Szeredi } 294334f485dSMiklos Szeredi 295334f485dSMiklos Szeredi static void request_send_wait(struct fuse_conn *fc, struct fuse_req *req, 296334f485dSMiklos Szeredi int interruptible) 297334f485dSMiklos Szeredi { 298334f485dSMiklos Szeredi req->isreply = 1; 299334f485dSMiklos Szeredi spin_lock(&fuse_lock); 300334f485dSMiklos Szeredi if (!fc->file) 301334f485dSMiklos Szeredi req->out.h.error = -ENOTCONN; 302334f485dSMiklos Szeredi else if (fc->conn_error) 303334f485dSMiklos Szeredi req->out.h.error = -ECONNREFUSED; 304334f485dSMiklos Szeredi else { 305334f485dSMiklos Szeredi queue_request(fc, req); 306334f485dSMiklos Szeredi /* acquire extra reference, since request is still needed 307334f485dSMiklos Szeredi after request_end() */ 308334f485dSMiklos Szeredi __fuse_get_request(req); 309334f485dSMiklos Szeredi 310334f485dSMiklos Szeredi request_wait_answer(req, interruptible); 311334f485dSMiklos Szeredi } 312334f485dSMiklos Szeredi spin_unlock(&fuse_lock); 313334f485dSMiklos Szeredi } 314334f485dSMiklos Szeredi 315334f485dSMiklos Szeredi void request_send(struct fuse_conn *fc, struct fuse_req *req) 316334f485dSMiklos Szeredi { 317334f485dSMiklos Szeredi request_send_wait(fc, req, 1); 318334f485dSMiklos Szeredi } 319334f485dSMiklos Szeredi 320334f485dSMiklos Szeredi /* 321334f485dSMiklos Szeredi * Non-interruptible version of the above function is for operations 322334f485dSMiklos Szeredi * which can't legally return -ERESTART{SYS,NOINTR}. This can still 323334f485dSMiklos Szeredi * be interrupted but only with SIGKILL. 324334f485dSMiklos Szeredi */ 325334f485dSMiklos Szeredi void request_send_nonint(struct fuse_conn *fc, struct fuse_req *req) 326334f485dSMiklos Szeredi { 327334f485dSMiklos Szeredi request_send_wait(fc, req, 0); 328334f485dSMiklos Szeredi } 329334f485dSMiklos Szeredi 330334f485dSMiklos Szeredi static void request_send_nowait(struct fuse_conn *fc, struct fuse_req *req) 331334f485dSMiklos Szeredi { 332334f485dSMiklos Szeredi spin_lock(&fuse_lock); 333334f485dSMiklos Szeredi if (fc->file) { 334334f485dSMiklos Szeredi queue_request(fc, req); 335334f485dSMiklos Szeredi spin_unlock(&fuse_lock); 336334f485dSMiklos Szeredi } else { 337334f485dSMiklos Szeredi req->out.h.error = -ENOTCONN; 338334f485dSMiklos Szeredi request_end(fc, req); 339334f485dSMiklos Szeredi } 340334f485dSMiklos Szeredi } 341334f485dSMiklos Szeredi 342334f485dSMiklos Szeredi void request_send_noreply(struct fuse_conn *fc, struct fuse_req *req) 343334f485dSMiklos Szeredi { 344334f485dSMiklos Szeredi req->isreply = 0; 345334f485dSMiklos Szeredi request_send_nowait(fc, req); 346334f485dSMiklos Szeredi } 347334f485dSMiklos Szeredi 348334f485dSMiklos Szeredi void request_send_background(struct fuse_conn *fc, struct fuse_req *req) 349334f485dSMiklos Szeredi { 350334f485dSMiklos Szeredi req->isreply = 1; 351334f485dSMiklos Szeredi background_request(req); 352334f485dSMiklos Szeredi request_send_nowait(fc, req); 353334f485dSMiklos Szeredi } 354334f485dSMiklos Szeredi 355334f485dSMiklos Szeredi void fuse_send_init(struct fuse_conn *fc) 356334f485dSMiklos Szeredi { 357334f485dSMiklos Szeredi /* This is called from fuse_read_super() so there's guaranteed 358334f485dSMiklos Szeredi to be a request available */ 359334f485dSMiklos Szeredi struct fuse_req *req = do_get_request(fc); 360334f485dSMiklos Szeredi struct fuse_init_in_out *arg = &req->misc.init_in_out; 361334f485dSMiklos Szeredi arg->major = FUSE_KERNEL_VERSION; 362334f485dSMiklos Szeredi arg->minor = FUSE_KERNEL_MINOR_VERSION; 363334f485dSMiklos Szeredi req->in.h.opcode = FUSE_INIT; 364334f485dSMiklos Szeredi req->in.numargs = 1; 365334f485dSMiklos Szeredi req->in.args[0].size = sizeof(*arg); 366334f485dSMiklos Szeredi req->in.args[0].value = arg; 367334f485dSMiklos Szeredi req->out.numargs = 1; 368334f485dSMiklos Szeredi req->out.args[0].size = sizeof(*arg); 369334f485dSMiklos Szeredi req->out.args[0].value = arg; 370334f485dSMiklos Szeredi request_send_background(fc, req); 371334f485dSMiklos Szeredi } 372334f485dSMiklos Szeredi 373334f485dSMiklos Szeredi /* 374334f485dSMiklos Szeredi * Lock the request. Up to the next unlock_request() there mustn't be 375334f485dSMiklos Szeredi * anything that could cause a page-fault. If the request was already 376334f485dSMiklos Szeredi * interrupted bail out. 377334f485dSMiklos Szeredi */ 378334f485dSMiklos Szeredi static inline int lock_request(struct fuse_req *req) 379334f485dSMiklos Szeredi { 380334f485dSMiklos Szeredi int err = 0; 381334f485dSMiklos Szeredi if (req) { 382334f485dSMiklos Szeredi spin_lock(&fuse_lock); 383334f485dSMiklos Szeredi if (req->interrupted) 384334f485dSMiklos Szeredi err = -ENOENT; 385334f485dSMiklos Szeredi else 386334f485dSMiklos Szeredi req->locked = 1; 387334f485dSMiklos Szeredi spin_unlock(&fuse_lock); 388334f485dSMiklos Szeredi } 389334f485dSMiklos Szeredi return err; 390334f485dSMiklos Szeredi } 391334f485dSMiklos Szeredi 392334f485dSMiklos Szeredi /* 393334f485dSMiklos Szeredi * Unlock request. If it was interrupted during being locked, the 394334f485dSMiklos Szeredi * requester thread is currently waiting for it to be unlocked, so 395334f485dSMiklos Szeredi * wake it up. 396334f485dSMiklos Szeredi */ 397334f485dSMiklos Szeredi static inline void unlock_request(struct fuse_req *req) 398334f485dSMiklos Szeredi { 399334f485dSMiklos Szeredi if (req) { 400334f485dSMiklos Szeredi spin_lock(&fuse_lock); 401334f485dSMiklos Szeredi req->locked = 0; 402334f485dSMiklos Szeredi if (req->interrupted) 403334f485dSMiklos Szeredi wake_up(&req->waitq); 404334f485dSMiklos Szeredi spin_unlock(&fuse_lock); 405334f485dSMiklos Szeredi } 406334f485dSMiklos Szeredi } 407334f485dSMiklos Szeredi 408334f485dSMiklos Szeredi struct fuse_copy_state { 409334f485dSMiklos Szeredi int write; 410334f485dSMiklos Szeredi struct fuse_req *req; 411334f485dSMiklos Szeredi const struct iovec *iov; 412334f485dSMiklos Szeredi unsigned long nr_segs; 413334f485dSMiklos Szeredi unsigned long seglen; 414334f485dSMiklos Szeredi unsigned long addr; 415334f485dSMiklos Szeredi struct page *pg; 416334f485dSMiklos Szeredi void *mapaddr; 417334f485dSMiklos Szeredi void *buf; 418334f485dSMiklos Szeredi unsigned len; 419334f485dSMiklos Szeredi }; 420334f485dSMiklos Szeredi 421334f485dSMiklos Szeredi static void fuse_copy_init(struct fuse_copy_state *cs, int write, 422334f485dSMiklos Szeredi struct fuse_req *req, const struct iovec *iov, 423334f485dSMiklos Szeredi unsigned long nr_segs) 424334f485dSMiklos Szeredi { 425334f485dSMiklos Szeredi memset(cs, 0, sizeof(*cs)); 426334f485dSMiklos Szeredi cs->write = write; 427334f485dSMiklos Szeredi cs->req = req; 428334f485dSMiklos Szeredi cs->iov = iov; 429334f485dSMiklos Szeredi cs->nr_segs = nr_segs; 430334f485dSMiklos Szeredi } 431334f485dSMiklos Szeredi 432334f485dSMiklos Szeredi /* Unmap and put previous page of userspace buffer */ 433334f485dSMiklos Szeredi static inline void fuse_copy_finish(struct fuse_copy_state *cs) 434334f485dSMiklos Szeredi { 435334f485dSMiklos Szeredi if (cs->mapaddr) { 436334f485dSMiklos Szeredi kunmap_atomic(cs->mapaddr, KM_USER0); 437334f485dSMiklos Szeredi if (cs->write) { 438334f485dSMiklos Szeredi flush_dcache_page(cs->pg); 439334f485dSMiklos Szeredi set_page_dirty_lock(cs->pg); 440334f485dSMiklos Szeredi } 441334f485dSMiklos Szeredi put_page(cs->pg); 442334f485dSMiklos Szeredi cs->mapaddr = NULL; 443334f485dSMiklos Szeredi } 444334f485dSMiklos Szeredi } 445334f485dSMiklos Szeredi 446334f485dSMiklos Szeredi /* 447334f485dSMiklos Szeredi * Get another pagefull of userspace buffer, and map it to kernel 448334f485dSMiklos Szeredi * address space, and lock request 449334f485dSMiklos Szeredi */ 450334f485dSMiklos Szeredi static int fuse_copy_fill(struct fuse_copy_state *cs) 451334f485dSMiklos Szeredi { 452334f485dSMiklos Szeredi unsigned long offset; 453334f485dSMiklos Szeredi int err; 454334f485dSMiklos Szeredi 455334f485dSMiklos Szeredi unlock_request(cs->req); 456334f485dSMiklos Szeredi fuse_copy_finish(cs); 457334f485dSMiklos Szeredi if (!cs->seglen) { 458334f485dSMiklos Szeredi BUG_ON(!cs->nr_segs); 459334f485dSMiklos Szeredi cs->seglen = cs->iov[0].iov_len; 460334f485dSMiklos Szeredi cs->addr = (unsigned long) cs->iov[0].iov_base; 461334f485dSMiklos Szeredi cs->iov ++; 462334f485dSMiklos Szeredi cs->nr_segs --; 463334f485dSMiklos Szeredi } 464334f485dSMiklos Szeredi down_read(¤t->mm->mmap_sem); 465334f485dSMiklos Szeredi err = get_user_pages(current, current->mm, cs->addr, 1, cs->write, 0, 466334f485dSMiklos Szeredi &cs->pg, NULL); 467334f485dSMiklos Szeredi up_read(¤t->mm->mmap_sem); 468334f485dSMiklos Szeredi if (err < 0) 469334f485dSMiklos Szeredi return err; 470334f485dSMiklos Szeredi BUG_ON(err != 1); 471334f485dSMiklos Szeredi offset = cs->addr % PAGE_SIZE; 472334f485dSMiklos Szeredi cs->mapaddr = kmap_atomic(cs->pg, KM_USER0); 473334f485dSMiklos Szeredi cs->buf = cs->mapaddr + offset; 474334f485dSMiklos Szeredi cs->len = min(PAGE_SIZE - offset, cs->seglen); 475334f485dSMiklos Szeredi cs->seglen -= cs->len; 476334f485dSMiklos Szeredi cs->addr += cs->len; 477334f485dSMiklos Szeredi 478334f485dSMiklos Szeredi return lock_request(cs->req); 479334f485dSMiklos Szeredi } 480334f485dSMiklos Szeredi 481334f485dSMiklos Szeredi /* Do as much copy to/from userspace buffer as we can */ 482334f485dSMiklos Szeredi static inline int fuse_copy_do(struct fuse_copy_state *cs, void **val, 483334f485dSMiklos Szeredi unsigned *size) 484334f485dSMiklos Szeredi { 485334f485dSMiklos Szeredi unsigned ncpy = min(*size, cs->len); 486334f485dSMiklos Szeredi if (val) { 487334f485dSMiklos Szeredi if (cs->write) 488334f485dSMiklos Szeredi memcpy(cs->buf, *val, ncpy); 489334f485dSMiklos Szeredi else 490334f485dSMiklos Szeredi memcpy(*val, cs->buf, ncpy); 491334f485dSMiklos Szeredi *val += ncpy; 492334f485dSMiklos Szeredi } 493334f485dSMiklos Szeredi *size -= ncpy; 494334f485dSMiklos Szeredi cs->len -= ncpy; 495334f485dSMiklos Szeredi cs->buf += ncpy; 496334f485dSMiklos Szeredi return ncpy; 497334f485dSMiklos Szeredi } 498334f485dSMiklos Szeredi 499334f485dSMiklos Szeredi /* 500334f485dSMiklos Szeredi * Copy a page in the request to/from the userspace buffer. Must be 501334f485dSMiklos Szeredi * done atomically 502334f485dSMiklos Szeredi */ 503334f485dSMiklos Szeredi static inline int fuse_copy_page(struct fuse_copy_state *cs, struct page *page, 504334f485dSMiklos Szeredi unsigned offset, unsigned count, int zeroing) 505334f485dSMiklos Szeredi { 506334f485dSMiklos Szeredi if (page && zeroing && count < PAGE_SIZE) { 507334f485dSMiklos Szeredi void *mapaddr = kmap_atomic(page, KM_USER1); 508334f485dSMiklos Szeredi memset(mapaddr, 0, PAGE_SIZE); 509334f485dSMiklos Szeredi kunmap_atomic(mapaddr, KM_USER1); 510334f485dSMiklos Szeredi } 511334f485dSMiklos Szeredi while (count) { 512334f485dSMiklos Szeredi int err; 513334f485dSMiklos Szeredi if (!cs->len && (err = fuse_copy_fill(cs))) 514334f485dSMiklos Szeredi return err; 515334f485dSMiklos Szeredi if (page) { 516334f485dSMiklos Szeredi void *mapaddr = kmap_atomic(page, KM_USER1); 517334f485dSMiklos Szeredi void *buf = mapaddr + offset; 518334f485dSMiklos Szeredi offset += fuse_copy_do(cs, &buf, &count); 519334f485dSMiklos Szeredi kunmap_atomic(mapaddr, KM_USER1); 520334f485dSMiklos Szeredi } else 521334f485dSMiklos Szeredi offset += fuse_copy_do(cs, NULL, &count); 522334f485dSMiklos Szeredi } 523334f485dSMiklos Szeredi if (page && !cs->write) 524334f485dSMiklos Szeredi flush_dcache_page(page); 525334f485dSMiklos Szeredi return 0; 526334f485dSMiklos Szeredi } 527334f485dSMiklos Szeredi 528334f485dSMiklos Szeredi /* Copy pages in the request to/from userspace buffer */ 529334f485dSMiklos Szeredi static int fuse_copy_pages(struct fuse_copy_state *cs, unsigned nbytes, 530334f485dSMiklos Szeredi int zeroing) 531334f485dSMiklos Szeredi { 532334f485dSMiklos Szeredi unsigned i; 533334f485dSMiklos Szeredi struct fuse_req *req = cs->req; 534334f485dSMiklos Szeredi unsigned offset = req->page_offset; 535334f485dSMiklos Szeredi unsigned count = min(nbytes, (unsigned) PAGE_SIZE - offset); 536334f485dSMiklos Szeredi 537334f485dSMiklos Szeredi for (i = 0; i < req->num_pages && (nbytes || zeroing); i++) { 538334f485dSMiklos Szeredi struct page *page = req->pages[i]; 539334f485dSMiklos Szeredi int err = fuse_copy_page(cs, page, offset, count, zeroing); 540334f485dSMiklos Szeredi if (err) 541334f485dSMiklos Szeredi return err; 542334f485dSMiklos Szeredi 543334f485dSMiklos Szeredi nbytes -= count; 544334f485dSMiklos Szeredi count = min(nbytes, (unsigned) PAGE_SIZE); 545334f485dSMiklos Szeredi offset = 0; 546334f485dSMiklos Szeredi } 547334f485dSMiklos Szeredi return 0; 548334f485dSMiklos Szeredi } 549334f485dSMiklos Szeredi 550334f485dSMiklos Szeredi /* Copy a single argument in the request to/from userspace buffer */ 551334f485dSMiklos Szeredi static int fuse_copy_one(struct fuse_copy_state *cs, void *val, unsigned size) 552334f485dSMiklos Szeredi { 553334f485dSMiklos Szeredi while (size) { 554334f485dSMiklos Szeredi int err; 555334f485dSMiklos Szeredi if (!cs->len && (err = fuse_copy_fill(cs))) 556334f485dSMiklos Szeredi return err; 557334f485dSMiklos Szeredi fuse_copy_do(cs, &val, &size); 558334f485dSMiklos Szeredi } 559334f485dSMiklos Szeredi return 0; 560334f485dSMiklos Szeredi } 561334f485dSMiklos Szeredi 562334f485dSMiklos Szeredi /* Copy request arguments to/from userspace buffer */ 563334f485dSMiklos Szeredi static int fuse_copy_args(struct fuse_copy_state *cs, unsigned numargs, 564334f485dSMiklos Szeredi unsigned argpages, struct fuse_arg *args, 565334f485dSMiklos Szeredi int zeroing) 566334f485dSMiklos Szeredi { 567334f485dSMiklos Szeredi int err = 0; 568334f485dSMiklos Szeredi unsigned i; 569334f485dSMiklos Szeredi 570334f485dSMiklos Szeredi for (i = 0; !err && i < numargs; i++) { 571334f485dSMiklos Szeredi struct fuse_arg *arg = &args[i]; 572334f485dSMiklos Szeredi if (i == numargs - 1 && argpages) 573334f485dSMiklos Szeredi err = fuse_copy_pages(cs, arg->size, zeroing); 574334f485dSMiklos Szeredi else 575334f485dSMiklos Szeredi err = fuse_copy_one(cs, arg->value, arg->size); 576334f485dSMiklos Szeredi } 577334f485dSMiklos Szeredi return err; 578334f485dSMiklos Szeredi } 579334f485dSMiklos Szeredi 580334f485dSMiklos Szeredi /* Wait until a request is available on the pending list */ 581334f485dSMiklos Szeredi static void request_wait(struct fuse_conn *fc) 582334f485dSMiklos Szeredi { 583334f485dSMiklos Szeredi DECLARE_WAITQUEUE(wait, current); 584334f485dSMiklos Szeredi 585334f485dSMiklos Szeredi add_wait_queue_exclusive(&fc->waitq, &wait); 586334f485dSMiklos Szeredi while (fc->sb && list_empty(&fc->pending)) { 587334f485dSMiklos Szeredi set_current_state(TASK_INTERRUPTIBLE); 588334f485dSMiklos Szeredi if (signal_pending(current)) 589334f485dSMiklos Szeredi break; 590334f485dSMiklos Szeredi 591334f485dSMiklos Szeredi spin_unlock(&fuse_lock); 592334f485dSMiklos Szeredi schedule(); 593334f485dSMiklos Szeredi spin_lock(&fuse_lock); 594334f485dSMiklos Szeredi } 595334f485dSMiklos Szeredi set_current_state(TASK_RUNNING); 596334f485dSMiklos Szeredi remove_wait_queue(&fc->waitq, &wait); 597334f485dSMiklos Szeredi } 598334f485dSMiklos Szeredi 599334f485dSMiklos Szeredi /* 600334f485dSMiklos Szeredi * Read a single request into the userspace filesystem's buffer. This 601334f485dSMiklos Szeredi * function waits until a request is available, then removes it from 602334f485dSMiklos Szeredi * the pending list and copies request data to userspace buffer. If 603334f485dSMiklos Szeredi * no reply is needed (FORGET) or request has been interrupted or 604334f485dSMiklos Szeredi * there was an error during the copying then it's finished by calling 605334f485dSMiklos Szeredi * request_end(). Otherwise add it to the processing list, and set 606334f485dSMiklos Szeredi * the 'sent' flag. 607334f485dSMiklos Szeredi */ 608334f485dSMiklos Szeredi static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov, 609334f485dSMiklos Szeredi unsigned long nr_segs, loff_t *off) 610334f485dSMiklos Szeredi { 611334f485dSMiklos Szeredi int err; 612334f485dSMiklos Szeredi struct fuse_conn *fc; 613334f485dSMiklos Szeredi struct fuse_req *req; 614334f485dSMiklos Szeredi struct fuse_in *in; 615334f485dSMiklos Szeredi struct fuse_copy_state cs; 616334f485dSMiklos Szeredi unsigned reqsize; 617334f485dSMiklos Szeredi 618334f485dSMiklos Szeredi spin_lock(&fuse_lock); 619334f485dSMiklos Szeredi fc = file->private_data; 620334f485dSMiklos Szeredi err = -EPERM; 621334f485dSMiklos Szeredi if (!fc) 622334f485dSMiklos Szeredi goto err_unlock; 623334f485dSMiklos Szeredi request_wait(fc); 624334f485dSMiklos Szeredi err = -ENODEV; 625334f485dSMiklos Szeredi if (!fc->sb) 626334f485dSMiklos Szeredi goto err_unlock; 627334f485dSMiklos Szeredi err = -ERESTARTSYS; 628334f485dSMiklos Szeredi if (list_empty(&fc->pending)) 629334f485dSMiklos Szeredi goto err_unlock; 630334f485dSMiklos Szeredi 631334f485dSMiklos Szeredi req = list_entry(fc->pending.next, struct fuse_req, list); 632334f485dSMiklos Szeredi list_del_init(&req->list); 633334f485dSMiklos Szeredi spin_unlock(&fuse_lock); 634334f485dSMiklos Szeredi 635334f485dSMiklos Szeredi in = &req->in; 636334f485dSMiklos Szeredi reqsize = req->in.h.len; 637334f485dSMiklos Szeredi fuse_copy_init(&cs, 1, req, iov, nr_segs); 638334f485dSMiklos Szeredi err = -EINVAL; 639334f485dSMiklos Szeredi if (iov_length(iov, nr_segs) >= reqsize) { 640334f485dSMiklos Szeredi err = fuse_copy_one(&cs, &in->h, sizeof(in->h)); 641334f485dSMiklos Szeredi if (!err) 642334f485dSMiklos Szeredi err = fuse_copy_args(&cs, in->numargs, in->argpages, 643334f485dSMiklos Szeredi (struct fuse_arg *) in->args, 0); 644334f485dSMiklos Szeredi } 645334f485dSMiklos Szeredi fuse_copy_finish(&cs); 646334f485dSMiklos Szeredi 647334f485dSMiklos Szeredi spin_lock(&fuse_lock); 648334f485dSMiklos Szeredi req->locked = 0; 649334f485dSMiklos Szeredi if (!err && req->interrupted) 650334f485dSMiklos Szeredi err = -ENOENT; 651334f485dSMiklos Szeredi if (err) { 652334f485dSMiklos Szeredi if (!req->interrupted) 653334f485dSMiklos Szeredi req->out.h.error = -EIO; 654334f485dSMiklos Szeredi request_end(fc, req); 655334f485dSMiklos Szeredi return err; 656334f485dSMiklos Szeredi } 657334f485dSMiklos Szeredi if (!req->isreply) 658334f485dSMiklos Szeredi request_end(fc, req); 659334f485dSMiklos Szeredi else { 660334f485dSMiklos Szeredi req->sent = 1; 661334f485dSMiklos Szeredi list_add_tail(&req->list, &fc->processing); 662334f485dSMiklos Szeredi spin_unlock(&fuse_lock); 663334f485dSMiklos Szeredi } 664334f485dSMiklos Szeredi return reqsize; 665334f485dSMiklos Szeredi 666334f485dSMiklos Szeredi err_unlock: 667334f485dSMiklos Szeredi spin_unlock(&fuse_lock); 668334f485dSMiklos Szeredi return err; 669334f485dSMiklos Szeredi } 670334f485dSMiklos Szeredi 671334f485dSMiklos Szeredi static ssize_t fuse_dev_read(struct file *file, char __user *buf, 672334f485dSMiklos Szeredi size_t nbytes, loff_t *off) 673334f485dSMiklos Szeredi { 674334f485dSMiklos Szeredi struct iovec iov; 675334f485dSMiklos Szeredi iov.iov_len = nbytes; 676334f485dSMiklos Szeredi iov.iov_base = buf; 677334f485dSMiklos Szeredi return fuse_dev_readv(file, &iov, 1, off); 678334f485dSMiklos Szeredi } 679334f485dSMiklos Szeredi 680334f485dSMiklos Szeredi /* Look up request on processing list by unique ID */ 681334f485dSMiklos Szeredi static struct fuse_req *request_find(struct fuse_conn *fc, u64 unique) 682334f485dSMiklos Szeredi { 683334f485dSMiklos Szeredi struct list_head *entry; 684334f485dSMiklos Szeredi 685334f485dSMiklos Szeredi list_for_each(entry, &fc->processing) { 686334f485dSMiklos Szeredi struct fuse_req *req; 687334f485dSMiklos Szeredi req = list_entry(entry, struct fuse_req, list); 688334f485dSMiklos Szeredi if (req->in.h.unique == unique) 689334f485dSMiklos Szeredi return req; 690334f485dSMiklos Szeredi } 691334f485dSMiklos Szeredi return NULL; 692334f485dSMiklos Szeredi } 693334f485dSMiklos Szeredi 694334f485dSMiklos Szeredi static int copy_out_args(struct fuse_copy_state *cs, struct fuse_out *out, 695334f485dSMiklos Szeredi unsigned nbytes) 696334f485dSMiklos Szeredi { 697334f485dSMiklos Szeredi unsigned reqsize = sizeof(struct fuse_out_header); 698334f485dSMiklos Szeredi 699334f485dSMiklos Szeredi if (out->h.error) 700334f485dSMiklos Szeredi return nbytes != reqsize ? -EINVAL : 0; 701334f485dSMiklos Szeredi 702334f485dSMiklos Szeredi reqsize += len_args(out->numargs, out->args); 703334f485dSMiklos Szeredi 704334f485dSMiklos Szeredi if (reqsize < nbytes || (reqsize > nbytes && !out->argvar)) 705334f485dSMiklos Szeredi return -EINVAL; 706334f485dSMiklos Szeredi else if (reqsize > nbytes) { 707334f485dSMiklos Szeredi struct fuse_arg *lastarg = &out->args[out->numargs-1]; 708334f485dSMiklos Szeredi unsigned diffsize = reqsize - nbytes; 709334f485dSMiklos Szeredi if (diffsize > lastarg->size) 710334f485dSMiklos Szeredi return -EINVAL; 711334f485dSMiklos Szeredi lastarg->size -= diffsize; 712334f485dSMiklos Szeredi } 713334f485dSMiklos Szeredi return fuse_copy_args(cs, out->numargs, out->argpages, out->args, 714334f485dSMiklos Szeredi out->page_zeroing); 715334f485dSMiklos Szeredi } 716334f485dSMiklos Szeredi 717334f485dSMiklos Szeredi /* 718334f485dSMiklos Szeredi * Write a single reply to a request. First the header is copied from 719334f485dSMiklos Szeredi * the write buffer. The request is then searched on the processing 720334f485dSMiklos Szeredi * list by the unique ID found in the header. If found, then remove 721334f485dSMiklos Szeredi * it from the list and copy the rest of the buffer to the request. 722334f485dSMiklos Szeredi * The request is finished by calling request_end() 723334f485dSMiklos Szeredi */ 724334f485dSMiklos Szeredi static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov, 725334f485dSMiklos Szeredi unsigned long nr_segs, loff_t *off) 726334f485dSMiklos Szeredi { 727334f485dSMiklos Szeredi int err; 728334f485dSMiklos Szeredi unsigned nbytes = iov_length(iov, nr_segs); 729334f485dSMiklos Szeredi struct fuse_req *req; 730334f485dSMiklos Szeredi struct fuse_out_header oh; 731334f485dSMiklos Szeredi struct fuse_copy_state cs; 732334f485dSMiklos Szeredi struct fuse_conn *fc = fuse_get_conn(file); 733334f485dSMiklos Szeredi if (!fc) 734334f485dSMiklos Szeredi return -ENODEV; 735334f485dSMiklos Szeredi 736334f485dSMiklos Szeredi fuse_copy_init(&cs, 0, NULL, iov, nr_segs); 737334f485dSMiklos Szeredi if (nbytes < sizeof(struct fuse_out_header)) 738334f485dSMiklos Szeredi return -EINVAL; 739334f485dSMiklos Szeredi 740334f485dSMiklos Szeredi err = fuse_copy_one(&cs, &oh, sizeof(oh)); 741334f485dSMiklos Szeredi if (err) 742334f485dSMiklos Szeredi goto err_finish; 743334f485dSMiklos Szeredi err = -EINVAL; 744334f485dSMiklos Szeredi if (!oh.unique || oh.error <= -1000 || oh.error > 0 || 745334f485dSMiklos Szeredi oh.len != nbytes) 746334f485dSMiklos Szeredi goto err_finish; 747334f485dSMiklos Szeredi 748334f485dSMiklos Szeredi spin_lock(&fuse_lock); 749334f485dSMiklos Szeredi req = request_find(fc, oh.unique); 750334f485dSMiklos Szeredi err = -EINVAL; 751334f485dSMiklos Szeredi if (!req) 752334f485dSMiklos Szeredi goto err_unlock; 753334f485dSMiklos Szeredi 754334f485dSMiklos Szeredi list_del_init(&req->list); 755334f485dSMiklos Szeredi if (req->interrupted) { 756334f485dSMiklos Szeredi request_end(fc, req); 757334f485dSMiklos Szeredi fuse_copy_finish(&cs); 758334f485dSMiklos Szeredi return -ENOENT; 759334f485dSMiklos Szeredi } 760334f485dSMiklos Szeredi req->out.h = oh; 761334f485dSMiklos Szeredi req->locked = 1; 762334f485dSMiklos Szeredi cs.req = req; 763334f485dSMiklos Szeredi spin_unlock(&fuse_lock); 764334f485dSMiklos Szeredi 765334f485dSMiklos Szeredi err = copy_out_args(&cs, &req->out, nbytes); 766334f485dSMiklos Szeredi fuse_copy_finish(&cs); 767334f485dSMiklos Szeredi 768334f485dSMiklos Szeredi spin_lock(&fuse_lock); 769334f485dSMiklos Szeredi req->locked = 0; 770334f485dSMiklos Szeredi if (!err) { 771334f485dSMiklos Szeredi if (req->interrupted) 772334f485dSMiklos Szeredi err = -ENOENT; 773334f485dSMiklos Szeredi } else if (!req->interrupted) 774334f485dSMiklos Szeredi req->out.h.error = -EIO; 775334f485dSMiklos Szeredi request_end(fc, req); 776334f485dSMiklos Szeredi 777334f485dSMiklos Szeredi return err ? err : nbytes; 778334f485dSMiklos Szeredi 779334f485dSMiklos Szeredi err_unlock: 780334f485dSMiklos Szeredi spin_unlock(&fuse_lock); 781334f485dSMiklos Szeredi err_finish: 782334f485dSMiklos Szeredi fuse_copy_finish(&cs); 783334f485dSMiklos Szeredi return err; 784334f485dSMiklos Szeredi } 785334f485dSMiklos Szeredi 786334f485dSMiklos Szeredi static ssize_t fuse_dev_write(struct file *file, const char __user *buf, 787334f485dSMiklos Szeredi size_t nbytes, loff_t *off) 788334f485dSMiklos Szeredi { 789334f485dSMiklos Szeredi struct iovec iov; 790334f485dSMiklos Szeredi iov.iov_len = nbytes; 791334f485dSMiklos Szeredi iov.iov_base = (char __user *) buf; 792334f485dSMiklos Szeredi return fuse_dev_writev(file, &iov, 1, off); 793334f485dSMiklos Szeredi } 794334f485dSMiklos Szeredi 795334f485dSMiklos Szeredi static unsigned fuse_dev_poll(struct file *file, poll_table *wait) 796334f485dSMiklos Szeredi { 797334f485dSMiklos Szeredi struct fuse_conn *fc = fuse_get_conn(file); 798334f485dSMiklos Szeredi unsigned mask = POLLOUT | POLLWRNORM; 799334f485dSMiklos Szeredi 800334f485dSMiklos Szeredi if (!fc) 801334f485dSMiklos Szeredi return -ENODEV; 802334f485dSMiklos Szeredi 803334f485dSMiklos Szeredi poll_wait(file, &fc->waitq, wait); 804334f485dSMiklos Szeredi 805334f485dSMiklos Szeredi spin_lock(&fuse_lock); 806334f485dSMiklos Szeredi if (!list_empty(&fc->pending)) 807334f485dSMiklos Szeredi mask |= POLLIN | POLLRDNORM; 808334f485dSMiklos Szeredi spin_unlock(&fuse_lock); 809334f485dSMiklos Szeredi 810334f485dSMiklos Szeredi return mask; 811334f485dSMiklos Szeredi } 812334f485dSMiklos Szeredi 813334f485dSMiklos Szeredi /* Abort all requests on the given list (pending or processing) */ 814334f485dSMiklos Szeredi static void end_requests(struct fuse_conn *fc, struct list_head *head) 815334f485dSMiklos Szeredi { 816334f485dSMiklos Szeredi while (!list_empty(head)) { 817334f485dSMiklos Szeredi struct fuse_req *req; 818334f485dSMiklos Szeredi req = list_entry(head->next, struct fuse_req, list); 819334f485dSMiklos Szeredi list_del_init(&req->list); 820334f485dSMiklos Szeredi req->out.h.error = -ECONNABORTED; 821334f485dSMiklos Szeredi request_end(fc, req); 822334f485dSMiklos Szeredi spin_lock(&fuse_lock); 823334f485dSMiklos Szeredi } 824334f485dSMiklos Szeredi } 825334f485dSMiklos Szeredi 826334f485dSMiklos Szeredi static int fuse_dev_release(struct inode *inode, struct file *file) 827334f485dSMiklos Szeredi { 828334f485dSMiklos Szeredi struct fuse_conn *fc; 829334f485dSMiklos Szeredi 830334f485dSMiklos Szeredi spin_lock(&fuse_lock); 831334f485dSMiklos Szeredi fc = file->private_data; 832334f485dSMiklos Szeredi if (fc) { 833334f485dSMiklos Szeredi fc->file = NULL; 834334f485dSMiklos Szeredi end_requests(fc, &fc->pending); 835334f485dSMiklos Szeredi end_requests(fc, &fc->processing); 836334f485dSMiklos Szeredi fuse_release_conn(fc); 837334f485dSMiklos Szeredi } 838334f485dSMiklos Szeredi spin_unlock(&fuse_lock); 839334f485dSMiklos Szeredi return 0; 840334f485dSMiklos Szeredi } 841334f485dSMiklos Szeredi 842334f485dSMiklos Szeredi struct file_operations fuse_dev_operations = { 843334f485dSMiklos Szeredi .owner = THIS_MODULE, 844334f485dSMiklos Szeredi .llseek = no_llseek, 845334f485dSMiklos Szeredi .read = fuse_dev_read, 846334f485dSMiklos Szeredi .readv = fuse_dev_readv, 847334f485dSMiklos Szeredi .write = fuse_dev_write, 848334f485dSMiklos Szeredi .writev = fuse_dev_writev, 849334f485dSMiklos Szeredi .poll = fuse_dev_poll, 850334f485dSMiklos Szeredi .release = fuse_dev_release, 851334f485dSMiklos Szeredi }; 852334f485dSMiklos Szeredi 853334f485dSMiklos Szeredi static struct miscdevice fuse_miscdevice = { 854334f485dSMiklos Szeredi .minor = FUSE_MINOR, 855334f485dSMiklos Szeredi .name = "fuse", 856334f485dSMiklos Szeredi .fops = &fuse_dev_operations, 857334f485dSMiklos Szeredi }; 858334f485dSMiklos Szeredi 859334f485dSMiklos Szeredi int __init fuse_dev_init(void) 860334f485dSMiklos Szeredi { 861334f485dSMiklos Szeredi int err = -ENOMEM; 862334f485dSMiklos Szeredi fuse_req_cachep = kmem_cache_create("fuse_request", 863334f485dSMiklos Szeredi sizeof(struct fuse_req), 864334f485dSMiklos Szeredi 0, 0, NULL, NULL); 865334f485dSMiklos Szeredi if (!fuse_req_cachep) 866334f485dSMiklos Szeredi goto out; 867334f485dSMiklos Szeredi 868334f485dSMiklos Szeredi err = misc_register(&fuse_miscdevice); 869334f485dSMiklos Szeredi if (err) 870334f485dSMiklos Szeredi goto out_cache_clean; 871334f485dSMiklos Szeredi 872334f485dSMiklos Szeredi return 0; 873334f485dSMiklos Szeredi 874334f485dSMiklos Szeredi out_cache_clean: 875334f485dSMiklos Szeredi kmem_cache_destroy(fuse_req_cachep); 876334f485dSMiklos Szeredi out: 877334f485dSMiklos Szeredi return err; 878334f485dSMiklos Szeredi } 879334f485dSMiklos Szeredi 880334f485dSMiklos Szeredi void fuse_dev_cleanup(void) 881334f485dSMiklos Szeredi { 882334f485dSMiklos Szeredi misc_deregister(&fuse_miscdevice); 883334f485dSMiklos Szeredi kmem_cache_destroy(fuse_req_cachep); 884334f485dSMiklos Szeredi } 885