Commit a131de0a authored by Miklos Szeredi's avatar Miklos Szeredi Committed by Linus Torvalds

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: default avatarMiklos Szeredi <mszeredi@suse.cz>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 819c4b3b
...@@ -273,28 +273,41 @@ static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req) ...@@ -273,28 +273,41 @@ static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)
queue_interrupt(fc, req); queue_interrupt(fc, req);
} }
if (req->force) { if (!req->force) {
spin_unlock(&fc->lock);
wait_event(req->waitq, req->state == FUSE_REQ_FINISHED);
spin_lock(&fc->lock);
} else {
sigset_t oldset; sigset_t oldset;
/* Only fatal signals may interrupt this */ /* Only fatal signals may interrupt this */
block_sigs(&oldset); block_sigs(&oldset);
wait_answer_interruptible(fc, req); wait_answer_interruptible(fc, req);
restore_sigs(&oldset); 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; * Either request is already in userspace, or it was forced.
if (req->state == FUSE_REQ_FINISHED) * Wait it out.
return; */
spin_unlock(&fc->lock);
wait_event(req->waitq, req->state == FUSE_REQ_FINISHED);
spin_lock(&fc->lock);
req->out.h.error = -EINTR; if (!req->aborted)
req->aborted = 1; return;
aborted: aborted:
BUG_ON(req->state != FUSE_REQ_FINISHED);
if (req->locked) { if (req->locked) {
/* This is uninterruptible sleep, because data is /* This is uninterruptible sleep, because data is
being copied to/from the buffers of req. During 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,14 +318,6 @@ static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)
wait_event(req->waitq, !req->locked); wait_event(req->waitq, !req->locked);
spin_lock(&fc->lock); 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) static unsigned len_args(unsigned numargs, struct fuse_arg *args)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment