aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fscache/object.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2017-01-18 14:29:25 +0000
committerAl Viro <viro@zeniv.linux.org.uk>2017-01-31 13:23:09 -0500
commit6bdded59c8933940ac7e5b416448276ac89d1144 (patch)
tree0620c0018aef6e596711114622e40d2f408e4bd3 /fs/fscache/object.c
parentFS-Cache: Initialise stores_lock in netfs cookie (diff)
downloadlinux-dev-6bdded59c8933940ac7e5b416448276ac89d1144.tar.xz
linux-dev-6bdded59c8933940ac7e5b416448276ac89d1144.zip
fscache: Clear outstanding writes when disabling a cookie
fscache_disable_cookie() needs to clear the outstanding writes on the cookie it's disabling because they cannot be completed after. Without this, fscache_nfs_open_file() gets stuck because it disables the cookie when the file is opened for writing but can't uncache the pages till afterwards - otherwise there's a race between the open routine and anyone who already has it open R/O and is still reading from it. Looking in /proc/pid/stack of the offending process shows: [<ffffffffa0142883>] __fscache_wait_on_page_write+0x82/0x9b [fscache] [<ffffffffa014336e>] __fscache_uncache_all_inode_pages+0x91/0xe1 [fscache] [<ffffffffa01740fa>] nfs_fscache_open_file+0x59/0x9e [nfs] [<ffffffffa01ccf41>] nfs4_file_open+0x17f/0x1b8 [nfsv4] [<ffffffff8117350e>] do_dentry_open+0x16d/0x2b7 [<ffffffff811743ac>] vfs_open+0x5c/0x65 [<ffffffff81184185>] path_openat+0x785/0x8fb [<ffffffff81184343>] do_filp_open+0x48/0x9e [<ffffffff81174710>] do_sys_open+0x13b/0x1cb [<ffffffff811747b9>] SyS_open+0x19/0x1b [<ffffffff81001c44>] do_syscall_64+0x80/0x17a [<ffffffff8165c2da>] return_from_SYSCALL_64+0x0/0x7a [<ffffffffffffffff>] 0xffffffffffffffff Reported-by: Jianhong Yin <jiyin@redhat.com> Signed-off-by: David Howells <dhowells@redhat.com> Acked-by: Jeff Layton <jlayton@redhat.com> Acked-by: Steve Dickson <steved@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to '')
-rw-r--r--fs/fscache/object.c6
1 files changed, 6 insertions, 0 deletions
diff --git a/fs/fscache/object.c b/fs/fscache/object.c
index 9e792e30f4db..be02a086ed9b 100644
--- a/fs/fscache/object.c
+++ b/fs/fscache/object.c
@@ -645,6 +645,12 @@ static const struct fscache_state *fscache_kill_object(struct fscache_object *ob
fscache_mark_object_dead(object);
object->oob_event_mask = 0;
+ if (test_bit(FSCACHE_OBJECT_RETIRED, &object->flags)) {
+ /* Reject any new read/write ops and abort any that are pending. */
+ clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags);
+ fscache_cancel_all_ops(object);
+ }
+
if (list_empty(&object->dependents) &&
object->n_ops == 0 &&
object->n_children == 0)