client: Add config option to inject sleep for tick

Testing the tick delay with a fork/suspend is causing
corruption in the lockdep code.  This approach uses
a config option to sleep the tick thread for a number
of seconds, avoiding the entire fork/suspend mess.

Signed-off-by: Sam Lang <sam.lang@inktank.com>
This commit is contained in:
Sam Lang 2012-12-13 17:23:27 -10:00
parent 83ee85b840
commit f16e571757
3 changed files with 9 additions and 48 deletions

View File

@ -3656,6 +3656,12 @@ void Client::flush_cap_releases()
void Client::tick()
{
if (cct->_conf->client_debug_inject_tick_delay > 0) {
sleep(cct->_conf->client_debug_inject_tick_delay);
assert(0 == cct->_conf->set_val("client_debug_inject_tick_delay", "0"));
cct->_conf->apply_changes(NULL);
}
ldout(cct, 21) << "tick" << dendl;
tick_event = new C_C_Tick(this);
timer.add_event_after(cct->_conf->client_tick_interval, tick_event);

View File

@ -183,6 +183,7 @@ OPTION(client_oc_target_dirty, OPT_INT, 1024*1024* 8) // target dirty (keep this
OPTION(client_oc_max_dirty_age, OPT_DOUBLE, 5.0) // max age in cache before writeback
OPTION(client_oc_max_objects, OPT_INT, 1000) // max objects in cache
OPTION(client_debug_force_sync_read, OPT_BOOL, false) // always read synchronously (go to osds)
OPTION(client_debug_inject_tick_delay, OPT_INT, 0) // delay the client tick for a number of seconds
// note: the max amount of "in flight" dirty data is roughly (max - target)
OPTION(fuse_use_invalidate_cb, OPT_BOOL, false) // use fuse 2.8+ invalidate callback to keep page cache consistent
OPTION(fuse_big_writes, OPT_BOOL, true)

View File

@ -26,60 +26,14 @@
#include <sys/xattr.h>
#include <signal.h>
void do_sigusr1(int s) {}
// wait_and_suspend() forks the process, waits for the
// child to signal SIGUSR1, suspends the child with SIGSTOP
// sleeps for s seconds, and then unsuspends the child,
// waits for the child to exit, and then returns the exit code
// of the child
static int _wait_and_suspend(int s) {
int fpid = fork();
if (fpid != 0) {
// wait for child to signal
signal(SIGUSR1, &do_sigusr1);
sigset_t set;
sigaddset(&set, SIGUSR1);
int sig;
sigwait(&set, &sig);
// fork and suspend child, sleep for 20 secs, and resume
kill(fpid, SIGSTOP);
sleep(s);
kill(fpid, SIGCONT);
int status;
wait(&status);
if (WIFEXITED(status))
return WEXITSTATUS(status);
return 1;
}
return -1;
}
// signal_for_suspend sends the parent the SIGUSR1 signal
// and sleeps for 1 second so that it can be suspended at the
// point of the call
static void _signal_for_suspend() {
kill(getppid(), SIGUSR1);
}
TEST(Caps, ReadZero) {
int w = _wait_and_suspend(20);
if (w >= 0) {
ASSERT_EQ(0, w);
return;
}
pid_t mypid = getpid();
int mypid = getpid();
struct ceph_mount_info *cmount;
ASSERT_EQ(0, ceph_create(&cmount, NULL));
ASSERT_EQ(0, ceph_conf_read_file(cmount, NULL));
ASSERT_EQ(0, ceph_mount(cmount, "/"));
ASSERT_EQ(0, ceph_conf_set(cmount, "client_cache_size", "10"));
int i = 0;
for(; i < 30; ++i) {
@ -114,7 +68,7 @@ TEST(Caps, ReadZero) {
ASSERT_EQ(expect, caps & expect);
}
_signal_for_suspend();
ASSERT_EQ(0, ceph_conf_set(cmount, "client_debug_inject_tick_delay", "20"));
for(i = 0; i < 30; ++i) {