/* * Transfer an interrupt request to userspace * * Unlike other requests this is assembled on demand, without a need * to allocate a separate fuse_req structure. * * Called with fc->lock held, releases it */ static int fuse_read_interrupt(struct fuse_conn *fc, struct fuse_req *req, const struct iovec *iov, unsigned long nr_segs) { struct fuse_copy_state cs; struct fuse_in_header ih; struct fuse_interrupt_in arg; unsigned reqsize = sizeof(ih) + sizeof(arg); int err; list_del_init(&req->intr_entry); req->intr_unique = fuse_get_unique(fc); memset(&ih, 0, sizeof(ih)); memset(&arg, 0, sizeof(arg)); ih.len = reqsize; ih.opcode = FUSE_INTERRUPT; ih.unique = req->intr_unique; arg.unique = req->in.h.unique; spin_unlock(&fc->lock); if (iov_length(iov, nr_segs) < reqsize) return -EINVAL; fuse_copy_init(&cs, fc, 1, NULL, iov, nr_segs); err = fuse_copy_one(&cs, &ih, sizeof(ih)); if (!err) err = fuse_copy_one(&cs, &arg, sizeof(arg)); fuse_copy_finish(&cs); return err ? err : reqsize; }
static void flush_bg_queue(struct fuse_conn *fc) { while (fc->active_background < fc->max_background && !list_empty(&fc->bg_queue)) { struct fuse_req *req; req = list_entry(fc->bg_queue.next, struct fuse_req, list); list_del(&req->list); fc->active_background++; req->in.h.unique = fuse_get_unique(fc); queue_request(fc, req); } }
static void queue_request(struct fuse_conn *fc, struct fuse_req *req) { req->in.h.unique = fuse_get_unique(fc); req->in.h.len = sizeof(struct fuse_in_header) + len_args(req->in.numargs, (struct fuse_arg *) req->in.args); list_add_tail(&req->list, &fc->pending); req->state = FUSE_REQ_PENDING; if (!req->waiting) { req->waiting = 1; atomic_inc(&fc->num_waiting); } wake_up(&fc->waitq); kill_fasync(&fc->fasync, SIGIO, POLL_IN); }