diff options
-rw-r--r-- | fs/fuse/dev.c | 24 | ||||
-rw-r--r-- | fs/fuse/fuse_i.h | 14 | ||||
-rw-r--r-- | fs/fuse/inode.c | 4 |
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 | ||
91 | struct fuse_req *fuse_get_req(struct fuse_conn *fc) | 91 | struct 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) | |||
288 | static void request_send_nowait(struct fuse_conn *fc, struct fuse_req *req) | 306 | static 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) | |||
306 | void request_send_background(struct fuse_conn *fc, struct fuse_req *req) | 325 | void 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 | ||
443 | static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req) | 447 | static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req) |