From: Miklos Szeredi Date: Thu, 16 Feb 2006 10:08:32 +0000 (+0000) Subject: fix X-Git-Tag: fuse_2_6_0_pre1~6 X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=99ac9c0fde5815b16e5c724fe64be4dc47d5366d;p=qemu-gpiodev%2Flibfuse.git fix --- diff --git a/ChangeLog b/ChangeLog index 3b2f2d9..f3c3e89 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2006-02-16 Miklos Szeredi + + * Fix rare race betweeen abort and release caused by failed iget() + in fuse_create_open(). + 2006-02-15 Miklos Szeredi * Work around FreeBSD runtime linker "feature" which binds an old diff --git a/README b/README index 4c5517a..6333943 100644 --- 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: diff --git a/kernel/dev.c b/kernel/dev.c index d8b5683..d35fc07 100644 --- a/kernel/dev.c +++ b/kernel/dev.c @@ -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; diff --git a/kernel/file.c b/kernel/file.c index be9cc39..77c540e 100644 --- a/kernel/file.c +++ b/kernel/file.c @@ -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,