Skip to content
This repository has been archived by the owner on Feb 26, 2020. It is now read-only.

Commit

Permalink
splat linux:shrinker: Fix race condition
Browse files Browse the repository at this point in the history
Ensure the test thread blocks until the shrinker has completed its
work.  This is done by putting the test thread to sleep and waking
it each time the shrinker callback runs.  Once the shrinker size
drops to zero or we time out the test is allowed to proceed.

Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #96
Closes #125
Closes #182
  • Loading branch information
Steven Johnson authored and behlendorf committed Dec 12, 2012
1 parent 576ec6a commit ca072ee
Showing 1 changed file with 27 additions and 1 deletion.
28 changes: 27 additions & 1 deletion module/splat/splat-linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,12 @@ splat_linux_test2(struct file *file, void *arg)
return 0;
}

/*
* Wait queue used to eliminate race between dropping of slab
* and execution of the shrinker callback
*/
DECLARE_WAIT_QUEUE_HEAD(shrinker_wait);

SPL_SHRINKER_CALLBACK_FWD_DECLARE(splat_linux_shrinker_fn);
SPL_SHRINKER_DECLARE(splat_linux_shrinker, splat_linux_shrinker_fn, 1);
static unsigned long splat_linux_shrinker_size = 0;
Expand Down Expand Up @@ -116,6 +122,9 @@ __splat_linux_shrinker_fn(struct shrinker *shrink, struct shrink_control *sc)
return -1;
}

/* Shrinker has run, so signal back to test. */
wake_up(&shrinker_wait);

return (int)splat_linux_shrinker_size;
}

Expand Down Expand Up @@ -183,7 +192,24 @@ splat_linux_test3(struct file *file, void *arg)
if (rc)
goto out;

if (splat_linux_shrinker_size != 0) {
/*
* By the time we get here, it is possible that the shrinker has not
* yet run. splat_linux_drop_slab sends a signal for it to run, but
* there is no guarantee of when it will actually run. We wait for it
* to run here, terminating when either the shrinker size is now 0 or
* we timeout after 1 second, which should be an eternity (error).
*/
rc = wait_event_timeout(shrinker_wait, !splat_linux_shrinker_size, HZ);
if (!rc) {
splat_vprint(file, SPLAT_LINUX_TEST3_NAME,
"Failed cache shrinking timed out, size now %lu",
splat_linux_shrinker_size);
rc = -ETIMEDOUT;
} else {
rc = 0;
}

if (!rc && splat_linux_shrinker_size != 0) {
splat_vprint(file, SPLAT_LINUX_TEST3_NAME,
"Failed cache was not shrunk to 0, size now %lu",
splat_linux_shrinker_size);
Expand Down

0 comments on commit ca072ee

Please sign in to comment.