diff options
| author | Miklos Szeredi <mszeredi@suse.cz> | 2007-10-17 02:31:04 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-17 11:43:04 -0400 |
| commit | a131de0a482ac95e6469f56981c7b063593fdc5d (patch) | |
| tree | 0799985119f15525cc8c3c93a4cacad307405a5a | |
| parent | 819c4b3b4009275caae973691378235c177a1429 (diff) | |
fuse: no abort on interrupt
Don't set 'aborted' flag on a request if it's interrupted. We have to wait
for the answer anyway, and this would only a very little time while copying
the reply.
This means, that write() on the fuse device will not return -ENOENT during
normal operation, only if the filesystem is aborted by a forced umount or
through the fusectl interface.
This could simplify userspace code somewhat when backward compatibility with
earlier kernel versions is not required.
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
| -rw-r--r-- | fs/fuse/dev.c | 43 |
1 files changed, 24 insertions, 19 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index c78f60e1ba5d..cc6c2908fb12 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
| @@ -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) |
