aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse/dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/fuse/dev.c')
-rw-r--r--fs/fuse/dev.c54
1 files changed, 35 insertions, 19 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 6c740f860665..cc750c68fe70 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -92,48 +92,50 @@ 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);
109 req->in.h.uid = current->fsuid; 111 req->in.h.uid = current->fsuid;
110 req->in.h.gid = current->fsgid; 112 req->in.h.gid = current->fsgid;
111 req->in.h.pid = current->pid; 113 req->in.h.pid = current->pid;
114 req->waiting = 1;
112 return req; 115 return req;
116
117 out:
118 atomic_dec(&fc->num_waiting);
119 return ERR_PTR(err);
113} 120}
114 121
115void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req) 122void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req)
116{ 123{
117 if (atomic_dec_and_test(&req->count)) { 124 if (atomic_dec_and_test(&req->count)) {
118 atomic_dec(&fc->num_waiting); 125 if (req->waiting)
126 atomic_dec(&fc->num_waiting);
119 fuse_request_free(req); 127 fuse_request_free(req);
120 } 128 }
121} 129}
122 130
123void fuse_release_background(struct fuse_conn *fc, struct fuse_req *req) 131void fuse_remove_background(struct fuse_conn *fc, struct fuse_req *req)
124{ 132{
125 iput(req->inode); 133 list_del_init(&req->bg_entry);
126 iput(req->inode2);
127 if (req->file)
128 fput(req->file);
129 spin_lock(&fc->lock);
130 list_del(&req->bg_entry);
131 if (fc->num_background == FUSE_MAX_BACKGROUND) { 134 if (fc->num_background == FUSE_MAX_BACKGROUND) {
132 fc->blocked = 0; 135 fc->blocked = 0;
133 wake_up_all(&fc->blocked_waitq); 136 wake_up_all(&fc->blocked_waitq);
134 } 137 }
135 fc->num_background--; 138 fc->num_background--;
136 spin_unlock(&fc->lock);
137} 139}
138 140
139/* 141/*
@@ -163,17 +165,27 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req)
163 wake_up(&req->waitq); 165 wake_up(&req->waitq);
164 fuse_put_request(fc, req); 166 fuse_put_request(fc, req);
165 } else { 167 } else {
168 struct inode *inode = req->inode;
169 struct inode *inode2 = req->inode2;
170 struct file *file = req->file;
166 void (*end) (struct fuse_conn *, struct fuse_req *) = req->end; 171 void (*end) (struct fuse_conn *, struct fuse_req *) = req->end;
167 req->end = NULL; 172 req->end = NULL;
173 req->inode = NULL;
174 req->inode2 = NULL;
175 req->file = NULL;
176 if (!list_empty(&req->bg_entry))
177 fuse_remove_background(fc, req);
168 spin_unlock(&fc->lock); 178 spin_unlock(&fc->lock);
169 down_read(&fc->sbput_sem); 179
170 if (fc->mounted)
171 fuse_release_background(fc, req);
172 up_read(&fc->sbput_sem);
173 if (end) 180 if (end)
174 end(fc, req); 181 end(fc, req);
175 else 182 else
176 fuse_put_request(fc, req); 183 fuse_put_request(fc, req);
184
185 if (file)
186 fput(file);
187 iput(inode);
188 iput(inode2);
177 } 189 }
178} 190}
179 191
@@ -277,6 +289,10 @@ static void queue_request(struct fuse_conn *fc, struct fuse_req *req)
277 len_args(req->in.numargs, (struct fuse_arg *) req->in.args); 289 len_args(req->in.numargs, (struct fuse_arg *) req->in.args);
278 list_add_tail(&req->list, &fc->pending); 290 list_add_tail(&req->list, &fc->pending);
279 req->state = FUSE_REQ_PENDING; 291 req->state = FUSE_REQ_PENDING;
292 if (!req->waiting) {
293 req->waiting = 1;
294 atomic_inc(&fc->num_waiting);
295 }
280 wake_up(&fc->waitq); 296 wake_up(&fc->waitq);
281 kill_fasync(&fc->fasync, SIGIO, POLL_IN); 297 kill_fasync(&fc->fasync, SIGIO, POLL_IN);
282} 298}