[PATCH] fuse: add connection aborting

Add ability to abort a filesystem connection.

With the introduction of asynchronous reads, the ability to interrupt any
request is not enough to dissolve deadlocks, since now waiting for the request
completion (page unlocked) is independent of the actual request, so in a
deadlock all threads will be uninterruptible.

The solution is to make it possible to abort all requests, even those
currently undergoing I/O to/from userspace.  The natural interface for this is
'mount -f mountpoint', but that only works as long as the filesystem is
attached.  So also add an 'abort' attribute to the sysfs view of the
connection.

Signed-off-by: Miklos Szeredi <miklos@szeredi.hu>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 1822359..d359d8d 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -196,6 +196,11 @@
 	return inode;
 }
 
+static void fuse_umount_begin(struct super_block *sb)
+{
+	fuse_abort_conn(get_fuse_conn_super(sb));
+}
+
 static void fuse_put_super(struct super_block *sb)
 {
 	struct fuse_conn *fc = get_fuse_conn_super(sb);
@@ -454,6 +459,7 @@
 	.read_inode	= fuse_read_inode,
 	.clear_inode	= fuse_clear_inode,
 	.put_super	= fuse_put_super,
+	.umount_begin	= fuse_umount_begin,
 	.statfs		= fuse_statfs,
 	.show_options	= fuse_show_options,
 };
@@ -560,11 +566,21 @@
 	return sprintf(page, "%i\n", atomic_read(&fc->num_waiting));
 }
 
+static ssize_t fuse_conn_abort_store(struct fuse_conn *fc, const char *page,
+				     size_t count)
+{
+	fuse_abort_conn(fc);
+	return count;
+}
+
 static struct fuse_conn_attr fuse_conn_waiting =
 	__ATTR(waiting, 0400, fuse_conn_waiting_show, NULL);
+static struct fuse_conn_attr fuse_conn_abort =
+	__ATTR(abort, 0600, NULL, fuse_conn_abort_store);
 
 static struct attribute *fuse_conn_attrs[] = {
 	&fuse_conn_waiting.attr,
+	&fuse_conn_abort.attr,
 	NULL,
 };