fix
authorMiklos Szeredi <miklos@szeredi.hu>
Thu, 16 Feb 2006 10:08:32 +0000 (10:08 +0000)
committerMiklos Szeredi <miklos@szeredi.hu>
Thu, 16 Feb 2006 10:08:32 +0000 (10:08 +0000)
ChangeLog
README
kernel/dev.c
kernel/file.c

index 3b2f2d966157817bfbcaf87c7b87b9887908ccad..f3c3e893d575089015c201eb84961d594f1cedce 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2006-02-16  Miklos Szeredi <miklos@szeredi.hu>
+
+       * Fix rare race betweeen abort and release caused by failed iget()
+       in fuse_create_open().
+
 2006-02-15  Miklos Szeredi <miklos@szeredi.hu>
 
        * Work around FreeBSD runtime linker "feature" which binds an old
diff --git a/README b/README
index 4c5517aa7827c72656da606bf23b73a9e9f690c4..6333943f58596a51a8760a240dcd530596b7b86b 100644 (file)
--- a/README
+++ b/README
@@ -44,7 +44,7 @@ be compiled.  It is possible to override this with the
 If './configure' cannot find the kernel source or it says the kernel
 source should be prepared, you may either try
 
-  ./configure--disable-kernel-module
+  ./configure --disable-kernel-module
 
 or if your kernel does not already contain FUSE support, do the
 following:
index d8b5683f255709125cca861ee9aa8a1c679d73e5..d35fc071fcf15da410de4c37429f5f07f76b644a 100644 (file)
@@ -106,6 +106,12 @@ static void restore_sigs(sigset_t *oldset)
 #endif
 #endif
 
+/*
+ * Reset request, so that it can be reused
+ *
+ * The caller must be _very_ careful to make sure, that it is holding
+ * the only reference to req
+ */
 void fuse_reset_request(struct fuse_req *req)
 {
        int preallocated = req->preallocated;
index be9cc391ee7faac84bb94d612fb0c618f2c4c42b..77c540eef51b1d7b5b01fc14e3924726997caa8f 100644 (file)
@@ -130,9 +130,14 @@ int fuse_open_common(struct inode *inode, struct file *file, int isdir)
 /* Special case for failed iget in CREATE */
 static void fuse_release_end(struct fuse_conn *fc, struct fuse_req *req)
 {
-       u64 nodeid = req->in.h.nodeid;
-       fuse_reset_request(req);
-       fuse_send_forget(fc, req, nodeid, 1);
+       /* If called from end_io_requests(), req has more than one
+          reference and fuse_reset_request() cannot work */
+       if (fc->connected) {
+               u64 nodeid = req->in.h.nodeid;
+               fuse_reset_request(req);
+               fuse_send_forget(fc, req, nodeid, 1);
+       } else
+               fuse_put_request(fc, req);
 }
 
 void fuse_send_release(struct fuse_conn *fc, struct fuse_file *ff,