X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=fs%2Ffuse%2Fdev.c;h=db534bcde45f6ff52a7cbfb44fcb8b49ea9bbb9d;hb=2b06ac867176d5d24757bda7e13f6255d6b96d7b;hp=de25bff31420841febb159100299e26735071d2f;hpb=c756e0a4d79202535774806f148026e40466a5eb;p=linux-2.6-omap-h63xx.git diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index de25bff3142..db534bcde45 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -231,8 +231,6 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req) fc->num_background--; } spin_unlock(&fc->lock); - dput(req->dentry); - mntput(req->vfsmount); wake_up(&req->waitq); if (end) end(fc, req); @@ -275,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 @@ -307,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) @@ -744,11 +747,12 @@ static ssize_t fuse_dev_read(struct kiocb *iocb, const struct iovec *iov, fuse_copy_finish(&cs); spin_lock(&fc->lock); req->locked = 0; - if (!err && req->aborted) - err = -ENOENT; + if (req->aborted) { + request_end(fc, req); + return -ENODEV; + } if (err) { - if (!req->aborted) - req->out.h.error = -EIO; + req->out.h.error = -EIO; request_end(fc, req); return err; }