diff options
author | Bryan Green <bryan@grid-net.com> | 2011-03-01 16:43:52 -0800 |
---|---|---|
committer | Miklos Szeredi <mszeredi@suse.cz> | 2011-03-21 13:58:05 +0100 |
commit | 357ccf2b69bcefa650a54db83702381d1c9d6959 (patch) | |
tree | 0bbcbb308b0a28a489d38177a4ad7b84b1ae36d5 | |
parent | 07d5f69b457019eda4ca568923b1d62b7ada89e1 (diff) | |
download | linux-3.10-357ccf2b69bcefa650a54db83702381d1c9d6959.tar.gz linux-3.10-357ccf2b69bcefa650a54db83702381d1c9d6959.tar.bz2 linux-3.10-357ccf2b69bcefa650a54db83702381d1c9d6959.zip |
fuse: wakeup pollers on connection release/abort
If a fuse dev connection is broken, wake up any
processes that are blocking, in a poll system call,
on one of the files in the now defunct filesystem.
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
-rw-r--r-- | fs/fuse/dev.c | 17 | ||||
-rw-r--r-- | fs/fuse/file.c | 2 |
2 files changed, 18 insertions, 1 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index cf8d28d1fba..213d3cf4f5e 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -1910,6 +1910,21 @@ __acquires(fc->lock) kfree(dequeue_forget(fc, 1, NULL)); } +static void end_polls(struct fuse_conn *fc) +{ + struct rb_node *p; + + p = rb_first(&fc->polled_files); + + while (p) { + struct fuse_file *ff; + ff = rb_entry(p, struct fuse_file, polled_node); + wake_up_interruptible_all(&ff->poll_wait); + + p = rb_next(p); + } +} + /* * Abort all requests. * @@ -1937,6 +1952,7 @@ void fuse_abort_conn(struct fuse_conn *fc) fc->blocked = 0; end_io_requests(fc); end_queued_requests(fc); + end_polls(fc); wake_up_all(&fc->waitq); wake_up_all(&fc->blocked_waitq); kill_fasync(&fc->fasync, SIGIO, POLL_IN); @@ -1953,6 +1969,7 @@ int fuse_dev_release(struct inode *inode, struct file *file) fc->connected = 0; fc->blocked = 0; end_queued_requests(fc); + end_polls(fc); wake_up_all(&fc->blocked_waitq); spin_unlock(&fc->lock); fuse_conn_put(fc); diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 9e0832dbb1e..6ea00734984 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -222,7 +222,7 @@ static void fuse_prepare_release(struct fuse_file *ff, int flags, int opcode) rb_erase(&ff->polled_node, &fc->polled_files); spin_unlock(&fc->lock); - wake_up_interruptible_sync(&ff->poll_wait); + wake_up_interruptible_all(&ff->poll_wait); inarg->fh = ff->fh; inarg->flags = flags; |