aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 d4efb6223e2c..8538b298a6b0 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)
92{ 92{
93 struct fuse_req *req; 93 struct fuse_req *req;
94 sigset_t oldset; 94 sigset_t oldset;
95 int intr;
95 int err; 96 int err;
96 97
98 atomic_inc(&fc->num_waiting);
97 block_sigs(&oldset); 99 block_sigs(&oldset);
98 err = wait_event_interruptible(fc->blocked_waitq, !fc->blocked); 100 intr = wait_event_interruptible(fc->blocked_waitq, !fc->blocked);
99 restore_sigs(&oldset); 101 restore_sigs(&oldset);
100 if (err) 102 err = -EINTR;
101 return ERR_PTR(-EINTR); 103 if (intr)
104 goto out;
102 105
103 req = fuse_request_alloc(); 106 req = fuse_request_alloc();
107 err = -ENOMEM;
104 if (!req) 108 if (!req)
105 return ERR_PTR(-ENOMEM); 109 goto out;
106 110
107 atomic_inc(&fc->num_waiting);
108 fuse_request_init(req); 111 fuse_request_init(req);
109 req->in.h.uid = current->fsuid; 112 req->in.h.uid = current->fsuid;
110 req->in.h.gid = current->fsgid; 113 req->in.h.gid = current->fsgid;
111 req->in.h.pid = current->pid; 114 req->in.h.pid = current->pid;
115 req->waiting = 1;
112 return req; 116 return req;
117
118 out:
119 atomic_dec(&fc->num_waiting);
120 return ERR_PTR(err);
113} 121}
114 122
115void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req) 123void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req)
116{ 124{
117 if (atomic_dec_and_test(&req->count)) { 125 if (atomic_dec_and_test(&req->count)) {
118 atomic_dec(&fc->num_waiting); 126 if (req->waiting)
127 atomic_dec(&fc->num_waiting);
119 fuse_request_free(req); 128 fuse_request_free(req);
120 } 129 }
121} 130}
@@ -281,6 +290,10 @@ static void queue_request(struct fuse_conn *fc, struct fuse_req *req)
281 len_args(req->in.numargs, (struct fuse_arg *) req->in.args); 290 len_args(req->in.numargs, (struct fuse_arg *) req->in.args);
282 list_add_tail(&req->list, &fc->pending); 291 list_add_tail(&req->list, &fc->pending);
283 req->state = FUSE_REQ_PENDING; 292 req->state = FUSE_REQ_PENDING;
293 if (!req->waiting) {
294 req->waiting = 1;
295 atomic_inc(&fc->num_waiting);
296 }
284 wake_up(&fc->waitq); 297 wake_up(&fc->waitq);
285 kill_fasync(&fc->fasync, SIGIO, POLL_IN); 298 kill_fasync(&fc->fasync, SIGIO, POLL_IN);
286} 299}
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index ee9b83042510..59661c481d9d 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -159,6 +159,9 @@ struct fuse_req {
159 /** Data is being copied to/from the request */ 159 /** Data is being copied to/from the request */
160 unsigned locked:1; 160 unsigned locked:1;
161 161
162 /** Request is counted as "waiting" */
163 unsigned waiting:1;
164
162 /** State of the request */ 165 /** State of the request */
163 enum fuse_req_state state; 166 enum fuse_req_state state;
164 167