mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
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;



  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®