summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Szeredi <miklos@szeredi.hu>2006-01-14 14:47:21 +0000
committerMiklos Szeredi <miklos@szeredi.hu>2006-01-14 14:47:21 +0000
commit9db5faa842b930ef2dd3557a8e26c34dfc94d6a8 (patch)
tree24e21cc74532ccc7b32b4965c7dfbcadb33c31d5
parenta982034e890ffb38926e478e3ce61c5cfd8f4a27 (diff)
downloadfuse-9db5faa842b930ef2dd3557a8e26c34dfc94d6a8.tar.gz
fix
-rw-r--r--ChangeLog11
-rw-r--r--kernel/dev.c12
-rw-r--r--kernel/fuse_i.h4
3 files changed, 18 insertions, 9 deletions
diff --git a/ChangeLog b/ChangeLog
index 5578982..a174eef 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2006-01-14 Miklos Szeredi <miklos@szeredi.hu>
+
+ * kernel: fix a couple of bugs
+
+ * Order of request_end() and fuse_copy_finish() was wrong
+
+ * request_end() used request pointer after decrementing refcount
+
+ * Clearing ->connected or ->mounted connection flags could race
+ with setting other bitfields not protected with a lock
+
2006-01-10 Miklos Szeredi <miklos@szeredi.hu>
* kernel: add necessary compile flags for 2.4.X/x86_64.
diff --git a/kernel/dev.c b/kernel/dev.c
index 073333f..3880f13 100644
--- a/kernel/dev.c
+++ b/kernel/dev.c
@@ -221,9 +221,7 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
*/
static void request_end(struct fuse_conn *fc, struct fuse_req *req)
{
- int putback;
req->finished = 1;
- putback = atomic_dec_and_test(&req->count);
spin_unlock(&fuse_lock);
if (req->background) {
down_read(&fc->sbput_sem);
@@ -237,13 +235,11 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req)
else if (req->in.h.opcode == FUSE_RELEASE && req->inode == NULL) {
/* Special case for failed iget in CREATE */
u64 nodeid = req->in.h.nodeid;
- __fuse_get_request(req);
fuse_reset_request(req);
fuse_send_forget(fc, req, nodeid, 1);
- putback = 0;
+ return;
}
- if (putback)
- fuse_putback_request(fc, req);
+ fuse_put_request(fc, req);
}
/*
@@ -824,8 +820,10 @@ static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov,
list_del_init(&req->list);
if (req->interrupted) {
- request_end(fc, req);
+ spin_unlock(&fuse_lock);
fuse_copy_finish(&cs);
+ spin_lock(&fuse_lock);
+ request_end(fc, req);
return -ENOENT;
}
req->out.h = oh;
diff --git a/kernel/fuse_i.h b/kernel/fuse_i.h
index 335b0c8..84e17dc 100644
--- a/kernel/fuse_i.h
+++ b/kernel/fuse_i.h
@@ -315,10 +315,10 @@ struct fuse_conn {
u64 reqctr;
/** Mount is active */
- unsigned mounted : 1;
+ unsigned mounted;
/** Connection established */
- unsigned connected : 1;
+ unsigned connected;
/** Connection failed (version mismatch) */
unsigned conn_error : 1;