From: Greg KH <gregkh@suse.de>
To: linux-kernel@vger.kernel.org, stable@kernel.org
Cc: stable-review@kernel.org, torvalds@linux-foundation.org,
akpm@linux-foundation.org, alan@lxorguk.ukuu.org.uk,
Miklos Szeredi <mszeredi@suse.cz>
Subject: [05/18] fuse: fix hang of single threaded fuseblk filesystem
Date: Fri, 04 Mar 2011 17:02:59 -0800 [thread overview]
Message-ID: <20110305010352.308656138@clark.kroah.org> (raw)
In-Reply-To: <20110305010410.GA18668@kroah.com>
2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Miklos Szeredi <mszeredi@suse.cz>
commit 5a18ec176c934ca1bc9dc61580a5e0e90a9b5733 upstream.
Single threaded NTFS-3G could get stuck if a delayed RELEASE reply
triggered a DESTROY request via path_put().
Fix this by
a) making RELEASE requests synchronous, whenever possible, on fuseblk
filesystems
b) if not possible (triggered by an asynchronous read/write) then do
the path_put() in a separate thread with schedule_work().
Reported-by: Oliver Neukum <oneukum@suse.de>
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
fs/fuse/file.c | 52 +++++++++++++++++++++++++++++++++++++++++++++-------
fs/fuse/fuse_i.h | 6 +++++-
2 files changed, 50 insertions(+), 8 deletions(-)
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -86,18 +86,52 @@ struct fuse_file *fuse_file_get(struct f
return ff;
}
+static void fuse_release_async(struct work_struct *work)
+{
+ struct fuse_req *req;
+ struct fuse_conn *fc;
+ struct path path;
+
+ req = container_of(work, struct fuse_req, misc.release.work);
+ path = req->misc.release.path;
+ fc = get_fuse_conn(path.dentry->d_inode);
+
+ fuse_put_request(fc, req);
+ path_put(&path);
+}
+
static void fuse_release_end(struct fuse_conn *fc, struct fuse_req *req)
{
- path_put(&req->misc.release.path);
+ if (fc->destroy_req) {
+ /*
+ * If this is a fuseblk mount, then it's possible that
+ * releasing the path will result in releasing the
+ * super block and sending the DESTROY request. If
+ * the server is single threaded, this would hang.
+ * For this reason do the path_put() in a separate
+ * thread.
+ */
+ atomic_inc(&req->count);
+ INIT_WORK(&req->misc.release.work, fuse_release_async);
+ schedule_work(&req->misc.release.work);
+ } else {
+ path_put(&req->misc.release.path);
+ }
}
-static void fuse_file_put(struct fuse_file *ff)
+static void fuse_file_put(struct fuse_file *ff, bool sync)
{
if (atomic_dec_and_test(&ff->count)) {
struct fuse_req *req = ff->reserved_req;
- req->end = fuse_release_end;
- fuse_request_send_background(ff->fc, req);
+ if (sync) {
+ fuse_request_send(ff->fc, req);
+ path_put(&req->misc.release.path);
+ fuse_put_request(ff->fc, req);
+ } else {
+ req->end = fuse_release_end;
+ fuse_request_send_background(ff->fc, req);
+ }
kfree(ff);
}
}
@@ -219,8 +253,12 @@ void fuse_release_common(struct file *fi
* Normally this will send the RELEASE request, however if
* some asynchronous READ or WRITE requests are outstanding,
* the sending will be delayed.
+ *
+ * Make the release synchronous if this is a fuseblk mount,
+ * synchronous RELEASE is allowed (and desirable) in this case
+ * because the server can be trusted not to screw up.
*/
- fuse_file_put(ff);
+ fuse_file_put(ff, ff->fc->destroy_req != NULL);
}
static int fuse_open(struct inode *inode, struct file *file)
@@ -549,7 +587,7 @@ static void fuse_readpages_end(struct fu
unlock_page(page);
}
if (req->ff)
- fuse_file_put(req->ff);
+ fuse_file_put(req->ff, false);
}
static void fuse_send_readpages(struct fuse_req *req, struct file *file)
@@ -1129,7 +1167,7 @@ static ssize_t fuse_direct_write(struct
static void fuse_writepage_free(struct fuse_conn *fc, struct fuse_req *req)
{
__free_page(req->pages[0]);
- fuse_file_put(req->ff);
+ fuse_file_put(req->ff, false);
}
static void fuse_writepage_finish(struct fuse_conn *fc, struct fuse_req *req)
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -21,6 +21,7 @@
#include <linux/rwsem.h>
#include <linux/rbtree.h>
#include <linux/poll.h>
+#include <linux/workqueue.h>
/** Max number of pages that can be used in a single read request */
#define FUSE_MAX_PAGES_PER_REQ 32
@@ -254,7 +255,10 @@ struct fuse_req {
union {
struct fuse_forget_in forget_in;
struct {
- struct fuse_release_in in;
+ union {
+ struct fuse_release_in in;
+ struct work_struct work;
+ };
struct path path;
} release;
struct fuse_init_in init_in;
next prev parent reply other threads:[~2011-03-05 1:08 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-03-05 1:04 [00/18] 2.6.32.32-longterm review Greg KH
2011-03-05 1:02 ` [01/18] Ocfs2/refcounttree: Fix a bug for refcounttree to writeback clusters in a right number Greg KH
2011-03-05 1:02 ` [02/18] drm: fix unsigned vs signed comparison issue in modeset ctl ioctl Greg KH
2011-03-05 1:02 ` [03/18] mfd: Fix NULL pointer due to non-initialized ucb1x00-ts absinfo Greg KH
2011-03-05 1:02 ` [04/18] x86: Use u32 instead of long to set reset vector back to 0 Greg KH
2011-03-05 1:02 ` Greg KH [this message]
2011-03-05 1:03 ` [06/18] clockevents: Prevent oneshot mode when broadcast device is periodic Greg KH
2011-03-05 1:03 ` [07/18] ext2: Fix link count corruption under heavy link+rename load Greg KH
2011-03-05 1:03 ` [08/18] sctp: Fix oops when sending queued ASCONF chunks Greg KH
2011-03-05 1:03 ` [09/18] virtio: set pci bus master enable bit Greg KH
2011-03-05 1:03 ` [10/18] netxen: fix set mac addr Greg KH
2011-03-05 1:03 ` [11/18] HID: add support for Acan FG-8100 barcode reader Greg KH
2011-03-05 1:03 ` [12/18] p54usb: add Senao NUB-350 usbid Greg KH
2011-03-05 1:03 ` [13/18] dccp: fix oops on Reset after close Greg KH
2011-03-05 1:03 ` [14/18] e1000e: disable broken PHY wakeup for ICH10 LOMs, use MAC wakeup instead Greg KH
2011-03-05 1:03 ` [15/18] r8169: disable ASPM Greg KH
2011-03-05 1:03 ` [16/18] usb: iowarrior: dont trust report_size for buffer size Greg KH
2011-03-05 1:03 ` [17/18] arp_notify: unconditionally send gratuitous ARP for NETDEV_NOTIFY_PEERS Greg KH
2011-03-05 9:36 ` Ian Campbell
2011-03-05 17:45 ` Mike Surcouf
2011-03-05 1:03 ` [18/18] CIFS: Fix oplock break handling (try #2) Greg KH
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20110305010352.308656138@clark.kroah.org \
--to=gregkh@suse.de \
--cc=akpm@linux-foundation.org \
--cc=alan@lxorguk.ukuu.org.uk \
--cc=linux-kernel@vger.kernel.org \
--cc=mszeredi@suse.cz \
--cc=stable-review@kernel.org \
--cc=stable@kernel.org \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®