aboutsummaryrefslogtreecommitdiff
path: root/fs/fuse
diff options
context:
space:
mode:
Diffstat (limited to 'fs/fuse')
-rw-r--r--fs/fuse/dev.c25
-rw-r--r--fs/fuse/fuse_i.h3
2 files changed, 22 insertions, 6 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index d4efb6223e2..8538b298a6b 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -92,30 +92,39 @@ struct fuse_req *fuse_get_req(struct fuse_conn *fc)
{
struct fuse_req *req;
sigset_t oldset;
+ int intr;
int err;
+ atomic_inc(&fc->num_waiting);
block_sigs(&oldset);
- err = wait_event_interruptible(fc->blocked_waitq, !fc->blocked);
+ intr = wait_event_interruptible(fc->blocked_waitq, !fc->blocked);
restore_sigs(&oldset);
- if (err)
- return ERR_PTR(-EINTR);
+ err = -EINTR;
+ if (intr)
+ goto out;
req = fuse_request_alloc();
+ err = -ENOMEM;
if (!req)
- return ERR_PTR(-ENOMEM);
+ goto out;
- atomic_inc(&fc->num_waiting);
fuse_request_init(req);
req->in.h.uid = current->fsuid;
req->in.h.gid = current->fsgid;
req->in.h.pid = current->pid;
+ req->waiting = 1;
return req;
+
+ out:
+ atomic_dec(&fc->num_waiting);
+ return ERR_PTR(err);
}
void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req)
{
if (atomic_dec_and_test(&req->count)) {
- atomic_dec(&fc->num_waiting);
+ if (req->waiting)
+ atomic_dec(&fc->num_waiting);
fuse_request_free(req);
}
}
@@ -281,6 +290,10 @@ static void queue_request(struct fuse_conn *fc, struct fuse_req *req)
len_args(req->in.numargs, (struct fuse_arg *) req->in.args);
list_add_tail(&req->list, &fc->pending);
req->state = FUSE_REQ_PENDING;
+ if (!req->waiting) {
+ req->waiting = 1;
+ atomic_inc(&fc->num_waiting);
+ }
wake_up(&fc->waitq);
kill_fasync(&fc->fasync, SIGIO, POLL_IN);
}
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index ee9b8304251..59661c481d9 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -159,6 +159,9 @@ struct fuse_req {
/** Data is being copied to/from the request */
unsigned locked:1;
+ /** Request is counted as "waiting" */
+ unsigned waiting:1;
+
/** State of the request */
enum fuse_req_state state;