diff options
Diffstat (limited to 'fs/fuse/dev.c')
-rw-r--r-- | fs/fuse/dev.c | 68 |
1 files changed, 39 insertions, 29 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 3ad22beb24c..db534bcde45 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
@@ -129,7 +129,7 @@ static struct fuse_req *get_reserved_req(struct fuse_conn *fc, | |||
129 | struct fuse_file *ff = file->private_data; | 129 | struct fuse_file *ff = file->private_data; |
130 | 130 | ||
131 | do { | 131 | do { |
132 | wait_event(fc->blocked_waitq, ff->reserved_req); | 132 | wait_event(fc->reserved_req_waitq, ff->reserved_req); |
133 | spin_lock(&fc->lock); | 133 | spin_lock(&fc->lock); |
134 | if (ff->reserved_req) { | 134 | if (ff->reserved_req) { |
135 | req = ff->reserved_req; | 135 | req = ff->reserved_req; |
@@ -155,7 +155,7 @@ static void put_reserved_req(struct fuse_conn *fc, struct fuse_req *req) | |||
155 | fuse_request_init(req); | 155 | fuse_request_init(req); |
156 | BUG_ON(ff->reserved_req); | 156 | BUG_ON(ff->reserved_req); |
157 | ff->reserved_req = req; | 157 | ff->reserved_req = req; |
158 | wake_up(&fc->blocked_waitq); | 158 | wake_up_all(&fc->reserved_req_waitq); |
159 | spin_unlock(&fc->lock); | 159 | spin_unlock(&fc->lock); |
160 | fput(file); | 160 | fput(file); |
161 | } | 161 | } |
@@ -224,13 +224,13 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req) | |||
224 | fc->blocked = 0; | 224 | fc->blocked = 0; |
225 | wake_up_all(&fc->blocked_waitq); | 225 | wake_up_all(&fc->blocked_waitq); |
226 | } | 226 | } |
227 | if (fc->num_background == FUSE_CONGESTION_THRESHOLD) { | ||
228 | clear_bdi_congested(&fc->bdi, READ); | ||
229 | clear_bdi_congested(&fc->bdi, WRITE); | ||
230 | } | ||
227 | fc->num_background--; | 231 | fc->num_background--; |
228 | } | 232 | } |
229 | spin_unlock(&fc->lock); | 233 | spin_unlock(&fc->lock); |
230 | dput(req->dentry); | ||
231 | mntput(req->vfsmount); | ||
232 | if (req->file) | ||
233 | fput(req->file); | ||
234 | wake_up(&req->waitq); | 234 | wake_up(&req->waitq); |
235 | if (end) | 235 | if (end) |
236 | end(fc, req); | 236 | end(fc, req); |
@@ -273,28 +273,41 @@ static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req) | |||
273 | queue_interrupt(fc, req); | 273 | queue_interrupt(fc, req); |
274 | } | 274 | } |
275 | 275 | ||
276 | if (req->force) { | 276 | if (!req->force) { |
277 | spin_unlock(&fc->lock); | ||
278 | wait_event(req->waitq, req->state == FUSE_REQ_FINISHED); | ||
279 | spin_lock(&fc->lock); | ||
280 | } else { | ||
281 | sigset_t oldset; | 277 | sigset_t oldset; |
282 | 278 | ||
283 | /* Only fatal signals may interrupt this */ | 279 | /* Only fatal signals may interrupt this */ |
284 | block_sigs(&oldset); | 280 | block_sigs(&oldset); |
285 | wait_answer_interruptible(fc, req); | 281 | wait_answer_interruptible(fc, req); |
286 | restore_sigs(&oldset); | 282 | restore_sigs(&oldset); |
283 | |||
284 | if (req->aborted) | ||
285 | goto aborted; | ||
286 | if (req->state == FUSE_REQ_FINISHED) | ||
287 | return; | ||
288 | |||
289 | /* Request is not yet in userspace, bail out */ | ||
290 | if (req->state == FUSE_REQ_PENDING) { | ||
291 | list_del(&req->list); | ||
292 | __fuse_put_request(req); | ||
293 | req->out.h.error = -EINTR; | ||
294 | return; | ||
295 | } | ||
287 | } | 296 | } |
288 | 297 | ||
289 | if (req->aborted) | 298 | /* |
290 | goto aborted; | 299 | * Either request is already in userspace, or it was forced. |
291 | if (req->state == FUSE_REQ_FINISHED) | 300 | * Wait it out. |
292 | return; | 301 | */ |
302 | spin_unlock(&fc->lock); | ||
303 | wait_event(req->waitq, req->state == FUSE_REQ_FINISHED); | ||
304 | spin_lock(&fc->lock); | ||
293 | 305 | ||
294 | req->out.h.error = -EINTR; | 306 | if (!req->aborted) |
295 | req->aborted = 1; | 307 | return; |
296 | 308 | ||
297 | aborted: | 309 | aborted: |
310 | BUG_ON(req->state != FUSE_REQ_FINISHED); | ||
298 | if (req->locked) { | 311 | if (req->locked) { |
299 | /* This is uninterruptible sleep, because data is | 312 | /* This is uninterruptible sleep, because data is |
300 | being copied to/from the buffers of req. During | 313 | being copied to/from the buffers of req. During |
@@ -305,14 +318,6 @@ static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req) | |||
305 | wait_event(req->waitq, !req->locked); | 318 | wait_event(req->waitq, !req->locked); |
306 | spin_lock(&fc->lock); | 319 | spin_lock(&fc->lock); |
307 | } | 320 | } |
308 | if (req->state == FUSE_REQ_PENDING) { | ||
309 | list_del(&req->list); | ||
310 | __fuse_put_request(req); | ||
311 | } else if (req->state == FUSE_REQ_SENT) { | ||
312 | spin_unlock(&fc->lock); | ||
313 | wait_event(req->waitq, req->state == FUSE_REQ_FINISHED); | ||
314 | spin_lock(&fc->lock); | ||
315 | } | ||
316 | } | 321 | } |
317 | 322 | ||
318 | static unsigned len_args(unsigned numargs, struct fuse_arg *args) | 323 | static unsigned len_args(unsigned numargs, struct fuse_arg *args) |
@@ -378,6 +383,10 @@ static void request_send_nowait(struct fuse_conn *fc, struct fuse_req *req) | |||
378 | fc->num_background++; | 383 | fc->num_background++; |
379 | if (fc->num_background == FUSE_MAX_BACKGROUND) | 384 | if (fc->num_background == FUSE_MAX_BACKGROUND) |
380 | fc->blocked = 1; | 385 | fc->blocked = 1; |
386 | if (fc->num_background == FUSE_CONGESTION_THRESHOLD) { | ||
387 | set_bdi_congested(&fc->bdi, READ); | ||
388 | set_bdi_congested(&fc->bdi, WRITE); | ||
389 | } | ||
381 | 390 | ||
382 | queue_request(fc, req); | 391 | queue_request(fc, req); |
383 | spin_unlock(&fc->lock); | 392 | spin_unlock(&fc->lock); |
@@ -738,11 +747,12 @@ static ssize_t fuse_dev_read(struct kiocb *iocb, const struct iovec *iov, | |||
738 | fuse_copy_finish(&cs); | 747 | fuse_copy_finish(&cs); |
739 | spin_lock(&fc->lock); | 748 | spin_lock(&fc->lock); |
740 | req->locked = 0; | 749 | req->locked = 0; |
741 | if (!err && req->aborted) | 750 | if (req->aborted) { |
742 | err = -ENOENT; | 751 | request_end(fc, req); |
752 | return -ENODEV; | ||
753 | } | ||
743 | if (err) { | 754 | if (err) { |
744 | if (!req->aborted) | 755 | req->out.h.error = -EIO; |
745 | req->out.h.error = -EIO; | ||
746 | request_end(fc, req); | 756 | request_end(fc, req); |
747 | return err; | 757 | return err; |
748 | } | 758 | } |