mirror of
https://github.com/ceph/ceph
synced 2025-02-23 19:17:37 +00:00
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:
parent
83ee85b840
commit
f16e571757
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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) {
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user