mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-22 09:58:09 +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/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 --dedup
|
||||||
./test/zdtm.py run -t zdtm/transition/maps007 --pre 2 --noauto-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
|
./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
|
# File to store content of streamed images
|
||||||
STREAMED_IMG_FILE_NAME = "img.criu"
|
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
|
prev_line = None
|
||||||
uuid = uuid.uuid4()
|
uuid = uuid.uuid4()
|
||||||
|
|
||||||
@ -628,6 +636,8 @@ class zdtm_test:
|
|||||||
["make", "zdtm_ct"], env=dict(os.environ, MAKEFLAGS=""))
|
["make", "zdtm_ct"], env=dict(os.environ, MAKEFLAGS=""))
|
||||||
if not os.access("zdtm/lib/libzdtmtst.a", os.F_OK):
|
if not os.access("zdtm/lib/libzdtmtst.a", os.F_OK):
|
||||||
subprocess.check_call(["make", "-C", "zdtm/"])
|
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']:
|
if 'rootless' in opts and opts['rootless']:
|
||||||
return
|
return
|
||||||
subprocess.check_call(
|
subprocess.check_call(
|
||||||
@ -880,6 +890,7 @@ class criu_cli:
|
|||||||
fault=None,
|
fault=None,
|
||||||
strace=[],
|
strace=[],
|
||||||
preexec=None,
|
preexec=None,
|
||||||
|
preload_libfault=False,
|
||||||
nowait=False,
|
nowait=False,
|
||||||
timeout=60):
|
timeout=60):
|
||||||
env = dict(
|
env = dict(
|
||||||
@ -890,6 +901,9 @@ class criu_cli:
|
|||||||
print("Forcing %s fault" % fault)
|
print("Forcing %s fault" % fault)
|
||||||
env['CRIU_FAULT'] = fault
|
env['CRIU_FAULT'] = fault
|
||||||
|
|
||||||
|
if preload_libfault:
|
||||||
|
env['LD_PRELOAD'] = LIBFAULT_PATH
|
||||||
|
|
||||||
cr = subprocess.Popen(strace +
|
cr = subprocess.Popen(strace +
|
||||||
[criu_bin, action, "--no-default-config"] + args,
|
[criu_bin, action, "--no-default-config"] + args,
|
||||||
env=env,
|
env=env,
|
||||||
@ -980,6 +994,7 @@ class criu_rpc:
|
|||||||
fault=None,
|
fault=None,
|
||||||
strace=[],
|
strace=[],
|
||||||
preexec=None,
|
preexec=None,
|
||||||
|
preload_libfault=False,
|
||||||
nowait=False,
|
nowait=False,
|
||||||
timeout=None):
|
timeout=None):
|
||||||
if fault:
|
if fault:
|
||||||
@ -1065,6 +1080,7 @@ class criu:
|
|||||||
self.__criu_bin = opts['criu_bin']
|
self.__criu_bin = opts['criu_bin']
|
||||||
self.__crit_bin = opts['crit_bin']
|
self.__crit_bin = opts['crit_bin']
|
||||||
self.__pre_dump_mode = opts['pre_dump_mode']
|
self.__pre_dump_mode = opts['pre_dump_mode']
|
||||||
|
self.__preload_libfault = bool(opts['preload_libfault'])
|
||||||
self.__mntns_compat_mode = bool(opts['mntns_compat_mode'])
|
self.__mntns_compat_mode = bool(opts['mntns_compat_mode'])
|
||||||
|
|
||||||
if opts['rpc']:
|
if opts['rpc']:
|
||||||
@ -1192,8 +1208,10 @@ class criu:
|
|||||||
with open("/proc/sys/kernel/ns_last_pid") as ns_last_pid_fd:
|
with open("/proc/sys/kernel/ns_last_pid") as ns_last_pid_fd:
|
||||||
ns_last_pid = ns_last_pid_fd.read()
|
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,
|
ret = self.__criu.run(action, s_args, self.__criu_bin, self.__fault,
|
||||||
strace, preexec, nowait)
|
strace, preexec, preload_libfault, nowait)
|
||||||
|
|
||||||
if nowait:
|
if nowait:
|
||||||
os.close(status_fds[1])
|
os.close(status_fds[1])
|
||||||
@ -2083,7 +2101,7 @@ class Launcher:
|
|||||||
'dedup', 'sbs', 'freezecg', 'user', 'dry_run', 'noauto_dedup',
|
'dedup', 'sbs', 'freezecg', 'user', 'dry_run', 'noauto_dedup',
|
||||||
'remote_lazy_pages', 'show_stats', 'lazy_migrate', 'stream',
|
'remote_lazy_pages', 'show_stats', 'lazy_migrate', 'stream',
|
||||||
'tls', 'criu_bin', 'crit_bin', 'pre_dump_mode', 'mntns_compat_mode',
|
'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}))
|
arg = repr((name, desc, flavor, {d: self.__opts[d] for d in nd}))
|
||||||
|
|
||||||
if self.__use_log:
|
if self.__use_log:
|
||||||
@ -2788,6 +2806,7 @@ def get_cli_args():
|
|||||||
help="Select tests for a shard <index> (0-based)")
|
help="Select tests for a shard <index> (0-based)")
|
||||||
rp.add_argument("--test-shard-count", type=int, default=0,
|
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)")
|
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 = sp.add_parser("list", help="List tests")
|
||||||
lp.set_defaults(action=list_tests)
|
lp.set_defaults(action=list_tests)
|
||||||
|
@ -11,6 +11,7 @@ class criu_config:
|
|||||||
fault=None,
|
fault=None,
|
||||||
strace=[],
|
strace=[],
|
||||||
preexec=None,
|
preexec=None,
|
||||||
|
preload=False,
|
||||||
nowait=False):
|
nowait=False):
|
||||||
|
|
||||||
config_path = tempfile.mktemp(".conf", "criu-%s-" % action)
|
config_path = tempfile.mktemp(".conf", "criu-%s-" % action)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user