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; 29*1e9a4ed9SMiklos Szeredi if (fc && !fc->mounted) 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 151*1e9a4ed9SMiklos Szeredi void fuse_release_background(struct fuse_req *req) 152*1e9a4ed9SMiklos Szeredi { 153*1e9a4ed9SMiklos Szeredi iput(req->inode); 154*1e9a4ed9SMiklos Szeredi iput(req->inode2); 155*1e9a4ed9SMiklos Szeredi if (req->file) 156*1e9a4ed9SMiklos Szeredi fput(req->file); 157*1e9a4ed9SMiklos Szeredi spin_lock(&fuse_lock); 158*1e9a4ed9SMiklos Szeredi list_del(&req->bg_entry); 159*1e9a4ed9SMiklos Szeredi spin_unlock(&fuse_lock); 160*1e9a4ed9SMiklos Szeredi } 161*1e9a4ed9SMiklos Szeredi 162334f485dSMiklos Szeredi /* 163334f485dSMiklos Szeredi * This function is called when a request is finished. Either a reply 164334f485dSMiklos Szeredi * has arrived or it was interrupted (and not yet sent) or some error 165334f485dSMiklos Szeredi * occured during communication with userspace, or the device file was 166334f485dSMiklos Szeredi * closed. It decreases the referece count for the request. In case 167334f485dSMiklos Szeredi * of a background request the referece to the stored objects are 168334f485dSMiklos Szeredi * released. The requester thread is woken up (if still waiting), and 169334f485dSMiklos Szeredi * finally the request is either freed or put on the unused_list 170334f485dSMiklos Szeredi * 171334f485dSMiklos Szeredi * Called with fuse_lock, unlocks it 172334f485dSMiklos Szeredi */ 173334f485dSMiklos Szeredi static void request_end(struct fuse_conn *fc, struct fuse_req *req) 174334f485dSMiklos Szeredi { 175334f485dSMiklos Szeredi int putback; 176334f485dSMiklos Szeredi req->finished = 1; 177334f485dSMiklos Szeredi putback = atomic_dec_and_test(&req->count); 178334f485dSMiklos Szeredi spin_unlock(&fuse_lock); 179334f485dSMiklos Szeredi if (req->background) { 180*1e9a4ed9SMiklos Szeredi down_read(&fc->sbput_sem); 181*1e9a4ed9SMiklos Szeredi if (fc->mounted) 182*1e9a4ed9SMiklos Szeredi fuse_release_background(req); 183*1e9a4ed9SMiklos Szeredi up_read(&fc->sbput_sem); 184334f485dSMiklos Szeredi } 185334f485dSMiklos Szeredi wake_up(&req->waitq); 186334f485dSMiklos Szeredi if (req->in.h.opcode == FUSE_INIT) { 187334f485dSMiklos Szeredi int i; 188334f485dSMiklos Szeredi 189334f485dSMiklos Szeredi if (req->misc.init_in_out.major != FUSE_KERNEL_VERSION) 190334f485dSMiklos Szeredi fc->conn_error = 1; 191334f485dSMiklos Szeredi 192334f485dSMiklos Szeredi /* After INIT reply is received other requests can go 193334f485dSMiklos Szeredi out. So do (FUSE_MAX_OUTSTANDING - 1) number of 194334f485dSMiklos Szeredi up()s on outstanding_sem. The last up() is done in 195334f485dSMiklos Szeredi fuse_putback_request() */ 196334f485dSMiklos Szeredi for (i = 1; i < FUSE_MAX_OUTSTANDING; i++) 197334f485dSMiklos Szeredi up(&fc->outstanding_sem); 198334f485dSMiklos Szeredi } 199334f485dSMiklos Szeredi if (putback) 200334f485dSMiklos Szeredi fuse_putback_request(fc, req); 201334f485dSMiklos Szeredi } 202334f485dSMiklos Szeredi 203*1e9a4ed9SMiklos Szeredi /* 204*1e9a4ed9SMiklos Szeredi * Unfortunately request interruption not just solves the deadlock 205*1e9a4ed9SMiklos Szeredi * problem, it causes problems too. These stem from the fact, that an 206*1e9a4ed9SMiklos Szeredi * interrupted request is continued to be processed in userspace, 207*1e9a4ed9SMiklos Szeredi * while all the locks and object references (inode and file) held 208*1e9a4ed9SMiklos Szeredi * during the operation are released. 209*1e9a4ed9SMiklos Szeredi * 210*1e9a4ed9SMiklos Szeredi * To release the locks is exactly why there's a need to interrupt the 211*1e9a4ed9SMiklos Szeredi * request, so there's not a lot that can be done about this, except 212*1e9a4ed9SMiklos Szeredi * introduce additional locking in userspace. 213*1e9a4ed9SMiklos Szeredi * 214*1e9a4ed9SMiklos Szeredi * More important is to keep inode and file references until userspace 215*1e9a4ed9SMiklos Szeredi * has replied, otherwise FORGET and RELEASE could be sent while the 216*1e9a4ed9SMiklos Szeredi * inode/file is still used by the filesystem. 217*1e9a4ed9SMiklos Szeredi * 218*1e9a4ed9SMiklos Szeredi * For this reason the concept of "background" request is introduced. 219*1e9a4ed9SMiklos Szeredi * An interrupted request is backgrounded if it has been already sent 220*1e9a4ed9SMiklos Szeredi * to userspace. Backgrounding involves getting an extra reference to 221*1e9a4ed9SMiklos Szeredi * inode(s) or file used in the request, and adding the request to 222*1e9a4ed9SMiklos Szeredi * fc->background list. When a reply is received for a background 223*1e9a4ed9SMiklos Szeredi * request, the object references are released, and the request is 224*1e9a4ed9SMiklos Szeredi * removed from the list. If the filesystem is unmounted while there 225*1e9a4ed9SMiklos Szeredi * are still background requests, the list is walked and references 226*1e9a4ed9SMiklos Szeredi * are released as if a reply was received. 227*1e9a4ed9SMiklos Szeredi * 228*1e9a4ed9SMiklos Szeredi * There's one more use for a background request. The RELEASE message is 229*1e9a4ed9SMiklos Szeredi * always sent as background, since it doesn't return an error or 230*1e9a4ed9SMiklos Szeredi * data. 231*1e9a4ed9SMiklos Szeredi */ 232*1e9a4ed9SMiklos Szeredi static void background_request(struct fuse_conn *fc, struct fuse_req *req) 233334f485dSMiklos Szeredi { 234334f485dSMiklos Szeredi req->background = 1; 235*1e9a4ed9SMiklos Szeredi list_add(&req->bg_entry, &fc->background); 236334f485dSMiklos Szeredi if (req->inode) 237334f485dSMiklos Szeredi req->inode = igrab(req->inode); 238334f485dSMiklos Szeredi if (req->inode2) 239334f485dSMiklos Szeredi req->inode2 = igrab(req->inode2); 240334f485dSMiklos Szeredi if (req->file) 241334f485dSMiklos Szeredi get_file(req->file); 242334f485dSMiklos Szeredi } 243334f485dSMiklos Szeredi 244334f485dSMiklos Szeredi static int request_wait_answer_nonint(struct fuse_req *req) 245334f485dSMiklos Szeredi { 246334f485dSMiklos Szeredi int err; 247334f485dSMiklos Szeredi sigset_t oldset; 248334f485dSMiklos Szeredi block_sigs(&oldset); 249334f485dSMiklos Szeredi err = wait_event_interruptible(req->waitq, req->finished); 250334f485dSMiklos Szeredi restore_sigs(&oldset); 251334f485dSMiklos Szeredi return err; 252334f485dSMiklos Szeredi } 253334f485dSMiklos Szeredi 254334f485dSMiklos Szeredi /* Called with fuse_lock held. Releases, and then reacquires it. */ 255*1e9a4ed9SMiklos Szeredi static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req, 256*1e9a4ed9SMiklos Szeredi int interruptible) 257334f485dSMiklos Szeredi { 258334f485dSMiklos Szeredi int intr; 259334f485dSMiklos Szeredi 260334f485dSMiklos Szeredi spin_unlock(&fuse_lock); 261334f485dSMiklos Szeredi if (interruptible) 262334f485dSMiklos Szeredi intr = wait_event_interruptible(req->waitq, req->finished); 263334f485dSMiklos Szeredi else 264334f485dSMiklos Szeredi intr = request_wait_answer_nonint(req); 265334f485dSMiklos Szeredi spin_lock(&fuse_lock); 266334f485dSMiklos Szeredi if (intr && interruptible && req->sent) { 267334f485dSMiklos Szeredi /* If request is already in userspace, only allow KILL 268334f485dSMiklos Szeredi signal to interrupt */ 269334f485dSMiklos Szeredi spin_unlock(&fuse_lock); 270334f485dSMiklos Szeredi intr = request_wait_answer_nonint(req); 271334f485dSMiklos Szeredi spin_lock(&fuse_lock); 272334f485dSMiklos Szeredi } 273334f485dSMiklos Szeredi if (!intr) 274334f485dSMiklos Szeredi return; 275334f485dSMiklos Szeredi 276334f485dSMiklos Szeredi if (!interruptible || req->sent) 277334f485dSMiklos Szeredi req->out.h.error = -EINTR; 278334f485dSMiklos Szeredi else 279334f485dSMiklos Szeredi req->out.h.error = -ERESTARTNOINTR; 280334f485dSMiklos Szeredi 281334f485dSMiklos Szeredi req->interrupted = 1; 282334f485dSMiklos Szeredi if (req->locked) { 283334f485dSMiklos Szeredi /* This is uninterruptible sleep, because data is 284334f485dSMiklos Szeredi being copied to/from the buffers of req. During 285334f485dSMiklos Szeredi locked state, there mustn't be any filesystem 286334f485dSMiklos Szeredi operation (e.g. page fault), since that could lead 287334f485dSMiklos Szeredi to deadlock */ 288334f485dSMiklos Szeredi spin_unlock(&fuse_lock); 289334f485dSMiklos Szeredi wait_event(req->waitq, !req->locked); 290334f485dSMiklos Szeredi spin_lock(&fuse_lock); 291334f485dSMiklos Szeredi } 292334f485dSMiklos Szeredi if (!req->sent && !list_empty(&req->list)) { 293334f485dSMiklos Szeredi list_del(&req->list); 294334f485dSMiklos Szeredi __fuse_put_request(req); 295334f485dSMiklos Szeredi } else if (!req->finished && req->sent) 296*1e9a4ed9SMiklos Szeredi background_request(fc, req); 297334f485dSMiklos Szeredi } 298334f485dSMiklos Szeredi 299334f485dSMiklos Szeredi static unsigned len_args(unsigned numargs, struct fuse_arg *args) 300334f485dSMiklos Szeredi { 301334f485dSMiklos Szeredi unsigned nbytes = 0; 302334f485dSMiklos Szeredi unsigned i; 303334f485dSMiklos Szeredi 304334f485dSMiklos Szeredi for (i = 0; i < numargs; i++) 305334f485dSMiklos Szeredi nbytes += args[i].size; 306334f485dSMiklos Szeredi 307334f485dSMiklos Szeredi return nbytes; 308334f485dSMiklos Szeredi } 309334f485dSMiklos Szeredi 310334f485dSMiklos Szeredi static void queue_request(struct fuse_conn *fc, struct fuse_req *req) 311334f485dSMiklos Szeredi { 312334f485dSMiklos Szeredi fc->reqctr++; 313334f485dSMiklos Szeredi /* zero is special */ 314334f485dSMiklos Szeredi if (fc->reqctr == 0) 315334f485dSMiklos Szeredi fc->reqctr = 1; 316334f485dSMiklos Szeredi req->in.h.unique = fc->reqctr; 317334f485dSMiklos Szeredi req->in.h.len = sizeof(struct fuse_in_header) + 318334f485dSMiklos Szeredi len_args(req->in.numargs, (struct fuse_arg *) req->in.args); 319334f485dSMiklos Szeredi if (!req->preallocated) { 320334f485dSMiklos Szeredi /* If request is not preallocated (either FORGET or 321334f485dSMiklos Szeredi RELEASE), then still decrease outstanding_sem, so 322334f485dSMiklos Szeredi user can't open infinite number of files while not 323334f485dSMiklos Szeredi processing the RELEASE requests. However for 324334f485dSMiklos Szeredi efficiency do it without blocking, so if down() 325334f485dSMiklos Szeredi would block, just increase the debt instead */ 326334f485dSMiklos Szeredi if (down_trylock(&fc->outstanding_sem)) 327334f485dSMiklos Szeredi fc->outstanding_debt++; 328334f485dSMiklos Szeredi } 329334f485dSMiklos Szeredi list_add_tail(&req->list, &fc->pending); 330334f485dSMiklos Szeredi wake_up(&fc->waitq); 331334f485dSMiklos Szeredi } 332334f485dSMiklos Szeredi 333334f485dSMiklos Szeredi static void request_send_wait(struct fuse_conn *fc, struct fuse_req *req, 334334f485dSMiklos Szeredi int interruptible) 335334f485dSMiklos Szeredi { 336334f485dSMiklos Szeredi req->isreply = 1; 337334f485dSMiklos Szeredi spin_lock(&fuse_lock); 338*1e9a4ed9SMiklos Szeredi if (!fc->connected) 339334f485dSMiklos Szeredi req->out.h.error = -ENOTCONN; 340334f485dSMiklos Szeredi else if (fc->conn_error) 341334f485dSMiklos Szeredi req->out.h.error = -ECONNREFUSED; 342334f485dSMiklos Szeredi else { 343334f485dSMiklos Szeredi queue_request(fc, req); 344334f485dSMiklos Szeredi /* acquire extra reference, since request is still needed 345334f485dSMiklos Szeredi after request_end() */ 346334f485dSMiklos Szeredi __fuse_get_request(req); 347334f485dSMiklos Szeredi 348*1e9a4ed9SMiklos Szeredi request_wait_answer(fc, req, interruptible); 349334f485dSMiklos Szeredi } 350334f485dSMiklos Szeredi spin_unlock(&fuse_lock); 351334f485dSMiklos Szeredi } 352334f485dSMiklos Szeredi 353334f485dSMiklos Szeredi void request_send(struct fuse_conn *fc, struct fuse_req *req) 354334f485dSMiklos Szeredi { 355334f485dSMiklos Szeredi request_send_wait(fc, req, 1); 356334f485dSMiklos Szeredi } 357334f485dSMiklos Szeredi 358334f485dSMiklos Szeredi /* 359334f485dSMiklos Szeredi * Non-interruptible version of the above function is for operations 360334f485dSMiklos Szeredi * which can't legally return -ERESTART{SYS,NOINTR}. This can still 361334f485dSMiklos Szeredi * be interrupted but only with SIGKILL. 362334f485dSMiklos Szeredi */ 363334f485dSMiklos Szeredi void request_send_nonint(struct fuse_conn *fc, struct fuse_req *req) 364334f485dSMiklos Szeredi { 365334f485dSMiklos Szeredi request_send_wait(fc, req, 0); 366334f485dSMiklos Szeredi } 367334f485dSMiklos Szeredi 368334f485dSMiklos Szeredi static void request_send_nowait(struct fuse_conn *fc, struct fuse_req *req) 369334f485dSMiklos Szeredi { 370334f485dSMiklos Szeredi spin_lock(&fuse_lock); 371*1e9a4ed9SMiklos Szeredi if (fc->connected) { 372334f485dSMiklos Szeredi queue_request(fc, req); 373334f485dSMiklos Szeredi spin_unlock(&fuse_lock); 374334f485dSMiklos Szeredi } else { 375334f485dSMiklos Szeredi req->out.h.error = -ENOTCONN; 376334f485dSMiklos Szeredi request_end(fc, req); 377334f485dSMiklos Szeredi } 378334f485dSMiklos Szeredi } 379334f485dSMiklos Szeredi 380334f485dSMiklos Szeredi void request_send_noreply(struct fuse_conn *fc, struct fuse_req *req) 381334f485dSMiklos Szeredi { 382334f485dSMiklos Szeredi req->isreply = 0; 383334f485dSMiklos Szeredi request_send_nowait(fc, req); 384334f485dSMiklos Szeredi } 385334f485dSMiklos Szeredi 386334f485dSMiklos Szeredi void request_send_background(struct fuse_conn *fc, struct fuse_req *req) 387334f485dSMiklos Szeredi { 388334f485dSMiklos Szeredi req->isreply = 1; 389*1e9a4ed9SMiklos Szeredi spin_lock(&fuse_lock); 390*1e9a4ed9SMiklos Szeredi background_request(fc, req); 391*1e9a4ed9SMiklos Szeredi spin_unlock(&fuse_lock); 392334f485dSMiklos Szeredi request_send_nowait(fc, req); 393334f485dSMiklos Szeredi } 394334f485dSMiklos Szeredi 395334f485dSMiklos Szeredi void fuse_send_init(struct fuse_conn *fc) 396334f485dSMiklos Szeredi { 397334f485dSMiklos Szeredi /* This is called from fuse_read_super() so there's guaranteed 398334f485dSMiklos Szeredi to be a request available */ 399334f485dSMiklos Szeredi struct fuse_req *req = do_get_request(fc); 400334f485dSMiklos Szeredi struct fuse_init_in_out *arg = &req->misc.init_in_out; 401334f485dSMiklos Szeredi arg->major = FUSE_KERNEL_VERSION; 402334f485dSMiklos Szeredi arg->minor = FUSE_KERNEL_MINOR_VERSION; 403334f485dSMiklos Szeredi req->in.h.opcode = FUSE_INIT; 404334f485dSMiklos Szeredi req->in.numargs = 1; 405334f485dSMiklos Szeredi req->in.args[0].size = sizeof(*arg); 406334f485dSMiklos Szeredi req->in.args[0].value = arg; 407334f485dSMiklos Szeredi req->out.numargs = 1; 408334f485dSMiklos Szeredi req->out.args[0].size = sizeof(*arg); 409334f485dSMiklos Szeredi req->out.args[0].value = arg; 410334f485dSMiklos Szeredi request_send_background(fc, req); 411334f485dSMiklos Szeredi } 412334f485dSMiklos Szeredi 413334f485dSMiklos Szeredi /* 414334f485dSMiklos Szeredi * Lock the request. Up to the next unlock_request() there mustn't be 415334f485dSMiklos Szeredi * anything that could cause a page-fault. If the request was already 416334f485dSMiklos Szeredi * interrupted bail out. 417334f485dSMiklos Szeredi */ 418334f485dSMiklos Szeredi static inline int lock_request(struct fuse_req *req) 419334f485dSMiklos Szeredi { 420334f485dSMiklos Szeredi int err = 0; 421334f485dSMiklos Szeredi if (req) { 422334f485dSMiklos Szeredi spin_lock(&fuse_lock); 423334f485dSMiklos Szeredi if (req->interrupted) 424334f485dSMiklos Szeredi err = -ENOENT; 425334f485dSMiklos Szeredi else 426334f485dSMiklos Szeredi req->locked = 1; 427334f485dSMiklos Szeredi spin_unlock(&fuse_lock); 428334f485dSMiklos Szeredi } 429334f485dSMiklos Szeredi return err; 430334f485dSMiklos Szeredi } 431334f485dSMiklos Szeredi 432334f485dSMiklos Szeredi /* 433334f485dSMiklos Szeredi * Unlock request. If it was interrupted during being locked, the 434334f485dSMiklos Szeredi * requester thread is currently waiting for it to be unlocked, so 435334f485dSMiklos Szeredi * wake it up. 436334f485dSMiklos Szeredi */ 437334f485dSMiklos Szeredi static inline void unlock_request(struct fuse_req *req) 438334f485dSMiklos Szeredi { 439334f485dSMiklos Szeredi if (req) { 440334f485dSMiklos Szeredi spin_lock(&fuse_lock); 441334f485dSMiklos Szeredi req->locked = 0; 442334f485dSMiklos Szeredi if (req->interrupted) 443334f485dSMiklos Szeredi wake_up(&req->waitq); 444334f485dSMiklos Szeredi spin_unlock(&fuse_lock); 445334f485dSMiklos Szeredi } 446334f485dSMiklos Szeredi } 447334f485dSMiklos Szeredi 448334f485dSMiklos Szeredi struct fuse_copy_state { 449334f485dSMiklos Szeredi int write; 450334f485dSMiklos Szeredi struct fuse_req *req; 451334f485dSMiklos Szeredi const struct iovec *iov; 452334f485dSMiklos Szeredi unsigned long nr_segs; 453334f485dSMiklos Szeredi unsigned long seglen; 454334f485dSMiklos Szeredi unsigned long addr; 455334f485dSMiklos Szeredi struct page *pg; 456334f485dSMiklos Szeredi void *mapaddr; 457334f485dSMiklos Szeredi void *buf; 458334f485dSMiklos Szeredi unsigned len; 459334f485dSMiklos Szeredi }; 460334f485dSMiklos Szeredi 461334f485dSMiklos Szeredi static void fuse_copy_init(struct fuse_copy_state *cs, int write, 462334f485dSMiklos Szeredi struct fuse_req *req, const struct iovec *iov, 463334f485dSMiklos Szeredi unsigned long nr_segs) 464334f485dSMiklos Szeredi { 465334f485dSMiklos Szeredi memset(cs, 0, sizeof(*cs)); 466334f485dSMiklos Szeredi cs->write = write; 467334f485dSMiklos Szeredi cs->req = req; 468334f485dSMiklos Szeredi cs->iov = iov; 469334f485dSMiklos Szeredi cs->nr_segs = nr_segs; 470334f485dSMiklos Szeredi } 471334f485dSMiklos Szeredi 472334f485dSMiklos Szeredi /* Unmap and put previous page of userspace buffer */ 473334f485dSMiklos Szeredi static inline void fuse_copy_finish(struct fuse_copy_state *cs) 474334f485dSMiklos Szeredi { 475334f485dSMiklos Szeredi if (cs->mapaddr) { 476334f485dSMiklos Szeredi kunmap_atomic(cs->mapaddr, KM_USER0); 477334f485dSMiklos Szeredi if (cs->write) { 478334f485dSMiklos Szeredi flush_dcache_page(cs->pg); 479334f485dSMiklos Szeredi set_page_dirty_lock(cs->pg); 480334f485dSMiklos Szeredi } 481334f485dSMiklos Szeredi put_page(cs->pg); 482334f485dSMiklos Szeredi cs->mapaddr = NULL; 483334f485dSMiklos Szeredi } 484334f485dSMiklos Szeredi } 485334f485dSMiklos Szeredi 486334f485dSMiklos Szeredi /* 487334f485dSMiklos Szeredi * Get another pagefull of userspace buffer, and map it to kernel 488334f485dSMiklos Szeredi * address space, and lock request 489334f485dSMiklos Szeredi */ 490334f485dSMiklos Szeredi static int fuse_copy_fill(struct fuse_copy_state *cs) 491334f485dSMiklos Szeredi { 492334f485dSMiklos Szeredi unsigned long offset; 493334f485dSMiklos Szeredi int err; 494334f485dSMiklos Szeredi 495334f485dSMiklos Szeredi unlock_request(cs->req); 496334f485dSMiklos Szeredi fuse_copy_finish(cs); 497334f485dSMiklos Szeredi if (!cs->seglen) { 498334f485dSMiklos Szeredi BUG_ON(!cs->nr_segs); 499334f485dSMiklos Szeredi cs->seglen = cs->iov[0].iov_len; 500334f485dSMiklos Szeredi cs->addr = (unsigned long) cs->iov[0].iov_base; 501334f485dSMiklos Szeredi cs->iov ++; 502334f485dSMiklos Szeredi cs->nr_segs --; 503334f485dSMiklos Szeredi } 504334f485dSMiklos Szeredi down_read(¤t->mm->mmap_sem); 505334f485dSMiklos Szeredi err = get_user_pages(current, current->mm, cs->addr, 1, cs->write, 0, 506334f485dSMiklos Szeredi &cs->pg, NULL); 507334f485dSMiklos Szeredi up_read(¤t->mm->mmap_sem); 508334f485dSMiklos Szeredi if (err < 0) 509334f485dSMiklos Szeredi return err; 510334f485dSMiklos Szeredi BUG_ON(err != 1); 511334f485dSMiklos Szeredi offset = cs->addr % PAGE_SIZE; 512334f485dSMiklos Szeredi cs->mapaddr = kmap_atomic(cs->pg, KM_USER0); 513334f485dSMiklos Szeredi cs->buf = cs->mapaddr + offset; 514334f485dSMiklos Szeredi cs->len = min(PAGE_SIZE - offset, cs->seglen); 515334f485dSMiklos Szeredi cs->seglen -= cs->len; 516334f485dSMiklos Szeredi cs->addr += cs->len; 517334f485dSMiklos Szeredi 518334f485dSMiklos Szeredi return lock_request(cs->req); 519334f485dSMiklos Szeredi } 520334f485dSMiklos Szeredi 521334f485dSMiklos Szeredi /* Do as much copy to/from userspace buffer as we can */ 522334f485dSMiklos Szeredi static inline int fuse_copy_do(struct fuse_copy_state *cs, void **val, 523334f485dSMiklos Szeredi unsigned *size) 524334f485dSMiklos Szeredi { 525334f485dSMiklos Szeredi unsigned ncpy = min(*size, cs->len); 526334f485dSMiklos Szeredi if (val) { 527334f485dSMiklos Szeredi if (cs->write) 528334f485dSMiklos Szeredi memcpy(cs->buf, *val, ncpy); 529334f485dSMiklos Szeredi else 530334f485dSMiklos Szeredi memcpy(*val, cs->buf, ncpy); 531334f485dSMiklos Szeredi *val += ncpy; 532334f485dSMiklos Szeredi } 533334f485dSMiklos Szeredi *size -= ncpy; 534334f485dSMiklos Szeredi cs->len -= ncpy; 535334f485dSMiklos Szeredi cs->buf += ncpy; 536334f485dSMiklos Szeredi return ncpy; 537334f485dSMiklos Szeredi } 538334f485dSMiklos Szeredi 539334f485dSMiklos Szeredi /* 540334f485dSMiklos Szeredi * Copy a page in the request to/from the userspace buffer. Must be 541334f485dSMiklos Szeredi * done atomically 542334f485dSMiklos Szeredi */ 543334f485dSMiklos Szeredi static inline int fuse_copy_page(struct fuse_copy_state *cs, struct page *page, 544334f485dSMiklos Szeredi unsigned offset, unsigned count, int zeroing) 545334f485dSMiklos Szeredi { 546334f485dSMiklos Szeredi if (page && zeroing && count < PAGE_SIZE) { 547334f485dSMiklos Szeredi void *mapaddr = kmap_atomic(page, KM_USER1); 548334f485dSMiklos Szeredi memset(mapaddr, 0, PAGE_SIZE); 549334f485dSMiklos Szeredi kunmap_atomic(mapaddr, KM_USER1); 550334f485dSMiklos Szeredi } 551334f485dSMiklos Szeredi while (count) { 552334f485dSMiklos Szeredi int err; 553334f485dSMiklos Szeredi if (!cs->len && (err = fuse_copy_fill(cs))) 554334f485dSMiklos Szeredi return err; 555334f485dSMiklos Szeredi if (page) { 556334f485dSMiklos Szeredi void *mapaddr = kmap_atomic(page, KM_USER1); 557334f485dSMiklos Szeredi void *buf = mapaddr + offset; 558334f485dSMiklos Szeredi offset += fuse_copy_do(cs, &buf, &count); 559334f485dSMiklos Szeredi kunmap_atomic(mapaddr, KM_USER1); 560334f485dSMiklos Szeredi } else 561334f485dSMiklos Szeredi offset += fuse_copy_do(cs, NULL, &count); 562334f485dSMiklos Szeredi } 563334f485dSMiklos Szeredi if (page && !cs->write) 564334f485dSMiklos Szeredi flush_dcache_page(page); 565334f485dSMiklos Szeredi return 0; 566334f485dSMiklos Szeredi } 567334f485dSMiklos Szeredi 568334f485dSMiklos Szeredi /* Copy pages in the request to/from userspace buffer */ 569334f485dSMiklos Szeredi static int fuse_copy_pages(struct fuse_copy_state *cs, unsigned nbytes, 570334f485dSMiklos Szeredi int zeroing) 571334f485dSMiklos Szeredi { 572334f485dSMiklos Szeredi unsigned i; 573334f485dSMiklos Szeredi struct fuse_req *req = cs->req; 574334f485dSMiklos Szeredi unsigned offset = req->page_offset; 575334f485dSMiklos Szeredi unsigned count = min(nbytes, (unsigned) PAGE_SIZE - offset); 576334f485dSMiklos Szeredi 577334f485dSMiklos Szeredi for (i = 0; i < req->num_pages && (nbytes || zeroing); i++) { 578334f485dSMiklos Szeredi struct page *page = req->pages[i]; 579334f485dSMiklos Szeredi int err = fuse_copy_page(cs, page, offset, count, zeroing); 580334f485dSMiklos Szeredi if (err) 581334f485dSMiklos Szeredi return err; 582334f485dSMiklos Szeredi 583334f485dSMiklos Szeredi nbytes -= count; 584334f485dSMiklos Szeredi count = min(nbytes, (unsigned) PAGE_SIZE); 585334f485dSMiklos Szeredi offset = 0; 586334f485dSMiklos Szeredi } 587334f485dSMiklos Szeredi return 0; 588334f485dSMiklos Szeredi } 589334f485dSMiklos Szeredi 590334f485dSMiklos Szeredi /* Copy a single argument in the request to/from userspace buffer */ 591334f485dSMiklos Szeredi static int fuse_copy_one(struct fuse_copy_state *cs, void *val, unsigned size) 592334f485dSMiklos Szeredi { 593334f485dSMiklos Szeredi while (size) { 594334f485dSMiklos Szeredi int err; 595334f485dSMiklos Szeredi if (!cs->len && (err = fuse_copy_fill(cs))) 596334f485dSMiklos Szeredi return err; 597334f485dSMiklos Szeredi fuse_copy_do(cs, &val, &size); 598334f485dSMiklos Szeredi } 599334f485dSMiklos Szeredi return 0; 600334f485dSMiklos Szeredi } 601334f485dSMiklos Szeredi 602334f485dSMiklos Szeredi /* Copy request arguments to/from userspace buffer */ 603334f485dSMiklos Szeredi static int fuse_copy_args(struct fuse_copy_state *cs, unsigned numargs, 604334f485dSMiklos Szeredi unsigned argpages, struct fuse_arg *args, 605334f485dSMiklos Szeredi int zeroing) 606334f485dSMiklos Szeredi { 607334f485dSMiklos Szeredi int err = 0; 608334f485dSMiklos Szeredi unsigned i; 609334f485dSMiklos Szeredi 610334f485dSMiklos Szeredi for (i = 0; !err && i < numargs; i++) { 611334f485dSMiklos Szeredi struct fuse_arg *arg = &args[i]; 612334f485dSMiklos Szeredi if (i == numargs - 1 && argpages) 613334f485dSMiklos Szeredi err = fuse_copy_pages(cs, arg->size, zeroing); 614334f485dSMiklos Szeredi else 615334f485dSMiklos Szeredi err = fuse_copy_one(cs, arg->value, arg->size); 616334f485dSMiklos Szeredi } 617334f485dSMiklos Szeredi return err; 618334f485dSMiklos Szeredi } 619334f485dSMiklos Szeredi 620334f485dSMiklos Szeredi /* Wait until a request is available on the pending list */ 621334f485dSMiklos Szeredi static void request_wait(struct fuse_conn *fc) 622334f485dSMiklos Szeredi { 623334f485dSMiklos Szeredi DECLARE_WAITQUEUE(wait, current); 624334f485dSMiklos Szeredi 625334f485dSMiklos Szeredi add_wait_queue_exclusive(&fc->waitq, &wait); 626*1e9a4ed9SMiklos Szeredi while (fc->mounted && list_empty(&fc->pending)) { 627334f485dSMiklos Szeredi set_current_state(TASK_INTERRUPTIBLE); 628334f485dSMiklos Szeredi if (signal_pending(current)) 629334f485dSMiklos Szeredi break; 630334f485dSMiklos Szeredi 631334f485dSMiklos Szeredi spin_unlock(&fuse_lock); 632334f485dSMiklos Szeredi schedule(); 633334f485dSMiklos Szeredi spin_lock(&fuse_lock); 634334f485dSMiklos Szeredi } 635334f485dSMiklos Szeredi set_current_state(TASK_RUNNING); 636334f485dSMiklos Szeredi remove_wait_queue(&fc->waitq, &wait); 637334f485dSMiklos Szeredi } 638334f485dSMiklos Szeredi 639334f485dSMiklos Szeredi /* 640334f485dSMiklos Szeredi * Read a single request into the userspace filesystem's buffer. This 641334f485dSMiklos Szeredi * function waits until a request is available, then removes it from 642334f485dSMiklos Szeredi * the pending list and copies request data to userspace buffer. If 643334f485dSMiklos Szeredi * no reply is needed (FORGET) or request has been interrupted or 644334f485dSMiklos Szeredi * there was an error during the copying then it's finished by calling 645334f485dSMiklos Szeredi * request_end(). Otherwise add it to the processing list, and set 646334f485dSMiklos Szeredi * the 'sent' flag. 647334f485dSMiklos Szeredi */ 648334f485dSMiklos Szeredi static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov, 649334f485dSMiklos Szeredi unsigned long nr_segs, loff_t *off) 650334f485dSMiklos Szeredi { 651334f485dSMiklos Szeredi int err; 652334f485dSMiklos Szeredi struct fuse_conn *fc; 653334f485dSMiklos Szeredi struct fuse_req *req; 654334f485dSMiklos Szeredi struct fuse_in *in; 655334f485dSMiklos Szeredi struct fuse_copy_state cs; 656334f485dSMiklos Szeredi unsigned reqsize; 657334f485dSMiklos Szeredi 658334f485dSMiklos Szeredi spin_lock(&fuse_lock); 659334f485dSMiklos Szeredi fc = file->private_data; 660334f485dSMiklos Szeredi err = -EPERM; 661334f485dSMiklos Szeredi if (!fc) 662334f485dSMiklos Szeredi goto err_unlock; 663334f485dSMiklos Szeredi request_wait(fc); 664334f485dSMiklos Szeredi err = -ENODEV; 665*1e9a4ed9SMiklos Szeredi if (!fc->mounted) 666334f485dSMiklos Szeredi goto err_unlock; 667334f485dSMiklos Szeredi err = -ERESTARTSYS; 668334f485dSMiklos Szeredi if (list_empty(&fc->pending)) 669334f485dSMiklos Szeredi goto err_unlock; 670334f485dSMiklos Szeredi 671334f485dSMiklos Szeredi req = list_entry(fc->pending.next, struct fuse_req, list); 672334f485dSMiklos Szeredi list_del_init(&req->list); 673334f485dSMiklos Szeredi spin_unlock(&fuse_lock); 674334f485dSMiklos Szeredi 675334f485dSMiklos Szeredi in = &req->in; 676334f485dSMiklos Szeredi reqsize = req->in.h.len; 677334f485dSMiklos Szeredi fuse_copy_init(&cs, 1, req, iov, nr_segs); 678334f485dSMiklos Szeredi err = -EINVAL; 679334f485dSMiklos Szeredi if (iov_length(iov, nr_segs) >= reqsize) { 680334f485dSMiklos Szeredi err = fuse_copy_one(&cs, &in->h, sizeof(in->h)); 681334f485dSMiklos Szeredi if (!err) 682334f485dSMiklos Szeredi err = fuse_copy_args(&cs, in->numargs, in->argpages, 683334f485dSMiklos Szeredi (struct fuse_arg *) in->args, 0); 684334f485dSMiklos Szeredi } 685334f485dSMiklos Szeredi fuse_copy_finish(&cs); 686334f485dSMiklos Szeredi 687334f485dSMiklos Szeredi spin_lock(&fuse_lock); 688334f485dSMiklos Szeredi req->locked = 0; 689334f485dSMiklos Szeredi if (!err && req->interrupted) 690334f485dSMiklos Szeredi err = -ENOENT; 691334f485dSMiklos Szeredi if (err) { 692334f485dSMiklos Szeredi if (!req->interrupted) 693334f485dSMiklos Szeredi req->out.h.error = -EIO; 694334f485dSMiklos Szeredi request_end(fc, req); 695334f485dSMiklos Szeredi return err; 696334f485dSMiklos Szeredi } 697334f485dSMiklos Szeredi if (!req->isreply) 698334f485dSMiklos Szeredi request_end(fc, req); 699334f485dSMiklos Szeredi else { 700334f485dSMiklos Szeredi req->sent = 1; 701334f485dSMiklos Szeredi list_add_tail(&req->list, &fc->processing); 702334f485dSMiklos Szeredi spin_unlock(&fuse_lock); 703334f485dSMiklos Szeredi } 704334f485dSMiklos Szeredi return reqsize; 705334f485dSMiklos Szeredi 706334f485dSMiklos Szeredi err_unlock: 707334f485dSMiklos Szeredi spin_unlock(&fuse_lock); 708334f485dSMiklos Szeredi return err; 709334f485dSMiklos Szeredi } 710334f485dSMiklos Szeredi 711334f485dSMiklos Szeredi static ssize_t fuse_dev_read(struct file *file, char __user *buf, 712334f485dSMiklos Szeredi size_t nbytes, loff_t *off) 713334f485dSMiklos Szeredi { 714334f485dSMiklos Szeredi struct iovec iov; 715334f485dSMiklos Szeredi iov.iov_len = nbytes; 716334f485dSMiklos Szeredi iov.iov_base = buf; 717334f485dSMiklos Szeredi return fuse_dev_readv(file, &iov, 1, off); 718334f485dSMiklos Szeredi } 719334f485dSMiklos Szeredi 720334f485dSMiklos Szeredi /* Look up request on processing list by unique ID */ 721334f485dSMiklos Szeredi static struct fuse_req *request_find(struct fuse_conn *fc, u64 unique) 722334f485dSMiklos Szeredi { 723334f485dSMiklos Szeredi struct list_head *entry; 724334f485dSMiklos Szeredi 725334f485dSMiklos Szeredi list_for_each(entry, &fc->processing) { 726334f485dSMiklos Szeredi struct fuse_req *req; 727334f485dSMiklos Szeredi req = list_entry(entry, struct fuse_req, list); 728334f485dSMiklos Szeredi if (req->in.h.unique == unique) 729334f485dSMiklos Szeredi return req; 730334f485dSMiklos Szeredi } 731334f485dSMiklos Szeredi return NULL; 732334f485dSMiklos Szeredi } 733334f485dSMiklos Szeredi 734e5e5558eSMiklos Szeredi /* fget() needs to be done in this context */ 735e5e5558eSMiklos Szeredi static void process_getdir(struct fuse_req *req) 736e5e5558eSMiklos Szeredi { 737e5e5558eSMiklos Szeredi struct fuse_getdir_out_i *arg = req->out.args[0].value; 738e5e5558eSMiklos Szeredi arg->file = fget(arg->fd); 739e5e5558eSMiklos Szeredi } 740e5e5558eSMiklos Szeredi 741334f485dSMiklos Szeredi static int copy_out_args(struct fuse_copy_state *cs, struct fuse_out *out, 742334f485dSMiklos Szeredi unsigned nbytes) 743334f485dSMiklos Szeredi { 744334f485dSMiklos Szeredi unsigned reqsize = sizeof(struct fuse_out_header); 745334f485dSMiklos Szeredi 746334f485dSMiklos Szeredi if (out->h.error) 747334f485dSMiklos Szeredi return nbytes != reqsize ? -EINVAL : 0; 748334f485dSMiklos Szeredi 749334f485dSMiklos Szeredi reqsize += len_args(out->numargs, out->args); 750334f485dSMiklos Szeredi 751334f485dSMiklos Szeredi if (reqsize < nbytes || (reqsize > nbytes && !out->argvar)) 752334f485dSMiklos Szeredi return -EINVAL; 753334f485dSMiklos Szeredi else if (reqsize > nbytes) { 754334f485dSMiklos Szeredi struct fuse_arg *lastarg = &out->args[out->numargs-1]; 755334f485dSMiklos Szeredi unsigned diffsize = reqsize - nbytes; 756334f485dSMiklos Szeredi if (diffsize > lastarg->size) 757334f485dSMiklos Szeredi return -EINVAL; 758334f485dSMiklos Szeredi lastarg->size -= diffsize; 759334f485dSMiklos Szeredi } 760334f485dSMiklos Szeredi return fuse_copy_args(cs, out->numargs, out->argpages, out->args, 761334f485dSMiklos Szeredi out->page_zeroing); 762334f485dSMiklos Szeredi } 763334f485dSMiklos Szeredi 764334f485dSMiklos Szeredi /* 765334f485dSMiklos Szeredi * Write a single reply to a request. First the header is copied from 766334f485dSMiklos Szeredi * the write buffer. The request is then searched on the processing 767334f485dSMiklos Szeredi * list by the unique ID found in the header. If found, then remove 768334f485dSMiklos Szeredi * it from the list and copy the rest of the buffer to the request. 769334f485dSMiklos Szeredi * The request is finished by calling request_end() 770334f485dSMiklos Szeredi */ 771334f485dSMiklos Szeredi static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov, 772334f485dSMiklos Szeredi unsigned long nr_segs, loff_t *off) 773334f485dSMiklos Szeredi { 774334f485dSMiklos Szeredi int err; 775334f485dSMiklos Szeredi unsigned nbytes = iov_length(iov, nr_segs); 776334f485dSMiklos Szeredi struct fuse_req *req; 777334f485dSMiklos Szeredi struct fuse_out_header oh; 778334f485dSMiklos Szeredi struct fuse_copy_state cs; 779334f485dSMiklos Szeredi struct fuse_conn *fc = fuse_get_conn(file); 780334f485dSMiklos Szeredi if (!fc) 781334f485dSMiklos Szeredi return -ENODEV; 782334f485dSMiklos Szeredi 783334f485dSMiklos Szeredi fuse_copy_init(&cs, 0, NULL, iov, nr_segs); 784334f485dSMiklos Szeredi if (nbytes < sizeof(struct fuse_out_header)) 785334f485dSMiklos Szeredi return -EINVAL; 786334f485dSMiklos Szeredi 787334f485dSMiklos Szeredi err = fuse_copy_one(&cs, &oh, sizeof(oh)); 788334f485dSMiklos Szeredi if (err) 789334f485dSMiklos Szeredi goto err_finish; 790334f485dSMiklos Szeredi err = -EINVAL; 791334f485dSMiklos Szeredi if (!oh.unique || oh.error <= -1000 || oh.error > 0 || 792334f485dSMiklos Szeredi oh.len != nbytes) 793334f485dSMiklos Szeredi goto err_finish; 794334f485dSMiklos Szeredi 795334f485dSMiklos Szeredi spin_lock(&fuse_lock); 796334f485dSMiklos Szeredi req = request_find(fc, oh.unique); 797334f485dSMiklos Szeredi err = -EINVAL; 798334f485dSMiklos Szeredi if (!req) 799334f485dSMiklos Szeredi goto err_unlock; 800334f485dSMiklos Szeredi 801334f485dSMiklos Szeredi list_del_init(&req->list); 802334f485dSMiklos Szeredi if (req->interrupted) { 803334f485dSMiklos Szeredi request_end(fc, req); 804334f485dSMiklos Szeredi fuse_copy_finish(&cs); 805334f485dSMiklos Szeredi return -ENOENT; 806334f485dSMiklos Szeredi } 807334f485dSMiklos Szeredi req->out.h = oh; 808334f485dSMiklos Szeredi req->locked = 1; 809334f485dSMiklos Szeredi cs.req = req; 810334f485dSMiklos Szeredi spin_unlock(&fuse_lock); 811334f485dSMiklos Szeredi 812334f485dSMiklos Szeredi err = copy_out_args(&cs, &req->out, nbytes); 813334f485dSMiklos Szeredi fuse_copy_finish(&cs); 814334f485dSMiklos Szeredi 815334f485dSMiklos Szeredi spin_lock(&fuse_lock); 816334f485dSMiklos Szeredi req->locked = 0; 817334f485dSMiklos Szeredi if (!err) { 818334f485dSMiklos Szeredi if (req->interrupted) 819334f485dSMiklos Szeredi err = -ENOENT; 820e5e5558eSMiklos Szeredi else if (req->in.h.opcode == FUSE_GETDIR && !oh.error) 821e5e5558eSMiklos Szeredi process_getdir(req); 822334f485dSMiklos Szeredi } else if (!req->interrupted) 823334f485dSMiklos Szeredi req->out.h.error = -EIO; 824334f485dSMiklos Szeredi request_end(fc, req); 825334f485dSMiklos Szeredi 826334f485dSMiklos Szeredi return err ? err : nbytes; 827334f485dSMiklos Szeredi 828334f485dSMiklos Szeredi err_unlock: 829334f485dSMiklos Szeredi spin_unlock(&fuse_lock); 830334f485dSMiklos Szeredi err_finish: 831334f485dSMiklos Szeredi fuse_copy_finish(&cs); 832334f485dSMiklos Szeredi return err; 833334f485dSMiklos Szeredi } 834334f485dSMiklos Szeredi 835334f485dSMiklos Szeredi static ssize_t fuse_dev_write(struct file *file, const char __user *buf, 836334f485dSMiklos Szeredi size_t nbytes, loff_t *off) 837334f485dSMiklos Szeredi { 838334f485dSMiklos Szeredi struct iovec iov; 839334f485dSMiklos Szeredi iov.iov_len = nbytes; 840334f485dSMiklos Szeredi iov.iov_base = (char __user *) buf; 841334f485dSMiklos Szeredi return fuse_dev_writev(file, &iov, 1, off); 842334f485dSMiklos Szeredi } 843334f485dSMiklos Szeredi 844334f485dSMiklos Szeredi static unsigned fuse_dev_poll(struct file *file, poll_table *wait) 845334f485dSMiklos Szeredi { 846334f485dSMiklos Szeredi struct fuse_conn *fc = fuse_get_conn(file); 847334f485dSMiklos Szeredi unsigned mask = POLLOUT | POLLWRNORM; 848334f485dSMiklos Szeredi 849334f485dSMiklos Szeredi if (!fc) 850334f485dSMiklos Szeredi return -ENODEV; 851334f485dSMiklos Szeredi 852334f485dSMiklos Szeredi poll_wait(file, &fc->waitq, wait); 853334f485dSMiklos Szeredi 854334f485dSMiklos Szeredi spin_lock(&fuse_lock); 855334f485dSMiklos Szeredi if (!list_empty(&fc->pending)) 856334f485dSMiklos Szeredi mask |= POLLIN | POLLRDNORM; 857334f485dSMiklos Szeredi spin_unlock(&fuse_lock); 858334f485dSMiklos Szeredi 859334f485dSMiklos Szeredi return mask; 860334f485dSMiklos Szeredi } 861334f485dSMiklos Szeredi 862334f485dSMiklos Szeredi /* Abort all requests on the given list (pending or processing) */ 863334f485dSMiklos Szeredi static void end_requests(struct fuse_conn *fc, struct list_head *head) 864334f485dSMiklos Szeredi { 865334f485dSMiklos Szeredi while (!list_empty(head)) { 866334f485dSMiklos Szeredi struct fuse_req *req; 867334f485dSMiklos Szeredi req = list_entry(head->next, struct fuse_req, list); 868334f485dSMiklos Szeredi list_del_init(&req->list); 869334f485dSMiklos Szeredi req->out.h.error = -ECONNABORTED; 870334f485dSMiklos Szeredi request_end(fc, req); 871334f485dSMiklos Szeredi spin_lock(&fuse_lock); 872334f485dSMiklos Szeredi } 873334f485dSMiklos Szeredi } 874334f485dSMiklos Szeredi 875334f485dSMiklos Szeredi static int fuse_dev_release(struct inode *inode, struct file *file) 876334f485dSMiklos Szeredi { 877334f485dSMiklos Szeredi struct fuse_conn *fc; 878334f485dSMiklos Szeredi 879334f485dSMiklos Szeredi spin_lock(&fuse_lock); 880334f485dSMiklos Szeredi fc = file->private_data; 881334f485dSMiklos Szeredi if (fc) { 882*1e9a4ed9SMiklos Szeredi fc->connected = 0; 883334f485dSMiklos Szeredi end_requests(fc, &fc->pending); 884334f485dSMiklos Szeredi end_requests(fc, &fc->processing); 885334f485dSMiklos Szeredi fuse_release_conn(fc); 886334f485dSMiklos Szeredi } 887334f485dSMiklos Szeredi spin_unlock(&fuse_lock); 888334f485dSMiklos Szeredi return 0; 889334f485dSMiklos Szeredi } 890334f485dSMiklos Szeredi 891334f485dSMiklos Szeredi struct file_operations fuse_dev_operations = { 892334f485dSMiklos Szeredi .owner = THIS_MODULE, 893334f485dSMiklos Szeredi .llseek = no_llseek, 894334f485dSMiklos Szeredi .read = fuse_dev_read, 895334f485dSMiklos Szeredi .readv = fuse_dev_readv, 896334f485dSMiklos Szeredi .write = fuse_dev_write, 897334f485dSMiklos Szeredi .writev = fuse_dev_writev, 898334f485dSMiklos Szeredi .poll = fuse_dev_poll, 899334f485dSMiklos Szeredi .release = fuse_dev_release, 900334f485dSMiklos Szeredi }; 901334f485dSMiklos Szeredi 902334f485dSMiklos Szeredi static struct miscdevice fuse_miscdevice = { 903334f485dSMiklos Szeredi .minor = FUSE_MINOR, 904334f485dSMiklos Szeredi .name = "fuse", 905334f485dSMiklos Szeredi .fops = &fuse_dev_operations, 906334f485dSMiklos Szeredi }; 907334f485dSMiklos Szeredi 908334f485dSMiklos Szeredi int __init fuse_dev_init(void) 909334f485dSMiklos Szeredi { 910334f485dSMiklos Szeredi int err = -ENOMEM; 911334f485dSMiklos Szeredi fuse_req_cachep = kmem_cache_create("fuse_request", 912334f485dSMiklos Szeredi sizeof(struct fuse_req), 913334f485dSMiklos Szeredi 0, 0, NULL, NULL); 914334f485dSMiklos Szeredi if (!fuse_req_cachep) 915334f485dSMiklos Szeredi goto out; 916334f485dSMiklos Szeredi 917334f485dSMiklos Szeredi err = misc_register(&fuse_miscdevice); 918334f485dSMiklos Szeredi if (err) 919334f485dSMiklos Szeredi goto out_cache_clean; 920334f485dSMiklos Szeredi 921334f485dSMiklos Szeredi return 0; 922334f485dSMiklos Szeredi 923334f485dSMiklos Szeredi out_cache_clean: 924334f485dSMiklos Szeredi kmem_cache_destroy(fuse_req_cachep); 925334f485dSMiklos Szeredi out: 926334f485dSMiklos Szeredi return err; 927334f485dSMiklos Szeredi } 928334f485dSMiklos Szeredi 929334f485dSMiklos Szeredi void fuse_dev_cleanup(void) 930334f485dSMiklos Szeredi { 931334f485dSMiklos Szeredi misc_deregister(&fuse_miscdevice); 932334f485dSMiklos Szeredi kmem_cache_destroy(fuse_req_cachep); 933334f485dSMiklos Szeredi } 934