aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/fuse/dev.c24
-rw-r--r--fs/fuse/fuse_i.h14
-rw-r--r--fs/fuse/inode.c4
3 files changed, 38 insertions, 4 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 4dc104c0e95d..6c740f860665 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -90,7 +90,17 @@ static void __fuse_put_request(struct fuse_req *req)
90 90
91struct fuse_req *fuse_get_req(struct fuse_conn *fc) 91struct fuse_req *fuse_get_req(struct fuse_conn *fc)
92{ 92{
93 struct fuse_req *req = fuse_request_alloc(); 93 struct fuse_req *req;
94 sigset_t oldset;
95 int err;
96
97 block_sigs(&oldset);
98 err = wait_event_interruptible(fc->blocked_waitq, !fc->blocked);
99 restore_sigs(&oldset);
100 if (err)
101 return ERR_PTR(-EINTR);
102
103 req = fuse_request_alloc();
94 if (!req) 104 if (!req)
95 return ERR_PTR(-ENOMEM); 105 return ERR_PTR(-ENOMEM);
96 106
@@ -118,6 +128,11 @@ void fuse_release_background(struct fuse_conn *fc, struct fuse_req *req)
118 fput(req->file); 128 fput(req->file);
119 spin_lock(&fc->lock); 129 spin_lock(&fc->lock);
120 list_del(&req->bg_entry); 130 list_del(&req->bg_entry);
131 if (fc->num_background == FUSE_MAX_BACKGROUND) {
132 fc->blocked = 0;
133 wake_up_all(&fc->blocked_waitq);
134 }
135 fc->num_background--;
121 spin_unlock(&fc->lock); 136 spin_unlock(&fc->lock);
122} 137}
123 138
@@ -195,6 +210,9 @@ static void background_request(struct fuse_conn *fc, struct fuse_req *req)
195{ 210{
196 req->background = 1; 211 req->background = 1;
197 list_add(&req->bg_entry, &fc->background); 212 list_add(&req->bg_entry, &fc->background);
213 fc->num_background++;
214 if (fc->num_background == FUSE_MAX_BACKGROUND)
215 fc->blocked = 1;
198 if (req->inode) 216 if (req->inode)
199 req->inode = igrab(req->inode); 217 req->inode = igrab(req->inode);
200 if (req->inode2) 218 if (req->inode2)
@@ -288,6 +306,7 @@ void request_send(struct fuse_conn *fc, struct fuse_req *req)
288static void request_send_nowait(struct fuse_conn *fc, struct fuse_req *req) 306static void request_send_nowait(struct fuse_conn *fc, struct fuse_req *req)
289{ 307{
290 spin_lock(&fc->lock); 308 spin_lock(&fc->lock);
309 background_request(fc, req);
291 if (fc->connected) { 310 if (fc->connected) {
292 queue_request(fc, req); 311 queue_request(fc, req);
293 spin_unlock(&fc->lock); 312 spin_unlock(&fc->lock);
@@ -306,9 +325,6 @@ void request_send_noreply(struct fuse_conn *fc, struct fuse_req *req)
306void request_send_background(struct fuse_conn *fc, struct fuse_req *req) 325void request_send_background(struct fuse_conn *fc, struct fuse_req *req)
307{ 326{
308 req->isreply = 1; 327 req->isreply = 1;
309 spin_lock(&fc->lock);
310 background_request(fc, req);
311 spin_unlock(&fc->lock);
312 request_send_nowait(fc, req); 328 request_send_nowait(fc, req);
313} 329}
314 330
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 242e69cb1251..19c7185a7546 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -18,6 +18,9 @@
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/** Maximum number of outstanding background requests */
22#define FUSE_MAX_BACKGROUND 10
23
21/** It could be as large as PATH_MAX, but would that have any uses? */ 24/** It could be as large as PATH_MAX, but would that have any uses? */
22#define FUSE_NAME_MAX 1024 25#define FUSE_NAME_MAX 1024
23 26
@@ -241,6 +244,17 @@ struct fuse_conn {
241 interrupted request) */ 244 interrupted request) */
242 struct list_head background; 245 struct list_head background;
243 246
247 /** Number of requests currently in the background */
248 unsigned num_background;
249
250 /** Flag indicating if connection is blocked. This will be
251 the case before the INIT reply is received, and if there
252 are too many outstading backgrounds requests */
253 int blocked;
254
255 /** waitq for blocked connection */
256 wait_queue_head_t blocked_waitq;
257
244 /** RW semaphore for exclusion with fuse_put_super() */ 258 /** RW semaphore for exclusion with fuse_put_super() */
245 struct rw_semaphore sbput_sem; 259 struct rw_semaphore sbput_sem;
246 260
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 824ebbc428ed..fd34037b0588 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -381,6 +381,7 @@ static struct fuse_conn *new_conn(void)
381 if (fc) { 381 if (fc) {
382 spin_lock_init(&fc->lock); 382 spin_lock_init(&fc->lock);
383 init_waitqueue_head(&fc->waitq); 383 init_waitqueue_head(&fc->waitq);
384 init_waitqueue_head(&fc->blocked_waitq);
384 INIT_LIST_HEAD(&fc->pending); 385 INIT_LIST_HEAD(&fc->pending);
385 INIT_LIST_HEAD(&fc->processing); 386 INIT_LIST_HEAD(&fc->processing);
386 INIT_LIST_HEAD(&fc->io); 387 INIT_LIST_HEAD(&fc->io);
@@ -392,6 +393,7 @@ static struct fuse_conn *new_conn(void)
392 fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE; 393 fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE;
393 fc->bdi.unplug_io_fn = default_unplug_io_fn; 394 fc->bdi.unplug_io_fn = default_unplug_io_fn;
394 fc->reqctr = 0; 395 fc->reqctr = 0;
396 fc->blocked = 1;
395 } 397 }
396 return fc; 398 return fc;
397} 399}
@@ -438,6 +440,8 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
438 fc->max_write = arg->minor < 5 ? 4096 : arg->max_write; 440 fc->max_write = arg->minor < 5 ? 4096 : arg->max_write;
439 } 441 }
440 fuse_put_request(fc, req); 442 fuse_put_request(fc, req);
443 fc->blocked = 0;
444 wake_up_all(&fc->blocked_waitq);
441} 445}
442 446
443static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req) 447static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req)