Skip to content

Commit

Permalink
fscache: fix race between enablement and dropping of object
Browse files Browse the repository at this point in the history
[ Upstream commit c5a94f4 ]

It was observed that a process blocked indefintely in
__fscache_read_or_alloc_page(), waiting for FSCACHE_COOKIE_LOOKING_UP
to be cleared via fscache_wait_for_deferred_lookup().

At this time, ->backing_objects was empty, which would normaly prevent
__fscache_read_or_alloc_page() from getting to the point of waiting.
This implies that ->backing_objects was cleared *after*
__fscache_read_or_alloc_page was was entered.

When an object is "killed" and then "dropped",
FSCACHE_COOKIE_LOOKING_UP is cleared in fscache_lookup_failure(), then
KILL_OBJECT and DROP_OBJECT are "called" and only in DROP_OBJECT is
->backing_objects cleared.  This leaves a window where
something else can set FSCACHE_COOKIE_LOOKING_UP and
__fscache_read_or_alloc_page() can start waiting, before
->backing_objects is cleared

There is some uncertainty in this analysis, but it seems to be fit the
observations.  Adding the wake in this patch will be handled correctly
by __fscache_read_or_alloc_page(), as it checks if ->backing_objects
is empty again, after waiting.

Customer which reported the hang, also report that the hang cannot be
reproduced with this fix.

The backtrace for the blocked process looked like:

PID: 29360  TASK: ffff881ff2ac0f80  CPU: 3   COMMAND: "zsh"
 #0 [ffff881ff43efbf8] schedule at ffffffff815e56f1
 Freescale#1 [ffff881ff43efc58] bit_wait at ffffffff815e64ed
 Freescale#2 [ffff881ff43efc68] __wait_on_bit at ffffffff815e61b8
 Freescale#3 [ffff881ff43efca0] out_of_line_wait_on_bit at ffffffff815e625e
 Freescale#4 [ffff881ff43efd08] fscache_wait_for_deferred_lookup at ffffffffa04f2e8f [fscache]
 Freescale#5 [ffff881ff43efd18] __fscache_read_or_alloc_page at ffffffffa04f2ffe [fscache]
 Freescale#6 [ffff881ff43efd58] __nfs_readpage_from_fscache at ffffffffa0679668 [nfs]
 Freescale#7 [ffff881ff43efd78] nfs_readpage at ffffffffa067092b [nfs]
 Freescale#8 [ffff881ff43efda0] generic_file_read_iter at ffffffff81187a73
 Freescale#9 [ffff881ff43efe50] nfs_file_read at ffffffffa066544b [nfs]
Freescale#10 [ffff881ff43efe70] __vfs_read at ffffffff811fc756
Freescale#11 [ffff881ff43efee8] vfs_read at ffffffff811fccfa
Freescale#12 [ffff881ff43eff18] sys_read at ffffffff811fda62
Freescale#13 [ffff881ff43eff50] entry_SYSCALL_64_fastpath at ffffffff815e986e

Signed-off-by: NeilBrown <[email protected]>
Signed-off-by: David Howells <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>
  • Loading branch information
NeilBrown authored and gregkh committed Dec 17, 2018
1 parent b718d6b commit 38026d1
Showing 1 changed file with 3 additions and 0 deletions.
3 changes: 3 additions & 0 deletions fs/fscache/object.c
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,9 @@ static const struct fscache_state *fscache_drop_object(struct fscache_object *ob

if (awaken)
wake_up_bit(&cookie->flags, FSCACHE_COOKIE_INVALIDATING);
if (test_and_clear_bit(FSCACHE_COOKIE_LOOKING_UP, &cookie->flags))
wake_up_bit(&cookie->flags, FSCACHE_COOKIE_LOOKING_UP);


/* Prevent a race with our last child, which has to signal EV_CLEARED
* before dropping our spinlock.
Expand Down

0 comments on commit 38026d1

Please sign in to comment.