diff options
Diffstat (limited to 'fs/fuse/dev.c')
-rw-r--r-- | fs/fuse/dev.c | 86 |
1 files changed, 77 insertions, 9 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 6e07696308dc..fed65303eeeb 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
@@ -251,6 +251,20 @@ static void queue_request(struct fuse_conn *fc, struct fuse_req *req) | |||
251 | kill_fasync(&fc->fasync, SIGIO, POLL_IN); | 251 | kill_fasync(&fc->fasync, SIGIO, POLL_IN); |
252 | } | 252 | } |
253 | 253 | ||
254 | void fuse_queue_forget(struct fuse_conn *fc, struct fuse_forget_link *forget, | ||
255 | u64 nodeid, u64 nlookup) | ||
256 | { | ||
257 | forget->nodeid = nodeid; | ||
258 | forget->nlookup = nlookup; | ||
259 | |||
260 | spin_lock(&fc->lock); | ||
261 | fc->forget_list_tail->next = forget; | ||
262 | fc->forget_list_tail = forget; | ||
263 | wake_up(&fc->waitq); | ||
264 | kill_fasync(&fc->fasync, SIGIO, POLL_IN); | ||
265 | spin_unlock(&fc->lock); | ||
266 | } | ||
267 | |||
254 | static void flush_bg_queue(struct fuse_conn *fc) | 268 | static void flush_bg_queue(struct fuse_conn *fc) |
255 | { | 269 | { |
256 | while (fc->active_background < fc->max_background && | 270 | while (fc->active_background < fc->max_background && |
@@ -438,12 +452,6 @@ static void fuse_request_send_nowait(struct fuse_conn *fc, struct fuse_req *req) | |||
438 | } | 452 | } |
439 | } | 453 | } |
440 | 454 | ||
441 | void fuse_request_send_noreply(struct fuse_conn *fc, struct fuse_req *req) | ||
442 | { | ||
443 | req->isreply = 0; | ||
444 | fuse_request_send_nowait(fc, req); | ||
445 | } | ||
446 | |||
447 | void fuse_request_send_background(struct fuse_conn *fc, struct fuse_req *req) | 455 | void fuse_request_send_background(struct fuse_conn *fc, struct fuse_req *req) |
448 | { | 456 | { |
449 | req->isreply = 1; | 457 | req->isreply = 1; |
@@ -896,9 +904,15 @@ static int fuse_copy_args(struct fuse_copy_state *cs, unsigned numargs, | |||
896 | return err; | 904 | return err; |
897 | } | 905 | } |
898 | 906 | ||
907 | static int forget_pending(struct fuse_conn *fc) | ||
908 | { | ||
909 | return fc->forget_list_head.next != NULL; | ||
910 | } | ||
911 | |||
899 | static int request_pending(struct fuse_conn *fc) | 912 | static int request_pending(struct fuse_conn *fc) |
900 | { | 913 | { |
901 | return !list_empty(&fc->pending) || !list_empty(&fc->interrupts); | 914 | return !list_empty(&fc->pending) || !list_empty(&fc->interrupts) || |
915 | forget_pending(fc); | ||
902 | } | 916 | } |
903 | 917 | ||
904 | /* Wait until a request is available on the pending list */ | 918 | /* Wait until a request is available on the pending list */ |
@@ -960,6 +974,50 @@ __releases(fc->lock) | |||
960 | return err ? err : reqsize; | 974 | return err ? err : reqsize; |
961 | } | 975 | } |
962 | 976 | ||
977 | static struct fuse_forget_link *dequeue_forget(struct fuse_conn *fc) | ||
978 | { | ||
979 | struct fuse_forget_link *forget = fc->forget_list_head.next; | ||
980 | |||
981 | fc->forget_list_head.next = forget->next; | ||
982 | if (fc->forget_list_head.next == NULL) | ||
983 | fc->forget_list_tail = &fc->forget_list_head; | ||
984 | |||
985 | return forget; | ||
986 | } | ||
987 | |||
988 | static int fuse_read_single_forget(struct fuse_conn *fc, | ||
989 | struct fuse_copy_state *cs, | ||
990 | size_t nbytes) | ||
991 | __releases(fc->lock) | ||
992 | { | ||
993 | int err; | ||
994 | struct fuse_forget_link *forget = dequeue_forget(fc); | ||
995 | struct fuse_forget_in arg = { | ||
996 | .nlookup = forget->nlookup, | ||
997 | }; | ||
998 | struct fuse_in_header ih = { | ||
999 | .opcode = FUSE_FORGET, | ||
1000 | .nodeid = forget->nodeid, | ||
1001 | .unique = fuse_get_unique(fc), | ||
1002 | .len = sizeof(ih) + sizeof(arg), | ||
1003 | }; | ||
1004 | |||
1005 | spin_unlock(&fc->lock); | ||
1006 | kfree(forget); | ||
1007 | if (nbytes < ih.len) | ||
1008 | return -EINVAL; | ||
1009 | |||
1010 | err = fuse_copy_one(cs, &ih, sizeof(ih)); | ||
1011 | if (!err) | ||
1012 | err = fuse_copy_one(cs, &arg, sizeof(arg)); | ||
1013 | fuse_copy_finish(cs); | ||
1014 | |||
1015 | if (err) | ||
1016 | return err; | ||
1017 | |||
1018 | return ih.len; | ||
1019 | } | ||
1020 | |||
963 | /* | 1021 | /* |
964 | * Read a single request into the userspace filesystem's buffer. This | 1022 | * Read a single request into the userspace filesystem's buffer. This |
965 | * function waits until a request is available, then removes it from | 1023 | * function waits until a request is available, then removes it from |
@@ -998,6 +1056,14 @@ static ssize_t fuse_dev_do_read(struct fuse_conn *fc, struct file *file, | |||
998 | return fuse_read_interrupt(fc, cs, nbytes, req); | 1056 | return fuse_read_interrupt(fc, cs, nbytes, req); |
999 | } | 1057 | } |
1000 | 1058 | ||
1059 | if (forget_pending(fc)) { | ||
1060 | if (list_empty(&fc->pending) || fc->forget_batch-- > 0) | ||
1061 | return fuse_read_single_forget(fc, cs, nbytes); | ||
1062 | |||
1063 | if (fc->forget_batch <= -8) | ||
1064 | fc->forget_batch = 16; | ||
1065 | } | ||
1066 | |||
1001 | req = list_entry(fc->pending.next, struct fuse_req, list); | 1067 | req = list_entry(fc->pending.next, struct fuse_req, list); |
1002 | req->state = FUSE_REQ_READING; | 1068 | req->state = FUSE_REQ_READING; |
1003 | list_move(&req->list, &fc->io); | 1069 | list_move(&req->list, &fc->io); |
@@ -1090,7 +1156,7 @@ static ssize_t fuse_dev_splice_read(struct file *in, loff_t *ppos, | |||
1090 | if (!fc) | 1156 | if (!fc) |
1091 | return -EPERM; | 1157 | return -EPERM; |
1092 | 1158 | ||
1093 | bufs = kmalloc(pipe->buffers * sizeof (struct pipe_buffer), GFP_KERNEL); | 1159 | bufs = kmalloc(pipe->buffers * sizeof(struct pipe_buffer), GFP_KERNEL); |
1094 | if (!bufs) | 1160 | if (!bufs) |
1095 | return -ENOMEM; | 1161 | return -ENOMEM; |
1096 | 1162 | ||
@@ -1626,7 +1692,7 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, | |||
1626 | if (!fc) | 1692 | if (!fc) |
1627 | return -EPERM; | 1693 | return -EPERM; |
1628 | 1694 | ||
1629 | bufs = kmalloc(pipe->buffers * sizeof (struct pipe_buffer), GFP_KERNEL); | 1695 | bufs = kmalloc(pipe->buffers * sizeof(struct pipe_buffer), GFP_KERNEL); |
1630 | if (!bufs) | 1696 | if (!bufs) |
1631 | return -ENOMEM; | 1697 | return -ENOMEM; |
1632 | 1698 | ||
@@ -1770,6 +1836,8 @@ __acquires(fc->lock) | |||
1770 | flush_bg_queue(fc); | 1836 | flush_bg_queue(fc); |
1771 | end_requests(fc, &fc->pending); | 1837 | end_requests(fc, &fc->pending); |
1772 | end_requests(fc, &fc->processing); | 1838 | end_requests(fc, &fc->processing); |
1839 | while (forget_pending(fc)) | ||
1840 | kfree(dequeue_forget(fc)); | ||
1773 | } | 1841 | } |
1774 | 1842 | ||
1775 | /* | 1843 | /* |