aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse/dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/fuse/dev.c')
-rw-r--r--fs/fuse/dev.c86
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
254void 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
254static void flush_bg_queue(struct fuse_conn *fc) 268static 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
441void 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
447void fuse_request_send_background(struct fuse_conn *fc, struct fuse_req *req) 455void 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
907static int forget_pending(struct fuse_conn *fc)
908{
909 return fc->forget_list_head.next != NULL;
910}
911
899static int request_pending(struct fuse_conn *fc) 912static 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
977static 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
988static 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/*