Skip to content

Commit

Permalink
fuse: no abort on interrupt
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
Miklos Szeredi authored and Linus Torvalds committed Oct 17, 2007
1 parent 819c4b3 commit a131de0
Showing 1 changed file with 24 additions and 19 deletions.
43 changes: 24 additions & 19 deletions fs/fuse/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -273,28 +273,41 @@ static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)
queue_interrupt(fc, req);
}

if (req->force) {
spin_unlock(&fc->lock);
wait_event(req->waitq, req->state == FUSE_REQ_FINISHED);
spin_lock(&fc->lock);
} else {
if (!req->force) {
sigset_t oldset;

/* Only fatal signals may interrupt this */
block_sigs(&oldset);
wait_answer_interruptible(fc, req);
restore_sigs(&oldset);

if (req->aborted)
goto aborted;
if (req->state == FUSE_REQ_FINISHED)
return;

/* Request is not yet in userspace, bail out */
if (req->state == FUSE_REQ_PENDING) {
list_del(&req->list);
__fuse_put_request(req);
req->out.h.error = -EINTR;
return;
}
}

if (req->aborted)
goto aborted;
if (req->state == FUSE_REQ_FINISHED)
return;
/*
* Either request is already in userspace, or it was forced.
* Wait it out.
*/
spin_unlock(&fc->lock);
wait_event(req->waitq, req->state == FUSE_REQ_FINISHED);
spin_lock(&fc->lock);

req->out.h.error = -EINTR;
req->aborted = 1;
if (!req->aborted)
return;

aborted:
BUG_ON(req->state != FUSE_REQ_FINISHED);
if (req->locked) {
/* This is uninterruptible sleep, because data is
being copied to/from the buffers of req. During
Expand All @@ -305,14 +318,6 @@ static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)
wait_event(req->waitq, !req->locked);
spin_lock(&fc->lock);
}
if (req->state == FUSE_REQ_PENDING) {
list_del(&req->list);
__fuse_put_request(req);
} else if (req->state == FUSE_REQ_SENT) {
spin_unlock(&fc->lock);
wait_event(req->waitq, req->state == FUSE_REQ_FINISHED);
spin_lock(&fc->lock);
}
}

static unsigned len_args(unsigned numargs, struct fuse_arg *args)
Expand Down

0 comments on commit a131de0

Please sign in to comment.