Skip to content

Commit 6bdded5

Browse files
dhowellsAl Viro
authored andcommitted
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>
1 parent 62deb81 commit 6bdded5

File tree

2 files changed

+11
-0
lines changed

2 files changed

+11
-0
lines changed

fs/fscache/cookie.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,7 @@ void __fscache_disable_cookie(struct fscache_cookie *cookie, bool invalidate)
542542
hlist_for_each_entry(object, &cookie->backing_objects, cookie_link) {
543543
if (invalidate)
544544
set_bit(FSCACHE_OBJECT_RETIRED, &object->flags);
545+
clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags);
545546
fscache_raise_event(object, FSCACHE_OBJECT_EV_KILL);
546547
}
547548
} else {
@@ -560,6 +561,10 @@ void __fscache_disable_cookie(struct fscache_cookie *cookie, bool invalidate)
560561
wait_on_atomic_t(&cookie->n_active, fscache_wait_atomic_t,
561562
TASK_UNINTERRUPTIBLE);
562563

564+
/* Make sure any pending writes are cancelled. */
565+
if (cookie->def->type != FSCACHE_COOKIE_TYPE_INDEX)
566+
fscache_invalidate_writes(cookie);
567+
563568
/* Reset the cookie state if it wasn't relinquished */
564569
if (!test_bit(FSCACHE_COOKIE_RELINQUISHED, &cookie->flags)) {
565570
atomic_inc(&cookie->n_active);

fs/fscache/object.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,12 @@ static const struct fscache_state *fscache_kill_object(struct fscache_object *ob
645645
fscache_mark_object_dead(object);
646646
object->oob_event_mask = 0;
647647

648+
if (test_bit(FSCACHE_OBJECT_RETIRED, &object->flags)) {
649+
/* Reject any new read/write ops and abort any that are pending. */
650+
clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags);
651+
fscache_cancel_all_ops(object);
652+
}
653+
648654
if (list_empty(&object->dependents) &&
649655
object->n_ops == 0 &&
650656
object->n_children == 0)

0 commit comments

Comments
 (0)