summaryrefslogtreecommitdiffstats
path: root/fs/fuse/inode.c
diff options
context:
space:
mode:
authorMiklos Szeredi <miklos@szeredi.hu>2006-01-16 22:14:41 -0800
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-16 23:15:30 -0800
commit69a53bf267fa58b89aa659d121dfe38436562a30 (patch)
tree36276fdbf7bfdc787708e8d5b2d4b79a0b5a4c56 /fs/fuse/inode.c
parent0cd5b88553acf0611474dbaf8e43770eed268060 (diff)
[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>
Diffstat (limited to 'fs/fuse/inode.c')
-rw-r--r--fs/fuse/inode.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 182235923cd..d359d8de22a 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -196,6 +196,11 @@ struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
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 @@ static struct super_operations fuse_super_operations = {
.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 @@ static ssize_t fuse_conn_waiting_show(struct fuse_conn *fc, char *page)
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,
};