aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorMiklos Szeredi <miklos@szeredi.hu>2006-04-11 01:54:58 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-04-11 09:18:49 -0400
commitce1d5a491f0ee50560416a73faa5e4ddbab074bd (patch)
tree21f91d983b467ad05df0213f54fe00aad84e5761 /fs
parenta87046d822f2d982d25b24c4a644d34f22d4888a (diff)
[PATCH] fuse: clean up request accounting
FUSE allocated most requests from a fixed size pool filled at mount time. However in some cases (release/forget) non-pool requests were used. File locking operations aren't well served by the request pool, since they may block indefinetly thus exhausting the pool. This patch removes the request pool and always allocates requests on demand. Signed-off-by: Miklos Szeredi <miklos@szeredi.hu> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/fuse/dev.c73
-rw-r--r--fs/fuse/dir.c118
-rw-r--r--fs/fuse/file.c48
-rw-r--r--fs/fuse/fuse_i.h26
-rw-r--r--fs/fuse/inode.c54
5 files changed, 111 insertions, 208 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 6b8843d4ad8c..4dc104c0e95d 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -72,10 +72,8 @@ static void restore_sigs(sigset_t *oldset)
72 */ 72 */
73void fuse_reset_request(struct fuse_req *req) 73void fuse_reset_request(struct fuse_req *req)
74{ 74{
75 int preallocated = req->preallocated;
76 BUG_ON(atomic_read(&req->count) != 1); 75 BUG_ON(atomic_read(&req->count) != 1);
77 fuse_request_init(req); 76 fuse_request_init(req);
78 req->preallocated = preallocated;
79} 77}
80 78
81static void __fuse_get_request(struct fuse_req *req) 79static void __fuse_get_request(struct fuse_req *req)
@@ -90,71 +88,28 @@ static void __fuse_put_request(struct fuse_req *req)
90 atomic_dec(&req->count); 88 atomic_dec(&req->count);
91} 89}
92 90
93static struct fuse_req *do_get_request(struct fuse_conn *fc) 91struct fuse_req *fuse_get_req(struct fuse_conn *fc)
94{ 92{
95 struct fuse_req *req; 93 struct fuse_req *req = fuse_request_alloc();
94 if (!req)
95 return ERR_PTR(-ENOMEM);
96 96
97 spin_lock(&fc->lock); 97 atomic_inc(&fc->num_waiting);
98 BUG_ON(list_empty(&fc->unused_list));
99 req = list_entry(fc->unused_list.next, struct fuse_req, list);
100 list_del_init(&req->list);
101 spin_unlock(&fc->lock);
102 fuse_request_init(req); 98 fuse_request_init(req);
103 req->preallocated = 1;
104 req->in.h.uid = current->fsuid; 99 req->in.h.uid = current->fsuid;
105 req->in.h.gid = current->fsgid; 100 req->in.h.gid = current->fsgid;
106 req->in.h.pid = current->pid; 101 req->in.h.pid = current->pid;
107 return req; 102 return req;
108} 103}
109 104
110/* This can return NULL, but only in case it's interrupted by a SIGKILL */
111struct fuse_req *fuse_get_request(struct fuse_conn *fc)
112{
113 int intr;
114 sigset_t oldset;
115
116 atomic_inc(&fc->num_waiting);
117 block_sigs(&oldset);
118 intr = down_interruptible(&fc->outstanding_sem);
119 restore_sigs(&oldset);
120 if (intr) {
121 atomic_dec(&fc->num_waiting);
122 return NULL;
123 }
124 return do_get_request(fc);
125}
126
127/* Must be called with fc->lock held */
128static void fuse_putback_request(struct fuse_conn *fc, struct fuse_req *req)
129{
130 if (req->preallocated) {
131 atomic_dec(&fc->num_waiting);
132 list_add(&req->list, &fc->unused_list);
133 } else
134 fuse_request_free(req);
135
136 /* If we are in debt decrease that first */
137 if (fc->outstanding_debt)
138 fc->outstanding_debt--;
139 else
140 up(&fc->outstanding_sem);
141}
142
143void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req) 105void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req)
144{ 106{
145 if (atomic_dec_and_test(&req->count)) { 107 if (atomic_dec_and_test(&req->count)) {
146 spin_lock(&fc->lock); 108 atomic_dec(&fc->num_waiting);
147 fuse_putback_request(fc, req); 109 fuse_request_free(req);
148 spin_unlock(&fc->lock);
149 } 110 }
150} 111}
151 112
152static void fuse_put_request_locked(struct fuse_conn *fc, struct fuse_req *req)
153{
154 if (atomic_dec_and_test(&req->count))
155 fuse_putback_request(fc, req);
156}
157
158void fuse_release_background(struct fuse_conn *fc, struct fuse_req *req) 113void fuse_release_background(struct fuse_conn *fc, struct fuse_req *req)
159{ 114{
160 iput(req->inode); 115 iput(req->inode);
@@ -189,9 +144,9 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req)
189 list_del(&req->list); 144 list_del(&req->list);
190 req->state = FUSE_REQ_FINISHED; 145 req->state = FUSE_REQ_FINISHED;
191 if (!req->background) { 146 if (!req->background) {
192 wake_up(&req->waitq);
193 fuse_put_request_locked(fc, req);
194 spin_unlock(&fc->lock); 147 spin_unlock(&fc->lock);
148 wake_up(&req->waitq);
149 fuse_put_request(fc, req);
195 } else { 150 } else {
196 void (*end) (struct fuse_conn *, struct fuse_req *) = req->end; 151 void (*end) (struct fuse_conn *, struct fuse_req *) = req->end;
197 req->end = NULL; 152 req->end = NULL;
@@ -302,16 +257,6 @@ static void queue_request(struct fuse_conn *fc, struct fuse_req *req)
302 req->in.h.unique = fc->reqctr; 257 req->in.h.unique = fc->reqctr;
303 req->in.h.len = sizeof(struct fuse_in_header) + 258 req->in.h.len = sizeof(struct fuse_in_header) +
304 len_args(req->in.numargs, (struct fuse_arg *) req->in.args); 259 len_args(req->in.numargs, (struct fuse_arg *) req->in.args);
305 if (!req->preallocated) {
306 /* If request is not preallocated (either FORGET or
307 RELEASE), then still decrease outstanding_sem, so
308 user can't open infinite number of files while not
309 processing the RELEASE requests. However for
310 efficiency do it without blocking, so if down()
311 would block, just increase the debt instead */
312 if (down_trylock(&fc->outstanding_sem))
313 fc->outstanding_debt++;
314 }
315 list_add_tail(&req->list, &fc->pending); 260 list_add_tail(&req->list, &fc->pending);
316 req->state = FUSE_REQ_PENDING; 261 req->state = FUSE_REQ_PENDING;
317 wake_up(&fc->waitq); 262 wake_up(&fc->waitq);
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 256355b80256..8d7546e832e8 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -117,8 +117,8 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
117 return 0; 117 return 0;
118 118
119 fc = get_fuse_conn(inode); 119 fc = get_fuse_conn(inode);
120 req = fuse_get_request(fc); 120 req = fuse_get_req(fc);
121 if (!req) 121 if (IS_ERR(req))
122 return 0; 122 return 0;
123 123
124 fuse_lookup_init(req, entry->d_parent->d_inode, entry, &outarg); 124 fuse_lookup_init(req, entry->d_parent->d_inode, entry, &outarg);
@@ -188,9 +188,9 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
188 if (entry->d_name.len > FUSE_NAME_MAX) 188 if (entry->d_name.len > FUSE_NAME_MAX)
189 return ERR_PTR(-ENAMETOOLONG); 189 return ERR_PTR(-ENAMETOOLONG);
190 190
191 req = fuse_get_request(fc); 191 req = fuse_get_req(fc);
192 if (!req) 192 if (IS_ERR(req))
193 return ERR_PTR(-EINTR); 193 return ERR_PTR(PTR_ERR(req));
194 194
195 fuse_lookup_init(req, dir, entry, &outarg); 195 fuse_lookup_init(req, dir, entry, &outarg);
196 request_send(fc, req); 196 request_send(fc, req);
@@ -244,15 +244,14 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
244 struct file *file; 244 struct file *file;
245 int flags = nd->intent.open.flags - 1; 245 int flags = nd->intent.open.flags - 1;
246 246
247 err = -ENOSYS;
248 if (fc->no_create) 247 if (fc->no_create)
249 goto out; 248 return -ENOSYS;
250 249
251 err = -EINTR; 250 req = fuse_get_req(fc);
252 req = fuse_get_request(fc); 251 if (IS_ERR(req))
253 if (!req) 252 return PTR_ERR(req);
254 goto out;
255 253
254 err = -ENOMEM;
256 ff = fuse_file_alloc(); 255 ff = fuse_file_alloc();
257 if (!ff) 256 if (!ff)
258 goto out_put_request; 257 goto out_put_request;
@@ -314,7 +313,6 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
314 fuse_file_free(ff); 313 fuse_file_free(ff);
315 out_put_request: 314 out_put_request:
316 fuse_put_request(fc, req); 315 fuse_put_request(fc, req);
317 out:
318 return err; 316 return err;
319} 317}
320 318
@@ -375,9 +373,9 @@ static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
375{ 373{
376 struct fuse_mknod_in inarg; 374 struct fuse_mknod_in inarg;
377 struct fuse_conn *fc = get_fuse_conn(dir); 375 struct fuse_conn *fc = get_fuse_conn(dir);
378 struct fuse_req *req = fuse_get_request(fc); 376 struct fuse_req *req = fuse_get_req(fc);
379 if (!req) 377 if (IS_ERR(req))
380 return -EINTR; 378 return PTR_ERR(req);
381 379
382 memset(&inarg, 0, sizeof(inarg)); 380 memset(&inarg, 0, sizeof(inarg));
383 inarg.mode = mode; 381 inarg.mode = mode;
@@ -407,9 +405,9 @@ static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode)
407{ 405{
408 struct fuse_mkdir_in inarg; 406 struct fuse_mkdir_in inarg;
409 struct fuse_conn *fc = get_fuse_conn(dir); 407 struct fuse_conn *fc = get_fuse_conn(dir);
410 struct fuse_req *req = fuse_get_request(fc); 408 struct fuse_req *req = fuse_get_req(fc);
411 if (!req) 409 if (IS_ERR(req))
412 return -EINTR; 410 return PTR_ERR(req);
413 411
414 memset(&inarg, 0, sizeof(inarg)); 412 memset(&inarg, 0, sizeof(inarg));
415 inarg.mode = mode; 413 inarg.mode = mode;
@@ -427,9 +425,9 @@ static int fuse_symlink(struct inode *dir, struct dentry *entry,
427{ 425{
428 struct fuse_conn *fc = get_fuse_conn(dir); 426 struct fuse_conn *fc = get_fuse_conn(dir);
429 unsigned len = strlen(link) + 1; 427 unsigned len = strlen(link) + 1;
430 struct fuse_req *req = fuse_get_request(fc); 428 struct fuse_req *req = fuse_get_req(fc);
431 if (!req) 429 if (IS_ERR(req))
432 return -EINTR; 430 return PTR_ERR(req);
433 431
434 req->in.h.opcode = FUSE_SYMLINK; 432 req->in.h.opcode = FUSE_SYMLINK;
435 req->in.numargs = 2; 433 req->in.numargs = 2;
@@ -444,9 +442,9 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry)
444{ 442{
445 int err; 443 int err;
446 struct fuse_conn *fc = get_fuse_conn(dir); 444 struct fuse_conn *fc = get_fuse_conn(dir);
447 struct fuse_req *req = fuse_get_request(fc); 445 struct fuse_req *req = fuse_get_req(fc);
448 if (!req) 446 if (IS_ERR(req))
449 return -EINTR; 447 return PTR_ERR(req);
450 448
451 req->in.h.opcode = FUSE_UNLINK; 449 req->in.h.opcode = FUSE_UNLINK;
452 req->in.h.nodeid = get_node_id(dir); 450 req->in.h.nodeid = get_node_id(dir);
@@ -476,9 +474,9 @@ static int fuse_rmdir(struct inode *dir, struct dentry *entry)
476{ 474{
477 int err; 475 int err;
478 struct fuse_conn *fc = get_fuse_conn(dir); 476 struct fuse_conn *fc = get_fuse_conn(dir);
479 struct fuse_req *req = fuse_get_request(fc); 477 struct fuse_req *req = fuse_get_req(fc);
480 if (!req) 478 if (IS_ERR(req))
481 return -EINTR; 479 return PTR_ERR(req);
482 480
483 req->in.h.opcode = FUSE_RMDIR; 481 req->in.h.opcode = FUSE_RMDIR;
484 req->in.h.nodeid = get_node_id(dir); 482 req->in.h.nodeid = get_node_id(dir);
@@ -504,9 +502,9 @@ static int fuse_rename(struct inode *olddir, struct dentry *oldent,
504 int err; 502 int err;
505 struct fuse_rename_in inarg; 503 struct fuse_rename_in inarg;
506 struct fuse_conn *fc = get_fuse_conn(olddir); 504 struct fuse_conn *fc = get_fuse_conn(olddir);
507 struct fuse_req *req = fuse_get_request(fc); 505 struct fuse_req *req = fuse_get_req(fc);
508 if (!req) 506 if (IS_ERR(req))
509 return -EINTR; 507 return PTR_ERR(req);
510 508
511 memset(&inarg, 0, sizeof(inarg)); 509 memset(&inarg, 0, sizeof(inarg));
512 inarg.newdir = get_node_id(newdir); 510 inarg.newdir = get_node_id(newdir);
@@ -553,9 +551,9 @@ static int fuse_link(struct dentry *entry, struct inode *newdir,
553 struct fuse_link_in inarg; 551 struct fuse_link_in inarg;
554 struct inode *inode = entry->d_inode; 552 struct inode *inode = entry->d_inode;
555 struct fuse_conn *fc = get_fuse_conn(inode); 553 struct fuse_conn *fc = get_fuse_conn(inode);
556 struct fuse_req *req = fuse_get_request(fc); 554 struct fuse_req *req = fuse_get_req(fc);
557 if (!req) 555 if (IS_ERR(req))
558 return -EINTR; 556 return PTR_ERR(req);
559 557
560 memset(&inarg, 0, sizeof(inarg)); 558 memset(&inarg, 0, sizeof(inarg));
561 inarg.oldnodeid = get_node_id(inode); 559 inarg.oldnodeid = get_node_id(inode);
@@ -583,9 +581,9 @@ int fuse_do_getattr(struct inode *inode)
583 int err; 581 int err;
584 struct fuse_attr_out arg; 582 struct fuse_attr_out arg;
585 struct fuse_conn *fc = get_fuse_conn(inode); 583 struct fuse_conn *fc = get_fuse_conn(inode);
586 struct fuse_req *req = fuse_get_request(fc); 584 struct fuse_req *req = fuse_get_req(fc);
587 if (!req) 585 if (IS_ERR(req))
588 return -EINTR; 586 return PTR_ERR(req);
589 587
590 req->in.h.opcode = FUSE_GETATTR; 588 req->in.h.opcode = FUSE_GETATTR;
591 req->in.h.nodeid = get_node_id(inode); 589 req->in.h.nodeid = get_node_id(inode);
@@ -673,9 +671,9 @@ static int fuse_access(struct inode *inode, int mask)
673 if (fc->no_access) 671 if (fc->no_access)
674 return 0; 672 return 0;
675 673
676 req = fuse_get_request(fc); 674 req = fuse_get_req(fc);
677 if (!req) 675 if (IS_ERR(req))
678 return -EINTR; 676 return PTR_ERR(req);
679 677
680 memset(&inarg, 0, sizeof(inarg)); 678 memset(&inarg, 0, sizeof(inarg));
681 inarg.mask = mask; 679 inarg.mask = mask;
@@ -780,9 +778,9 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
780 if (is_bad_inode(inode)) 778 if (is_bad_inode(inode))
781 return -EIO; 779 return -EIO;
782 780
783 req = fuse_get_request(fc); 781 req = fuse_get_req(fc);
784 if (!req) 782 if (IS_ERR(req))
785 return -EINTR; 783 return PTR_ERR(req);
786 784
787 page = alloc_page(GFP_KERNEL); 785 page = alloc_page(GFP_KERNEL);
788 if (!page) { 786 if (!page) {
@@ -809,11 +807,11 @@ static char *read_link(struct dentry *dentry)
809{ 807{
810 struct inode *inode = dentry->d_inode; 808 struct inode *inode = dentry->d_inode;
811 struct fuse_conn *fc = get_fuse_conn(inode); 809 struct fuse_conn *fc = get_fuse_conn(inode);
812 struct fuse_req *req = fuse_get_request(fc); 810 struct fuse_req *req = fuse_get_req(fc);
813 char *link; 811 char *link;
814 812
815 if (!req) 813 if (IS_ERR(req))
816 return ERR_PTR(-EINTR); 814 return ERR_PTR(PTR_ERR(req));
817 815
818 link = (char *) __get_free_page(GFP_KERNEL); 816 link = (char *) __get_free_page(GFP_KERNEL);
819 if (!link) { 817 if (!link) {
@@ -933,9 +931,9 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr)
933 } 931 }
934 } 932 }
935 933
936 req = fuse_get_request(fc); 934 req = fuse_get_req(fc);
937 if (!req) 935 if (IS_ERR(req))
938 return -EINTR; 936 return PTR_ERR(req);
939 937
940 memset(&inarg, 0, sizeof(inarg)); 938 memset(&inarg, 0, sizeof(inarg));
941 iattr_to_fattr(attr, &inarg); 939 iattr_to_fattr(attr, &inarg);
@@ -995,9 +993,9 @@ static int fuse_setxattr(struct dentry *entry, const char *name,
995 if (fc->no_setxattr) 993 if (fc->no_setxattr)
996 return -EOPNOTSUPP; 994 return -EOPNOTSUPP;
997 995
998 req = fuse_get_request(fc); 996 req = fuse_get_req(fc);
999 if (!req) 997 if (IS_ERR(req))
1000 return -EINTR; 998 return PTR_ERR(req);
1001 999
1002 memset(&inarg, 0, sizeof(inarg)); 1000 memset(&inarg, 0, sizeof(inarg));
1003 inarg.size = size; 1001 inarg.size = size;
@@ -1035,9 +1033,9 @@ static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
1035 if (fc->no_getxattr) 1033 if (fc->no_getxattr)
1036 return -EOPNOTSUPP; 1034 return -EOPNOTSUPP;
1037 1035
1038 req = fuse_get_request(fc); 1036 req = fuse_get_req(fc);
1039 if (!req) 1037 if (IS_ERR(req))
1040 return -EINTR; 1038 return PTR_ERR(req);
1041 1039
1042 memset(&inarg, 0, sizeof(inarg)); 1040 memset(&inarg, 0, sizeof(inarg));
1043 inarg.size = size; 1041 inarg.size = size;
@@ -1085,9 +1083,9 @@ static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
1085 if (fc->no_listxattr) 1083 if (fc->no_listxattr)
1086 return -EOPNOTSUPP; 1084 return -EOPNOTSUPP;
1087 1085
1088 req = fuse_get_request(fc); 1086 req = fuse_get_req(fc);
1089 if (!req) 1087 if (IS_ERR(req))
1090 return -EINTR; 1088 return PTR_ERR(req);
1091 1089
1092 memset(&inarg, 0, sizeof(inarg)); 1090 memset(&inarg, 0, sizeof(inarg));
1093 inarg.size = size; 1091 inarg.size = size;
@@ -1131,9 +1129,9 @@ static int fuse_removexattr(struct dentry *entry, const char *name)
1131 if (fc->no_removexattr) 1129 if (fc->no_removexattr)
1132 return -EOPNOTSUPP; 1130 return -EOPNOTSUPP;
1133 1131
1134 req = fuse_get_request(fc); 1132 req = fuse_get_req(fc);
1135 if (!req) 1133 if (IS_ERR(req))
1136 return -EINTR; 1134 return PTR_ERR(req);
1137 1135
1138 req->in.h.opcode = FUSE_REMOVEXATTR; 1136 req->in.h.opcode = FUSE_REMOVEXATTR;
1139 req->in.h.nodeid = get_node_id(inode); 1137 req->in.h.nodeid = get_node_id(inode);
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 3ac39c0288de..e4f041a11bb5 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -22,9 +22,9 @@ static int fuse_send_open(struct inode *inode, struct file *file, int isdir,
22 struct fuse_req *req; 22 struct fuse_req *req;
23 int err; 23 int err;
24 24
25 req = fuse_get_request(fc); 25 req = fuse_get_req(fc);
26 if (!req) 26 if (IS_ERR(req))
27 return -EINTR; 27 return PTR_ERR(req);
28 28
29 memset(&inarg, 0, sizeof(inarg)); 29 memset(&inarg, 0, sizeof(inarg));
30 inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); 30 inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
@@ -184,9 +184,9 @@ static int fuse_flush(struct file *file)
184 if (fc->no_flush) 184 if (fc->no_flush)
185 return 0; 185 return 0;
186 186
187 req = fuse_get_request(fc); 187 req = fuse_get_req(fc);
188 if (!req) 188 if (IS_ERR(req))
189 return -EINTR; 189 return PTR_ERR(req);
190 190
191 memset(&inarg, 0, sizeof(inarg)); 191 memset(&inarg, 0, sizeof(inarg));
192 inarg.fh = ff->fh; 192 inarg.fh = ff->fh;
@@ -223,9 +223,9 @@ int fuse_fsync_common(struct file *file, struct dentry *de, int datasync,
223 if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir)) 223 if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir))
224 return 0; 224 return 0;
225 225
226 req = fuse_get_request(fc); 226 req = fuse_get_req(fc);
227 if (!req) 227 if (IS_ERR(req))
228 return -EINTR; 228 return PTR_ERR(req);
229 229
230 memset(&inarg, 0, sizeof(inarg)); 230 memset(&inarg, 0, sizeof(inarg));
231 inarg.fh = ff->fh; 231 inarg.fh = ff->fh;
@@ -297,9 +297,9 @@ static int fuse_readpage(struct file *file, struct page *page)
297 if (is_bad_inode(inode)) 297 if (is_bad_inode(inode))
298 goto out; 298 goto out;
299 299
300 err = -EINTR; 300 req = fuse_get_req(fc);
301 req = fuse_get_request(fc); 301 err = PTR_ERR(req);
302 if (!req) 302 if (IS_ERR(req))
303 goto out; 303 goto out;
304 304
305 req->out.page_zeroing = 1; 305 req->out.page_zeroing = 1;
@@ -368,10 +368,10 @@ static int fuse_readpages_fill(void *_data, struct page *page)
368 (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read || 368 (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read ||
369 req->pages[req->num_pages - 1]->index + 1 != page->index)) { 369 req->pages[req->num_pages - 1]->index + 1 != page->index)) {
370 fuse_send_readpages(req, data->file, inode); 370 fuse_send_readpages(req, data->file, inode);
371 data->req = req = fuse_get_request(fc); 371 data->req = req = fuse_get_req(fc);
372 if (!req) { 372 if (IS_ERR(req)) {
373 unlock_page(page); 373 unlock_page(page);
374 return -EINTR; 374 return PTR_ERR(req);
375 } 375 }
376 } 376 }
377 req->pages[req->num_pages] = page; 377 req->pages[req->num_pages] = page;
@@ -392,9 +392,9 @@ static int fuse_readpages(struct file *file, struct address_space *mapping,
392 392
393 data.file = file; 393 data.file = file;
394 data.inode = inode; 394 data.inode = inode;
395 data.req = fuse_get_request(fc); 395 data.req = fuse_get_req(fc);
396 if (!data.req) 396 if (IS_ERR(data.req))
397 return -EINTR; 397 return PTR_ERR(data.req);
398 398
399 err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data); 399 err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data);
400 if (!err) { 400 if (!err) {
@@ -455,9 +455,9 @@ static int fuse_commit_write(struct file *file, struct page *page,
455 if (is_bad_inode(inode)) 455 if (is_bad_inode(inode))
456 return -EIO; 456 return -EIO;
457 457
458 req = fuse_get_request(fc); 458 req = fuse_get_req(fc);
459 if (!req) 459 if (IS_ERR(req))
460 return -EINTR; 460 return PTR_ERR(req);
461 461
462 req->num_pages = 1; 462 req->num_pages = 1;
463 req->pages[0] = page; 463 req->pages[0] = page;
@@ -532,9 +532,9 @@ static ssize_t fuse_direct_io(struct file *file, const char __user *buf,
532 if (is_bad_inode(inode)) 532 if (is_bad_inode(inode))
533 return -EIO; 533 return -EIO;
534 534
535 req = fuse_get_request(fc); 535 req = fuse_get_req(fc);
536 if (!req) 536 if (IS_ERR(req))
537 return -EINTR; 537 return PTR_ERR(req);
538 538
539 while (count) { 539 while (count) {
540 size_t nres; 540 size_t nres;
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 6ed812fd6200..242e69cb1251 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -18,9 +18,6 @@
18/** Max number of pages that can be used in a single read request */ 18/** Max number of pages that can be used in a single read request */
19#define FUSE_MAX_PAGES_PER_REQ 32 19#define FUSE_MAX_PAGES_PER_REQ 32
20 20
21/** If more requests are outstanding, then the operation will block */
22#define FUSE_MAX_OUTSTANDING 10
23
24/** It could be as large as PATH_MAX, but would that have any uses? */ 21/** It could be as large as PATH_MAX, but would that have any uses? */
25#define FUSE_NAME_MAX 1024 22#define FUSE_NAME_MAX 1024
26 23
@@ -131,8 +128,8 @@ struct fuse_conn;
131 * A request to the client 128 * A request to the client
132 */ 129 */
133struct fuse_req { 130struct fuse_req {
134 /** This can be on either unused_list, pending processing or 131 /** This can be on either pending processing or io lists in
135 io lists in fuse_conn */ 132 fuse_conn */
136 struct list_head list; 133 struct list_head list;
137 134
138 /** Entry on the background list */ 135 /** Entry on the background list */
@@ -150,9 +147,6 @@ struct fuse_req {
150 /** True if the request has reply */ 147 /** True if the request has reply */
151 unsigned isreply:1; 148 unsigned isreply:1;
152 149
153 /** The request is preallocated */
154 unsigned preallocated:1;
155
156 /** The request was interrupted */ 150 /** The request was interrupted */
157 unsigned interrupted:1; 151 unsigned interrupted:1;
158 152
@@ -247,19 +241,9 @@ struct fuse_conn {
247 interrupted request) */ 241 interrupted request) */
248 struct list_head background; 242 struct list_head background;
249 243
250 /** Controls the maximum number of outstanding requests */
251 struct semaphore outstanding_sem;
252
253 /** This counts the number of outstanding requests if
254 outstanding_sem would go negative */
255 unsigned outstanding_debt;
256
257 /** RW semaphore for exclusion with fuse_put_super() */ 244 /** RW semaphore for exclusion with fuse_put_super() */
258 struct rw_semaphore sbput_sem; 245 struct rw_semaphore sbput_sem;
259 246
260 /** The list of unused requests */
261 struct list_head unused_list;
262
263 /** The next unique request id */ 247 /** The next unique request id */
264 u64 reqctr; 248 u64 reqctr;
265 249
@@ -452,11 +436,11 @@ void fuse_reset_request(struct fuse_req *req);
452/** 436/**
453 * Reserve a preallocated request 437 * Reserve a preallocated request
454 */ 438 */
455struct fuse_req *fuse_get_request(struct fuse_conn *fc); 439struct fuse_req *fuse_get_req(struct fuse_conn *fc);
456 440
457/** 441/**
458 * Decrement reference count of a request. If count goes to zero put 442 * Decrement reference count of a request. If count goes to zero free
459 * on unused list (preallocated) or free request (not preallocated). 443 * the request.
460 */ 444 */
461void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req); 445void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req);
462 446
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index cc58debeabd4..824ebbc428ed 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -243,9 +243,9 @@ static int fuse_statfs(struct super_block *sb, struct kstatfs *buf)
243 struct fuse_statfs_out outarg; 243 struct fuse_statfs_out outarg;
244 int err; 244 int err;
245 245
246 req = fuse_get_request(fc); 246 req = fuse_get_req(fc);
247 if (!req) 247 if (IS_ERR(req))
248 return -EINTR; 248 return PTR_ERR(req);
249 249
250 memset(&outarg, 0, sizeof(outarg)); 250 memset(&outarg, 0, sizeof(outarg));
251 req->in.numargs = 0; 251 req->in.numargs = 0;
@@ -370,15 +370,7 @@ static int fuse_show_options(struct seq_file *m, struct vfsmount *mnt)
370 370
371static void fuse_conn_release(struct kobject *kobj) 371static void fuse_conn_release(struct kobject *kobj)
372{ 372{
373 struct fuse_conn *fc = get_fuse_conn_kobj(kobj); 373 kfree(get_fuse_conn_kobj(kobj));
374
375 while (!list_empty(&fc->unused_list)) {
376 struct fuse_req *req;
377 req = list_entry(fc->unused_list.next, struct fuse_req, list);
378 list_del(&req->list);
379 fuse_request_free(req);
380 }
381 kfree(fc);
382} 374}
383 375
384static struct fuse_conn *new_conn(void) 376static struct fuse_conn *new_conn(void)
@@ -387,27 +379,16 @@ static struct fuse_conn *new_conn(void)
387 379
388 fc = kzalloc(sizeof(*fc), GFP_KERNEL); 380 fc = kzalloc(sizeof(*fc), GFP_KERNEL);
389 if (fc) { 381 if (fc) {
390 int i;
391 spin_lock_init(&fc->lock); 382 spin_lock_init(&fc->lock);
392 init_waitqueue_head(&fc->waitq); 383 init_waitqueue_head(&fc->waitq);
393 INIT_LIST_HEAD(&fc->pending); 384 INIT_LIST_HEAD(&fc->pending);
394 INIT_LIST_HEAD(&fc->processing); 385 INIT_LIST_HEAD(&fc->processing);
395 INIT_LIST_HEAD(&fc->io); 386 INIT_LIST_HEAD(&fc->io);
396 INIT_LIST_HEAD(&fc->unused_list);
397 INIT_LIST_HEAD(&fc->background); 387 INIT_LIST_HEAD(&fc->background);
398 sema_init(&fc->outstanding_sem, 1); /* One for INIT */
399 init_rwsem(&fc->sbput_sem); 388 init_rwsem(&fc->sbput_sem);
400 kobj_set_kset_s(fc, connections_subsys); 389 kobj_set_kset_s(fc, connections_subsys);
401 kobject_init(&fc->kobj); 390 kobject_init(&fc->kobj);
402 atomic_set(&fc->num_waiting, 0); 391 atomic_set(&fc->num_waiting, 0);
403 for (i = 0; i < FUSE_MAX_OUTSTANDING; i++) {
404 struct fuse_req *req = fuse_request_alloc();
405 if (!req) {
406 kobject_put(&fc->kobj);
407 return NULL;
408 }
409 list_add(&req->list, &fc->unused_list);
410 }
411 fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE; 392 fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE;
412 fc->bdi.unplug_io_fn = default_unplug_io_fn; 393 fc->bdi.unplug_io_fn = default_unplug_io_fn;
413 fc->reqctr = 0; 394 fc->reqctr = 0;
@@ -438,7 +419,6 @@ static struct super_operations fuse_super_operations = {
438 419
439static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) 420static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
440{ 421{
441 int i;
442 struct fuse_init_out *arg = &req->misc.init_out; 422 struct fuse_init_out *arg = &req->misc.init_out;
443 423
444 if (req->out.h.error || arg->major != FUSE_KERNEL_VERSION) 424 if (req->out.h.error || arg->major != FUSE_KERNEL_VERSION)
@@ -457,22 +437,11 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
457 fc->minor = arg->minor; 437 fc->minor = arg->minor;
458 fc->max_write = arg->minor < 5 ? 4096 : arg->max_write; 438 fc->max_write = arg->minor < 5 ? 4096 : arg->max_write;
459 } 439 }
460
461 /* After INIT reply is received other requests can go
462 out. So do (FUSE_MAX_OUTSTANDING - 1) number of
463 up()s on outstanding_sem. The last up() is done in
464 fuse_putback_request() */
465 for (i = 1; i < FUSE_MAX_OUTSTANDING; i++)
466 up(&fc->outstanding_sem);
467
468 fuse_put_request(fc, req); 440 fuse_put_request(fc, req);
469} 441}
470 442
471static void fuse_send_init(struct fuse_conn *fc) 443static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req)
472{ 444{
473 /* This is called from fuse_read_super() so there's guaranteed
474 to be exactly one request available */
475 struct fuse_req *req = fuse_get_request(fc);
476 struct fuse_init_in *arg = &req->misc.init_in; 445 struct fuse_init_in *arg = &req->misc.init_in;
477 446
478 arg->major = FUSE_KERNEL_VERSION; 447 arg->major = FUSE_KERNEL_VERSION;
@@ -508,6 +477,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
508 struct fuse_mount_data d; 477 struct fuse_mount_data d;
509 struct file *file; 478 struct file *file;
510 struct dentry *root_dentry; 479 struct dentry *root_dentry;
480 struct fuse_req *init_req;
511 int err; 481 int err;
512 482
513 if (!parse_fuse_opt((char *) data, &d)) 483 if (!parse_fuse_opt((char *) data, &d))
@@ -554,13 +524,17 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
554 goto err; 524 goto err;
555 } 525 }
556 526
527 init_req = fuse_request_alloc();
528 if (!init_req)
529 goto err_put_root;
530
557 err = kobject_set_name(&fc->kobj, "%llu", conn_id()); 531 err = kobject_set_name(&fc->kobj, "%llu", conn_id());
558 if (err) 532 if (err)
559 goto err_put_root; 533 goto err_free_req;
560 534
561 err = kobject_add(&fc->kobj); 535 err = kobject_add(&fc->kobj);
562 if (err) 536 if (err)
563 goto err_put_root; 537 goto err_free_req;
564 538
565 sb->s_root = root_dentry; 539 sb->s_root = root_dentry;
566 fc->mounted = 1; 540 fc->mounted = 1;
@@ -574,10 +548,12 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
574 */ 548 */
575 fput(file); 549 fput(file);
576 550
577 fuse_send_init(fc); 551 fuse_send_init(fc, init_req);
578 552
579 return 0; 553 return 0;
580 554
555 err_free_req:
556 fuse_request_free(init_req);
581 err_put_root: 557 err_put_root:
582 dput(root_dentry); 558 dput(root_dentry);
583 err: 559 err: