aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiklos Szeredi <miklos@szeredi.hu>2006-01-17 01:14:26 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-17 02:15:29 -0500
commitf43b155a5a8a95b06bc0b4474fbb7311c7e9709a (patch)
tree482a03476b71498939adb9aa7ec1a4c072902927
parent222f1d69183f10d70a37de5785698fe0aa363c12 (diff)
[PATCH] fuse: fix request_end()
This function used the request object after decrementing its reference count and releasing the lock. This could in theory lead to all sorts of problems. Fix and simplify at the same time. Signed-off-by: Miklos Szeredi <miklos@szeredi.hu> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--fs/fuse/dev.c18
1 files changed, 7 insertions, 11 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 9af88953db69..de402e4d8bce 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -171,19 +171,17 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
171/* 171/*
172 * This function is called when a request is finished. Either a reply 172 * This function is called when a request is finished. Either a reply
173 * has arrived or it was interrupted (and not yet sent) or some error 173 * has arrived or it was interrupted (and not yet sent) or some error
174 * occurred during communication with userspace, or the device file was 174 * occurred during communication with userspace, or the device file
175 * closed. It decreases the reference count for the request. In case 175 * was closed. In case of a background request the reference to the
176 * of a background request the reference to the stored objects are 176 * stored objects are released. The requester thread is woken up (if
177 * released. The requester thread is woken up (if still waiting), and 177 * still waiting), and finally the reference to the request is
178 * finally the request is either freed or put on the unused_list 178 * released
179 * 179 *
180 * Called with fuse_lock, unlocks it 180 * Called with fuse_lock, unlocks it
181 */ 181 */
182static void request_end(struct fuse_conn *fc, struct fuse_req *req) 182static void request_end(struct fuse_conn *fc, struct fuse_req *req)
183{ 183{
184 int putback;
185 req->finished = 1; 184 req->finished = 1;
186 putback = atomic_dec_and_test(&req->count);
187 spin_unlock(&fuse_lock); 185 spin_unlock(&fuse_lock);
188 if (req->background) { 186 if (req->background) {
189 down_read(&fc->sbput_sem); 187 down_read(&fc->sbput_sem);
@@ -197,13 +195,11 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req)
197 else if (req->in.h.opcode == FUSE_RELEASE && req->inode == NULL) { 195 else if (req->in.h.opcode == FUSE_RELEASE && req->inode == NULL) {
198 /* Special case for failed iget in CREATE */ 196 /* Special case for failed iget in CREATE */
199 u64 nodeid = req->in.h.nodeid; 197 u64 nodeid = req->in.h.nodeid;
200 __fuse_get_request(req);
201 fuse_reset_request(req); 198 fuse_reset_request(req);
202 fuse_send_forget(fc, req, nodeid, 1); 199 fuse_send_forget(fc, req, nodeid, 1);
203 putback = 0; 200 return;
204 } 201 }
205 if (putback) 202 fuse_put_request(fc, req);
206 fuse_putback_request(fc, req);
207} 203}
208 204
209/* 205/*