diff options
-rw-r--r-- | fs/fuse/dev.c | 86 | ||||
-rw-r--r-- | fs/fuse/dir.c | 53 | ||||
-rw-r--r-- | fs/fuse/fuse_i.h | 28 | ||||
-rw-r--r-- | fs/fuse/inode.c | 30 |
4 files changed, 133 insertions, 64 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 | /* |
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index c9627c95482d..6ea42e98cb17 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -10,9 +10,9 @@ | |||
10 | 10 | ||
11 | #include <linux/pagemap.h> | 11 | #include <linux/pagemap.h> |
12 | #include <linux/file.h> | 12 | #include <linux/file.h> |
13 | #include <linux/gfp.h> | ||
14 | #include <linux/sched.h> | 13 | #include <linux/sched.h> |
15 | #include <linux/namei.h> | 14 | #include <linux/namei.h> |
15 | #include <linux/slab.h> | ||
16 | 16 | ||
17 | #if BITS_PER_LONG >= 64 | 17 | #if BITS_PER_LONG >= 64 |
18 | static inline void fuse_dentry_settime(struct dentry *entry, u64 time) | 18 | static inline void fuse_dentry_settime(struct dentry *entry, u64 time) |
@@ -165,7 +165,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd) | |||
165 | struct fuse_entry_out outarg; | 165 | struct fuse_entry_out outarg; |
166 | struct fuse_conn *fc; | 166 | struct fuse_conn *fc; |
167 | struct fuse_req *req; | 167 | struct fuse_req *req; |
168 | struct fuse_req *forget_req; | 168 | struct fuse_forget_link *forget; |
169 | struct dentry *parent; | 169 | struct dentry *parent; |
170 | u64 attr_version; | 170 | u64 attr_version; |
171 | 171 | ||
@@ -178,8 +178,8 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd) | |||
178 | if (IS_ERR(req)) | 178 | if (IS_ERR(req)) |
179 | return 0; | 179 | return 0; |
180 | 180 | ||
181 | forget_req = fuse_get_req(fc); | 181 | forget = fuse_alloc_forget(); |
182 | if (IS_ERR(forget_req)) { | 182 | if (!forget) { |
183 | fuse_put_request(fc, req); | 183 | fuse_put_request(fc, req); |
184 | return 0; | 184 | return 0; |
185 | } | 185 | } |
@@ -199,15 +199,14 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd) | |||
199 | if (!err) { | 199 | if (!err) { |
200 | struct fuse_inode *fi = get_fuse_inode(inode); | 200 | struct fuse_inode *fi = get_fuse_inode(inode); |
201 | if (outarg.nodeid != get_node_id(inode)) { | 201 | if (outarg.nodeid != get_node_id(inode)) { |
202 | fuse_send_forget(fc, forget_req, | 202 | fuse_queue_forget(fc, forget, outarg.nodeid, 1); |
203 | outarg.nodeid, 1); | ||
204 | return 0; | 203 | return 0; |
205 | } | 204 | } |
206 | spin_lock(&fc->lock); | 205 | spin_lock(&fc->lock); |
207 | fi->nlookup++; | 206 | fi->nlookup++; |
208 | spin_unlock(&fc->lock); | 207 | spin_unlock(&fc->lock); |
209 | } | 208 | } |
210 | fuse_put_request(fc, forget_req); | 209 | kfree(forget); |
211 | if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT) | 210 | if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT) |
212 | return 0; | 211 | return 0; |
213 | 212 | ||
@@ -259,7 +258,7 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name, | |||
259 | { | 258 | { |
260 | struct fuse_conn *fc = get_fuse_conn_super(sb); | 259 | struct fuse_conn *fc = get_fuse_conn_super(sb); |
261 | struct fuse_req *req; | 260 | struct fuse_req *req; |
262 | struct fuse_req *forget_req; | 261 | struct fuse_forget_link *forget; |
263 | u64 attr_version; | 262 | u64 attr_version; |
264 | int err; | 263 | int err; |
265 | 264 | ||
@@ -273,9 +272,9 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name, | |||
273 | if (IS_ERR(req)) | 272 | if (IS_ERR(req)) |
274 | goto out; | 273 | goto out; |
275 | 274 | ||
276 | forget_req = fuse_get_req(fc); | 275 | forget = fuse_alloc_forget(); |
277 | err = PTR_ERR(forget_req); | 276 | err = -ENOMEM; |
278 | if (IS_ERR(forget_req)) { | 277 | if (!forget) { |
279 | fuse_put_request(fc, req); | 278 | fuse_put_request(fc, req); |
280 | goto out; | 279 | goto out; |
281 | } | 280 | } |
@@ -301,13 +300,13 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name, | |||
301 | attr_version); | 300 | attr_version); |
302 | err = -ENOMEM; | 301 | err = -ENOMEM; |
303 | if (!*inode) { | 302 | if (!*inode) { |
304 | fuse_send_forget(fc, forget_req, outarg->nodeid, 1); | 303 | fuse_queue_forget(fc, forget, outarg->nodeid, 1); |
305 | goto out; | 304 | goto out; |
306 | } | 305 | } |
307 | err = 0; | 306 | err = 0; |
308 | 307 | ||
309 | out_put_forget: | 308 | out_put_forget: |
310 | fuse_put_request(fc, forget_req); | 309 | kfree(forget); |
311 | out: | 310 | out: |
312 | return err; | 311 | return err; |
313 | } | 312 | } |
@@ -374,7 +373,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode, | |||
374 | struct inode *inode; | 373 | struct inode *inode; |
375 | struct fuse_conn *fc = get_fuse_conn(dir); | 374 | struct fuse_conn *fc = get_fuse_conn(dir); |
376 | struct fuse_req *req; | 375 | struct fuse_req *req; |
377 | struct fuse_req *forget_req; | 376 | struct fuse_forget_link *forget; |
378 | struct fuse_create_in inarg; | 377 | struct fuse_create_in inarg; |
379 | struct fuse_open_out outopen; | 378 | struct fuse_open_out outopen; |
380 | struct fuse_entry_out outentry; | 379 | struct fuse_entry_out outentry; |
@@ -388,9 +387,9 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode, | |||
388 | if (flags & O_DIRECT) | 387 | if (flags & O_DIRECT) |
389 | return -EINVAL; | 388 | return -EINVAL; |
390 | 389 | ||
391 | forget_req = fuse_get_req(fc); | 390 | forget = fuse_alloc_forget(); |
392 | if (IS_ERR(forget_req)) | 391 | if (!forget) |
393 | return PTR_ERR(forget_req); | 392 | return -ENOMEM; |
394 | 393 | ||
395 | req = fuse_get_req(fc); | 394 | req = fuse_get_req(fc); |
396 | err = PTR_ERR(req); | 395 | err = PTR_ERR(req); |
@@ -448,10 +447,10 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode, | |||
448 | if (!inode) { | 447 | if (!inode) { |
449 | flags &= ~(O_CREAT | O_EXCL | O_TRUNC); | 448 | flags &= ~(O_CREAT | O_EXCL | O_TRUNC); |
450 | fuse_sync_release(ff, flags); | 449 | fuse_sync_release(ff, flags); |
451 | fuse_send_forget(fc, forget_req, outentry.nodeid, 1); | 450 | fuse_queue_forget(fc, forget, outentry.nodeid, 1); |
452 | return -ENOMEM; | 451 | return -ENOMEM; |
453 | } | 452 | } |
454 | fuse_put_request(fc, forget_req); | 453 | kfree(forget); |
455 | d_instantiate(entry, inode); | 454 | d_instantiate(entry, inode); |
456 | fuse_change_entry_timeout(entry, &outentry); | 455 | fuse_change_entry_timeout(entry, &outentry); |
457 | fuse_invalidate_attr(dir); | 456 | fuse_invalidate_attr(dir); |
@@ -469,7 +468,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode, | |||
469 | out_put_request: | 468 | out_put_request: |
470 | fuse_put_request(fc, req); | 469 | fuse_put_request(fc, req); |
471 | out_put_forget_req: | 470 | out_put_forget_req: |
472 | fuse_put_request(fc, forget_req); | 471 | kfree(forget); |
473 | return err; | 472 | return err; |
474 | } | 473 | } |
475 | 474 | ||
@@ -483,12 +482,12 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req, | |||
483 | struct fuse_entry_out outarg; | 482 | struct fuse_entry_out outarg; |
484 | struct inode *inode; | 483 | struct inode *inode; |
485 | int err; | 484 | int err; |
486 | struct fuse_req *forget_req; | 485 | struct fuse_forget_link *forget; |
487 | 486 | ||
488 | forget_req = fuse_get_req(fc); | 487 | forget = fuse_alloc_forget(); |
489 | if (IS_ERR(forget_req)) { | 488 | if (!forget) { |
490 | fuse_put_request(fc, req); | 489 | fuse_put_request(fc, req); |
491 | return PTR_ERR(forget_req); | 490 | return -ENOMEM; |
492 | } | 491 | } |
493 | 492 | ||
494 | memset(&outarg, 0, sizeof(outarg)); | 493 | memset(&outarg, 0, sizeof(outarg)); |
@@ -515,10 +514,10 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req, | |||
515 | inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, | 514 | inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, |
516 | &outarg.attr, entry_attr_timeout(&outarg), 0); | 515 | &outarg.attr, entry_attr_timeout(&outarg), 0); |
517 | if (!inode) { | 516 | if (!inode) { |
518 | fuse_send_forget(fc, forget_req, outarg.nodeid, 1); | 517 | fuse_queue_forget(fc, forget, outarg.nodeid, 1); |
519 | return -ENOMEM; | 518 | return -ENOMEM; |
520 | } | 519 | } |
521 | fuse_put_request(fc, forget_req); | 520 | kfree(forget); |
522 | 521 | ||
523 | if (S_ISDIR(inode->i_mode)) { | 522 | if (S_ISDIR(inode->i_mode)) { |
524 | struct dentry *alias; | 523 | struct dentry *alias; |
@@ -541,7 +540,7 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req, | |||
541 | return 0; | 540 | return 0; |
542 | 541 | ||
543 | out_put_forget_req: | 542 | out_put_forget_req: |
544 | fuse_put_request(fc, forget_req); | 543 | kfree(forget); |
545 | return err; | 544 | return err; |
546 | } | 545 | } |
547 | 546 | ||
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 57d4a3a0f102..33369c63a522 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h | |||
@@ -53,6 +53,13 @@ extern struct mutex fuse_mutex; | |||
53 | extern unsigned max_user_bgreq; | 53 | extern unsigned max_user_bgreq; |
54 | extern unsigned max_user_congthresh; | 54 | extern unsigned max_user_congthresh; |
55 | 55 | ||
56 | /* One forget request */ | ||
57 | struct fuse_forget_link { | ||
58 | u64 nodeid; | ||
59 | u64 nlookup; | ||
60 | struct fuse_forget_link *next; | ||
61 | }; | ||
62 | |||
56 | /** FUSE inode */ | 63 | /** FUSE inode */ |
57 | struct fuse_inode { | 64 | struct fuse_inode { |
58 | /** Inode data */ | 65 | /** Inode data */ |
@@ -66,7 +73,7 @@ struct fuse_inode { | |||
66 | u64 nlookup; | 73 | u64 nlookup; |
67 | 74 | ||
68 | /** The request used for sending the FORGET message */ | 75 | /** The request used for sending the FORGET message */ |
69 | struct fuse_req *forget_req; | 76 | struct fuse_forget_link *forget; |
70 | 77 | ||
71 | /** Time in jiffies until the file attributes are valid */ | 78 | /** Time in jiffies until the file attributes are valid */ |
72 | u64 i_time; | 79 | u64 i_time; |
@@ -255,7 +262,6 @@ struct fuse_req { | |||
255 | 262 | ||
256 | /** Data for asynchronous requests */ | 263 | /** Data for asynchronous requests */ |
257 | union { | 264 | union { |
258 | struct fuse_forget_in forget_in; | ||
259 | struct { | 265 | struct { |
260 | struct fuse_release_in in; | 266 | struct fuse_release_in in; |
261 | struct path path; | 267 | struct path path; |
@@ -369,6 +375,13 @@ struct fuse_conn { | |||
369 | /** Pending interrupts */ | 375 | /** Pending interrupts */ |
370 | struct list_head interrupts; | 376 | struct list_head interrupts; |
371 | 377 | ||
378 | /** Queue of pending forgets */ | ||
379 | struct fuse_forget_link forget_list_head; | ||
380 | struct fuse_forget_link *forget_list_tail; | ||
381 | |||
382 | /** Batching of FORGET requests (positive indicates FORGET batch) */ | ||
383 | int forget_batch; | ||
384 | |||
372 | /** Flag indicating if connection is blocked. This will be | 385 | /** Flag indicating if connection is blocked. This will be |
373 | the case before the INIT reply is received, and if there | 386 | the case before the INIT reply is received, and if there |
374 | are too many outstading backgrounds requests */ | 387 | are too many outstading backgrounds requests */ |
@@ -543,8 +556,10 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name, | |||
543 | /** | 556 | /** |
544 | * Send FORGET command | 557 | * Send FORGET command |
545 | */ | 558 | */ |
546 | void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req, | 559 | void fuse_queue_forget(struct fuse_conn *fc, struct fuse_forget_link *forget, |
547 | u64 nodeid, u64 nlookup); | 560 | u64 nodeid, u64 nlookup); |
561 | |||
562 | struct fuse_forget_link *fuse_alloc_forget(void); | ||
548 | 563 | ||
549 | /** | 564 | /** |
550 | * Initialize READ or READDIR request | 565 | * Initialize READ or READDIR request |
@@ -656,11 +671,6 @@ void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req); | |||
656 | void fuse_request_send(struct fuse_conn *fc, struct fuse_req *req); | 671 | void fuse_request_send(struct fuse_conn *fc, struct fuse_req *req); |
657 | 672 | ||
658 | /** | 673 | /** |
659 | * Send a request with no reply | ||
660 | */ | ||
661 | void fuse_request_send_noreply(struct fuse_conn *fc, struct fuse_req *req); | ||
662 | |||
663 | /** | ||
664 | * Send a request in the background | 674 | * Send a request in the background |
665 | */ | 675 | */ |
666 | void fuse_request_send_background(struct fuse_conn *fc, struct fuse_req *req); | 676 | void fuse_request_send_background(struct fuse_conn *fc, struct fuse_req *req); |
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index cfce3ad86a92..7ba4d351da65 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
@@ -71,6 +71,11 @@ struct fuse_mount_data { | |||
71 | unsigned blksize; | 71 | unsigned blksize; |
72 | }; | 72 | }; |
73 | 73 | ||
74 | struct fuse_forget_link *fuse_alloc_forget() | ||
75 | { | ||
76 | return kzalloc(sizeof(struct fuse_forget_link), GFP_KERNEL); | ||
77 | } | ||
78 | |||
74 | static struct inode *fuse_alloc_inode(struct super_block *sb) | 79 | static struct inode *fuse_alloc_inode(struct super_block *sb) |
75 | { | 80 | { |
76 | struct inode *inode; | 81 | struct inode *inode; |
@@ -90,8 +95,8 @@ static struct inode *fuse_alloc_inode(struct super_block *sb) | |||
90 | INIT_LIST_HEAD(&fi->queued_writes); | 95 | INIT_LIST_HEAD(&fi->queued_writes); |
91 | INIT_LIST_HEAD(&fi->writepages); | 96 | INIT_LIST_HEAD(&fi->writepages); |
92 | init_waitqueue_head(&fi->page_waitq); | 97 | init_waitqueue_head(&fi->page_waitq); |
93 | fi->forget_req = fuse_request_alloc(); | 98 | fi->forget = fuse_alloc_forget(); |
94 | if (!fi->forget_req) { | 99 | if (!fi->forget) { |
95 | kmem_cache_free(fuse_inode_cachep, inode); | 100 | kmem_cache_free(fuse_inode_cachep, inode); |
96 | return NULL; | 101 | return NULL; |
97 | } | 102 | } |
@@ -104,24 +109,10 @@ static void fuse_destroy_inode(struct inode *inode) | |||
104 | struct fuse_inode *fi = get_fuse_inode(inode); | 109 | struct fuse_inode *fi = get_fuse_inode(inode); |
105 | BUG_ON(!list_empty(&fi->write_files)); | 110 | BUG_ON(!list_empty(&fi->write_files)); |
106 | BUG_ON(!list_empty(&fi->queued_writes)); | 111 | BUG_ON(!list_empty(&fi->queued_writes)); |
107 | if (fi->forget_req) | 112 | kfree(fi->forget); |
108 | fuse_request_free(fi->forget_req); | ||
109 | kmem_cache_free(fuse_inode_cachep, inode); | 113 | kmem_cache_free(fuse_inode_cachep, inode); |
110 | } | 114 | } |
111 | 115 | ||
112 | void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req, | ||
113 | u64 nodeid, u64 nlookup) | ||
114 | { | ||
115 | struct fuse_forget_in *inarg = &req->misc.forget_in; | ||
116 | inarg->nlookup = nlookup; | ||
117 | req->in.h.opcode = FUSE_FORGET; | ||
118 | req->in.h.nodeid = nodeid; | ||
119 | req->in.numargs = 1; | ||
120 | req->in.args[0].size = sizeof(struct fuse_forget_in); | ||
121 | req->in.args[0].value = inarg; | ||
122 | fuse_request_send_noreply(fc, req); | ||
123 | } | ||
124 | |||
125 | static void fuse_evict_inode(struct inode *inode) | 116 | static void fuse_evict_inode(struct inode *inode) |
126 | { | 117 | { |
127 | truncate_inode_pages(&inode->i_data, 0); | 118 | truncate_inode_pages(&inode->i_data, 0); |
@@ -129,8 +120,8 @@ static void fuse_evict_inode(struct inode *inode) | |||
129 | if (inode->i_sb->s_flags & MS_ACTIVE) { | 120 | if (inode->i_sb->s_flags & MS_ACTIVE) { |
130 | struct fuse_conn *fc = get_fuse_conn(inode); | 121 | struct fuse_conn *fc = get_fuse_conn(inode); |
131 | struct fuse_inode *fi = get_fuse_inode(inode); | 122 | struct fuse_inode *fi = get_fuse_inode(inode); |
132 | fuse_send_forget(fc, fi->forget_req, fi->nodeid, fi->nlookup); | 123 | fuse_queue_forget(fc, fi->forget, fi->nodeid, fi->nlookup); |
133 | fi->forget_req = NULL; | 124 | fi->forget = NULL; |
134 | } | 125 | } |
135 | } | 126 | } |
136 | 127 | ||
@@ -534,6 +525,7 @@ void fuse_conn_init(struct fuse_conn *fc) | |||
534 | INIT_LIST_HEAD(&fc->interrupts); | 525 | INIT_LIST_HEAD(&fc->interrupts); |
535 | INIT_LIST_HEAD(&fc->bg_queue); | 526 | INIT_LIST_HEAD(&fc->bg_queue); |
536 | INIT_LIST_HEAD(&fc->entry); | 527 | INIT_LIST_HEAD(&fc->entry); |
528 | fc->forget_list_tail = &fc->forget_list_head; | ||
537 | atomic_set(&fc->num_waiting, 0); | 529 | atomic_set(&fc->num_waiting, 0); |
538 | fc->max_background = FUSE_DEFAULT_MAX_BACKGROUND; | 530 | fc->max_background = FUSE_DEFAULT_MAX_BACKGROUND; |
539 | fc->congestion_threshold = FUSE_DEFAULT_CONGESTION_THRESHOLD; | 531 | fc->congestion_threshold = FUSE_DEFAULT_CONGESTION_THRESHOLD; |