Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+24 −19
Original line number Diff line number Diff line
@@ -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;
	req->aborted = 1;
			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);

	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
@@ -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)