aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2010-12-07 14:16:56 -0500
committerMiklos Szeredi <mszeredi@suse.cz>2010-12-07 14:16:56 -0500
commit07e77dca8a1f17a724a9b7449f0ca02e70e9d057 (patch)
tree69186be641145fd997ce15e17a22598d9a264119 /fs
parent8ac835056ca39b242d98332f46e4d65428a8b7db (diff)
fuse: separate queue for FORGET requests
Terje Malmedal reports that a fuse filesystem with 32 million inodes on a machine with lots of memory can go unresponsive for up to 30 minutes when all those inodes are evicted from the icache. The reason is that FORGET messages, sent when the inode is evicted, are queued up together with regular filesystem requests, and while the huge queue of FORGET messages are processed no other filesystem operation can proceed. Since a full fuse request structure is allocated for each inode, these take up quite a bit of memory as well. To solve these issues, create a slim 'fuse_forget_link' structure containing just the minimum of information required to send the FORGET request and chain these on a separate queue. When userspace is asking for a request make sure that FORGET and non-FORGET requests are selected fairly: for each 8 non-FORGET allow 16 FORGET requests. This will make sure FORGETs do not pile up, yet other requests are also allowed to proceed while the queued FORGETs are processed. Reported-by: Terje Malmedal <terje.malmedal@usit.uio.no> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Diffstat (limited to 'fs')
-rw-r--r--fs/fuse/dev.c86
-rw-r--r--fs/fuse/dir.c53
-rw-r--r--fs/fuse/fuse_i.h28
-rw-r--r--fs/fuse/inode.c30
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
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/*
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
18static inline void fuse_dentry_settime(struct dentry *entry, u64 time) 18static 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;
53extern unsigned max_user_bgreq; 53extern unsigned max_user_bgreq;
54extern unsigned max_user_congthresh; 54extern unsigned max_user_congthresh;
55 55
56/* One forget request */
57struct fuse_forget_link {
58 u64 nodeid;
59 u64 nlookup;
60 struct fuse_forget_link *next;
61};
62
56/** FUSE inode */ 63/** FUSE inode */
57struct fuse_inode { 64struct 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 */
546void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req, 559void fuse_queue_forget(struct fuse_conn *fc, struct fuse_forget_link *forget,
547 u64 nodeid, u64 nlookup); 560 u64 nodeid, u64 nlookup);
561
562struct 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);
656void fuse_request_send(struct fuse_conn *fc, struct fuse_req *req); 671void fuse_request_send(struct fuse_conn *fc, struct fuse_req *req);
657 672
658/** 673/**
659 * Send a request with no reply
660 */
661void 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 */
666void fuse_request_send_background(struct fuse_conn *fc, struct fuse_req *req); 676void 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
74struct fuse_forget_link *fuse_alloc_forget()
75{
76 return kzalloc(sizeof(struct fuse_forget_link), GFP_KERNEL);
77}
78
74static struct inode *fuse_alloc_inode(struct super_block *sb) 79static 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
112void 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
125static void fuse_evict_inode(struct inode *inode) 116static 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;