diff options
author | Bryan Green <bryan@grid-net.com> | 2011-03-01 19:43:52 -0500 |
---|---|---|
committer | Miklos Szeredi <mszeredi@suse.cz> | 2011-03-21 08:58:05 -0400 |
commit | 357ccf2b69bcefa650a54db83702381d1c9d6959 (patch) | |
tree | 0bbcbb308b0a28a489d38177a4ad7b84b1ae36d5 /fs/fuse | |
parent | 07d5f69b457019eda4ca568923b1d62b7ada89e1 (diff) |
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>
Diffstat (limited to 'fs/fuse')
-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 cf8d28d1fbad..213d3cf4f5e9 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
@@ -1910,6 +1910,21 @@ __acquires(fc->lock) | |||
1910 | kfree(dequeue_forget(fc, 1, NULL)); | 1910 | kfree(dequeue_forget(fc, 1, NULL)); |
1911 | } | 1911 | } |
1912 | 1912 | ||
1913 | static void end_polls(struct fuse_conn *fc) | ||
1914 | { | ||
1915 | struct rb_node *p; | ||
1916 | |||
1917 | p = rb_first(&fc->polled_files); | ||
1918 | |||
1919 | while (p) { | ||
1920 | struct fuse_file *ff; | ||
1921 | ff = rb_entry(p, struct fuse_file, polled_node); | ||
1922 | wake_up_interruptible_all(&ff->poll_wait); | ||
1923 | |||
1924 | p = rb_next(p); | ||
1925 | } | ||
1926 | } | ||
1927 | |||
1913 | /* | 1928 | /* |
1914 | * Abort all requests. | 1929 | * Abort all requests. |
1915 | * | 1930 | * |
@@ -1937,6 +1952,7 @@ void fuse_abort_conn(struct fuse_conn *fc) | |||
1937 | fc->blocked = 0; | 1952 | fc->blocked = 0; |
1938 | end_io_requests(fc); | 1953 | end_io_requests(fc); |
1939 | end_queued_requests(fc); | 1954 | end_queued_requests(fc); |
1955 | end_polls(fc); | ||
1940 | wake_up_all(&fc->waitq); | 1956 | wake_up_all(&fc->waitq); |
1941 | wake_up_all(&fc->blocked_waitq); | 1957 | wake_up_all(&fc->blocked_waitq); |
1942 | kill_fasync(&fc->fasync, SIGIO, POLL_IN); | 1958 | kill_fasync(&fc->fasync, SIGIO, POLL_IN); |
@@ -1953,6 +1969,7 @@ int fuse_dev_release(struct inode *inode, struct file *file) | |||
1953 | fc->connected = 0; | 1969 | fc->connected = 0; |
1954 | fc->blocked = 0; | 1970 | fc->blocked = 0; |
1955 | end_queued_requests(fc); | 1971 | end_queued_requests(fc); |
1972 | end_polls(fc); | ||
1956 | wake_up_all(&fc->blocked_waitq); | 1973 | wake_up_all(&fc->blocked_waitq); |
1957 | spin_unlock(&fc->lock); | 1974 | spin_unlock(&fc->lock); |
1958 | fuse_conn_put(fc); | 1975 | fuse_conn_put(fc); |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 9e0832dbb1e3..6ea00734984e 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) | |||
222 | rb_erase(&ff->polled_node, &fc->polled_files); | 222 | rb_erase(&ff->polled_node, &fc->polled_files); |
223 | spin_unlock(&fc->lock); | 223 | spin_unlock(&fc->lock); |
224 | 224 | ||
225 | wake_up_interruptible_sync(&ff->poll_wait); | 225 | wake_up_interruptible_all(&ff->poll_wait); |
226 | 226 | ||
227 | inarg->fh = ff->fh; | 227 | inarg->fh = ff->fh; |
228 | inarg->flags = flags; | 228 | inarg->flags = flags; |