aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse/fuse_i.h
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/fuse/fuse_i.h
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/fuse/fuse_i.h')
-rw-r--r--fs/fuse/fuse_i.h28
1 files changed, 19 insertions, 9 deletions
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);