mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-22 01:51:51 +00:00
zdtm: add support for LD_PRELOAD tests
This commit adds a `--preload-libfault` option to ZDTM's run command. This option runs CRIU with LD_PRELOAD to intercept libc functions such as pread(). This method allows to simulate special cases, for example, when a successful call to pread() transfers fewer bytes than requested. Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
This commit is contained in:
parent
e7276cf63b
commit
1da29f27f6
@ -262,6 +262,9 @@ make -C test/others/rpc/ run
|
||||
|
||||
./test/zdtm.py run -t zdtm/static/env00 --sibling
|
||||
|
||||
./test/zdtm.py run -t zdtm/static/maps00 --preload-libfault
|
||||
./test/zdtm.py run -t zdtm/static/maps02 --preload-libfault
|
||||
|
||||
./test/zdtm.py run -t zdtm/transition/maps007 --pre 2 --dedup
|
||||
./test/zdtm.py run -t zdtm/transition/maps007 --pre 2 --noauto-dedup
|
||||
./test/zdtm.py run -t zdtm/transition/maps007 --pre 2 --page-server
|
||||
|
21
test/libfault/Makefile
Normal file
21
test/libfault/Makefile
Normal file
@ -0,0 +1,21 @@
|
||||
CC = gcc
|
||||
CFLAGS = -c -fPIC -ldl
|
||||
|
||||
SRC = libfault.c
|
||||
OBJ = $(SRC:.c=.o)
|
||||
|
||||
LIB = libfault.so
|
||||
|
||||
.PHONY: all clean run
|
||||
|
||||
all: $(LIB)
|
||||
|
||||
$(LIB): $(OBJ)
|
||||
$(CC) -shared -o $(LIB) $(OBJ)
|
||||
|
||||
$(OBJ): $(SRC)
|
||||
$(CC) $(CFLAGS) $<
|
||||
|
||||
clean:
|
||||
rm -f $(OBJ) $(LIB)
|
||||
|
31
test/libfault/libfault.c
Normal file
31
test/libfault/libfault.c
Normal file
@ -0,0 +1,31 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <unistd.h>
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
|
||||
ssize_t (*original_pread)(int fd, void *buf, size_t count, off_t offset) = NULL;
|
||||
|
||||
/**
|
||||
* This function is a wrapper around pread() that is used for testing CRIU's
|
||||
* handling of cases where pread() returns less data than requested.
|
||||
*
|
||||
* pmc_fill() in criu/pagemap.c is a good example of where this can happen.
|
||||
*/
|
||||
ssize_t pread64(int fd, void *buf, size_t count, off_t offset)
|
||||
{
|
||||
if (!original_pread) {
|
||||
original_pread = dlsym(RTLD_NEXT, "pread");
|
||||
if (!original_pread) {
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* The following aims to simulate the case when pread() returns less
|
||||
* data than requested. We need to ensure that CRIU handles such cases. */
|
||||
if (count > 2048) {
|
||||
count -= 1024;
|
||||
}
|
||||
|
||||
return original_pread(fd, buf, count, offset);
|
||||
}
|
23
test/zdtm.py
23
test/zdtm.py
@ -32,6 +32,14 @@ from zdtm.criu_config import criu_config
|
||||
# File to store content of streamed images
|
||||
STREAMED_IMG_FILE_NAME = "img.criu"
|
||||
|
||||
# A library used to preload C functions to simulate
|
||||
# cases such as partial read with pread().
|
||||
LIBFAULT_PATH = os.path.join(
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"libfault",
|
||||
"libfault.so"
|
||||
)
|
||||
|
||||
prev_line = None
|
||||
uuid = uuid.uuid4()
|
||||
|
||||
@ -628,6 +636,8 @@ class zdtm_test:
|
||||
["make", "zdtm_ct"], env=dict(os.environ, MAKEFLAGS=""))
|
||||
if not os.access("zdtm/lib/libzdtmtst.a", os.F_OK):
|
||||
subprocess.check_call(["make", "-C", "zdtm/"])
|
||||
if 'preload_libfault' in opts and opts['preload_libfault']:
|
||||
subprocess.check_call(["make", "-C", "libfault/"])
|
||||
if 'rootless' in opts and opts['rootless']:
|
||||
return
|
||||
subprocess.check_call(
|
||||
@ -880,6 +890,7 @@ class criu_cli:
|
||||
fault=None,
|
||||
strace=[],
|
||||
preexec=None,
|
||||
preload_libfault=False,
|
||||
nowait=False,
|
||||
timeout=60):
|
||||
env = dict(
|
||||
@ -890,6 +901,9 @@ class criu_cli:
|
||||
print("Forcing %s fault" % fault)
|
||||
env['CRIU_FAULT'] = fault
|
||||
|
||||
if preload_libfault:
|
||||
env['LD_PRELOAD'] = LIBFAULT_PATH
|
||||
|
||||
cr = subprocess.Popen(strace +
|
||||
[criu_bin, action, "--no-default-config"] + args,
|
||||
env=env,
|
||||
@ -980,6 +994,7 @@ class criu_rpc:
|
||||
fault=None,
|
||||
strace=[],
|
||||
preexec=None,
|
||||
preload_libfault=False,
|
||||
nowait=False,
|
||||
timeout=None):
|
||||
if fault:
|
||||
@ -1065,6 +1080,7 @@ class criu:
|
||||
self.__criu_bin = opts['criu_bin']
|
||||
self.__crit_bin = opts['crit_bin']
|
||||
self.__pre_dump_mode = opts['pre_dump_mode']
|
||||
self.__preload_libfault = bool(opts['preload_libfault'])
|
||||
self.__mntns_compat_mode = bool(opts['mntns_compat_mode'])
|
||||
|
||||
if opts['rpc']:
|
||||
@ -1192,8 +1208,10 @@ class criu:
|
||||
with open("/proc/sys/kernel/ns_last_pid") as ns_last_pid_fd:
|
||||
ns_last_pid = ns_last_pid_fd.read()
|
||||
|
||||
preload_libfault = self.__preload_libfault and action in ['dump', 'pre-dump', 'restore']
|
||||
|
||||
ret = self.__criu.run(action, s_args, self.__criu_bin, self.__fault,
|
||||
strace, preexec, nowait)
|
||||
strace, preexec, preload_libfault, nowait)
|
||||
|
||||
if nowait:
|
||||
os.close(status_fds[1])
|
||||
@ -2083,7 +2101,7 @@ class Launcher:
|
||||
'dedup', 'sbs', 'freezecg', 'user', 'dry_run', 'noauto_dedup',
|
||||
'remote_lazy_pages', 'show_stats', 'lazy_migrate', 'stream',
|
||||
'tls', 'criu_bin', 'crit_bin', 'pre_dump_mode', 'mntns_compat_mode',
|
||||
'rootless')
|
||||
'rootless', 'preload_libfault')
|
||||
arg = repr((name, desc, flavor, {d: self.__opts[d] for d in nd}))
|
||||
|
||||
if self.__use_log:
|
||||
@ -2788,6 +2806,7 @@ def get_cli_args():
|
||||
help="Select tests for a shard <index> (0-based)")
|
||||
rp.add_argument("--test-shard-count", type=int, default=0,
|
||||
help="Specify how many shards are being run (0=sharding disabled; must be the same for all shards)")
|
||||
rp.add_argument("--preload-libfault", action="store_true", help="Run criu with library preload to simulate special cases")
|
||||
|
||||
lp = sp.add_parser("list", help="List tests")
|
||||
lp.set_defaults(action=list_tests)
|
||||
|
@ -11,6 +11,7 @@ class criu_config:
|
||||
fault=None,
|
||||
strace=[],
|
||||
preexec=None,
|
||||
preload=False,
|
||||
nowait=False):
|
||||
|
||||
config_path = tempfile.mktemp(".conf", "criu-%s-" % action)
|
||||
|
Loading…
x
Reference in New Issue
Block a user