The dmesg output in cleanup_cgroup() makes it hard to find the
actual error in CI logs because one needs to scroll past it.
Move dmesg to dedicated CI steps that always run instead.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
Add a "Print dmesg" step with if: always() to every GitHub
Actions job that runs CRIU tests. For VM-based tests (CentOS
Stream, VM Fedora) dmesg runs inside the VM via lima. Jobs
that only compile or run non-CRIU tests are left unchanged.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
Add a "Print dmesg" step with when: always to the CircleCI
test-local job so kernel logs are captured even on failure.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
- Add -I../../include to CFLAGS so common/config.h is found.
- Guard the TCP queue enum in tcp-conn.c with
#ifndef CONFIG_HAS_TCP_REPAIR, matching soccr.h, to avoid
redeclaration errors on systems where <netinet/tcp.h> already
provides these symbols.
- Use libsoccr_release(so) instead of libsoccr_resume(so) for the
original socket handle whose fd was already closed, fixing a
Bad file descriptor error from setsockopt.
- Port run.py and tcp-test.py to Python 3: use bytes literals for
pipe I/O, read from sys.stdin.buffer, and decode pipe output
before parsing.
- Replace eval() with ast.literal_eval() to avoid code injection
warnings.
- Clean all test binaries in the clean target, and hook it into
the top-level make clean/mrproper via clean-top.
- Add soccr/test Python files to the top-level ruff target.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
Pass name and uns as parameters to ns_flavor.__init__() instead
of overwriting them after the super constructor sets them. This
avoids the attribute-overwrite pattern flagged by CodeQL while
keeping the same behavior.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
Add explicit 'return None' to all code paths in __criu_act() so
that explicit returns (returning ret on the nowait path) are not
mixed with implicit fall-through returns.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
The loop iteration variable 'i' in cr() is never used inside
the loop body. Rename it to '_' to indicate it is intentionally
unused and silence the CodeQL warning.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
exit() is provided by the site module for interactive use.
Use sys.exit() which is the proper way to exit from scripts.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
The sys.exit(1) after a while True loop can never be reached.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
The pass statements are redundant since the except blocks
already contain a print() call.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
BaseException
Replace bare except clauses with except Exception to avoid
catching BaseException subclasses like SystemExit and
KeyboardInterrupt.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
When cross-compile dependency packages cannot be installed, emit
a ::error:: annotation so that the failure reason is visible in
the GitHub Actions summary. Use \r to ensure the annotation is
recognized even inside Docker BuildKit output which prefixes
each line with step and timing information.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
duplication
Move the riscv64-specific APT repository setup (GPG keys, custom
source lists) from the template into the header file. This allows
the riscv64 template to be a symlink to the shared
Dockerfile.stable-cross.tmpl, like all other cross-compilation
targets. Skip amdgpu_plugin for riscv64 as it is not supported.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
free(NULL) is a no-op per the C standard (C99 7.20.3.2), so
guarding free() calls with NULL checks is unnecessary.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
The cross compile test for riscv was always failing with repository
inconsistencies around ncurses packages. The package is not actually
needed for CRIU, so just drop it.
Signed-off-by: Adrian Reber <areber@redhat.com>
Test that SCM_CREDENTIALS ancillary messages queued in a unix
socket are correctly saved and restored by CRIU.
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
(cherry picked from commit a9b546c74f6c1e817b0790bd9621cc137bb719f3)
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
Long story short: we face standard "which was first chicken or egg?"
problem here.
1) In add_fake_unix_queuers() for each unpared established unix socket
we want to add a "fake" queuer. And we want to decide at this point
which task should create this queuer and we just try to copy the task
from original socket. But original socket can have no task yet too,
because it can have no open fds, instead it is residing inside other
unix socket.
2) In prepare_scms we look through the packets from all unix sockets and
detect file descriptors in them.
3) We need to add those packets in special queuer's list so that queuer
can understand when all files we need to put in it are already created.
So it means that we need to have "fake" queuers present at this point.
4) At the same time it is also a point to understand which task should
create those descriptors from unix sockets and we just try to copy the
task from the queuer who would put them to unix socket.
You can imagine that queuers should be created (1) before we try to copy
task from them (3) and their peer socket may only give the task to
queuers (1) after it copyes the task from it's ancestor unix socket (4).
So let's fix it with:
- Split "fake" queuer owner task detection into separate step after
handling scm
- When handling scm, if queuer has no owner task, take it from original
socket
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
(cherry picked from commit 82641caf2580bd941cd78df32193556ed1ae31c2)
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
Here is how we dump nested unix sockets inside unix sockets:
+-> dump_one_unix_fd <-+
+-> dump_sk_queue |
+-> dump_sk_queue_packet |
+-> dump_packet_cmsg |
+-> dump_one_file |
+-> do_dump_gen_file +
+-> queue_packet_entry
+-> list_add_tail(packets_list)
So in the images more deeper unix socket goes strictly before the more
shallow one.
Before this patch on restore we also had the same reverse order due to
list_add_tail used when adding to packets_list. Because of it we first
handle deeper sockets in prepare_scms and later shallow ones.
This is conterintuitive because in case of nested unix sockets without
any actual open fds on them we need to find out which task should create
them (file_master()->task) and in unix_note_scm_rights we determine this
owner from queuer which can also have it yet unset because it would be
handled later in prepare_scms.
Let's reverse the walk order on restore in prepare_scms.
Note: we can't just reverse the order in list as we rely in
restore_sk_queue that packets of one socket are in original order.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
(cherry picked from commit db11de636842c29ca21e9176cd43b785c7379c56)
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
We already do so in other branch of if in dup_fdinfo, let's then do it
symmetrically. We later put pointer to this FdinfoEntry in collect_fd_to
int alloc_fle to fdinfo_list_entry->fe so it can be later used from
other places and if one thread modifies it we would not see modification
in other threads.
Do we really need to see these modifications? - It's Mistery, but better
be on the safe side.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
(cherry picked from commit 376773c840e1b527f894e83048f0be61869c409a)
Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
This would help to understand restore logs of unix sockets.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
(cherry picked from commit ae1bc673960ce7679527a7fb13cb5dcf8aaf5890)
Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
Printing info message when we go to nested fds will make easier to
understand logs of unix sockets dumping.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
(cherry picked from commit ae7cee5ef93efba90466bbf67d0e0367a05cc830)
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
This allows us to catch long standing bug in vzcriu when scm-s were not
dumped properly - scm-s from second packet contained both scm-s from
first and second packet. This happenes in case there several SCM_RIGHTS
packets and at least one SCM_CREDENTIALS packets were sent to unix
socket at the same time.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
(cherry picked from commit 65ea504a97506355c0a5a4d9612a4827a58d6631)
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
When we have several SCM_RIGHTS packets and at least one SCM_CREDENTIALS
sent simultaneousely into same unix socket we see that SCM_RIGHTS are
dumped wrong. It happens because before this patch SkPacketEntry had
been reused when dumping consequent packets, thus when dumping
SCM_RIGHTS for non-first packet it's pe.scm also contained SCM_RIGHTS
for previous packet.
To fix this let's not reuse SkPacketEntry. Also while on it let's split
dump_sk_queue_packet() - separate function for dumping one packet, to
add more readability to the code. Also drop meaningless "ret = -E2BIG"
and staff. Note that after this change pe.ucred is also not reused as it
probably should've always been.
Fixes: e4956b0b1 ("sk-queue: Add support of ucreds in unix sockets")
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
(cherry picked from commit 6832ccd499c1bef9bc220cdf42202c468fe5a37c)
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
Reproducer for the next problem:
When unix socket contains SCM with SCM_CREDENTIALS
cmsg_type we have to postpone saving this packet to
CR_FD_SK_QUEUES image because we need to have information
about process which creds was transfered in this message.
But if this SkPacketEntry already contains data from
SCM_RIGHTS messages (file descriptors was transfered
through unix socket) we will lose this data because of
incorrect queue_packet_entry function implementation.
This problem tends to inconsistent CRIU dump and on
restore we will get:
Error (criu/files.c:230): Empty list on file desc id 13(5)
Error (criu/files.c:232): BUG at criu/files.c:232
Reviewed-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
(cherry picked from commit 6aa13217721db06b7cbd873e615580f0a455d5a7)
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
If SkPacketEntry contains both SCM_CREDENTIALS and SCM_RIGHTS message
then only SCM_RIGHTS will be put into socket queue.
Reviewed-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
(cherry picked from commit 1aa1b1cb430e39271e7fbd44bd8609198a7f3a20)
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
When unix socket contains SCM with SCM_CREDENTIALS
cmsg_type we have to postpone saving this packet to
CR_FD_SK_QUEUES image because we need to have information
about process which creds was transfered in this message.
But if this SkPacketEntry already contains data from
SCM_RIGHTS messages (file descriptors was transfered
through unix socket) we will lose this data because of
incorrect queue_packet_entry function implementation.
This problem tends to inconsistent CRIU dump and on
restore we will get:
Error (criu/files.c:230): Empty list on file desc id 13(5)
Error (criu/files.c:232): BUG at criu/files.c:232
Reviewed-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
(cherry picked from commit e6a9ce32ad14d18ff3160e5339e4582885d740fe)
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
The queue may have a dead process' data in such case we rather
should ignore the packet.
Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
(cherry picked from commit f854da2284c2c0163055322804aa616b17a34c28)
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
For debug sake.
Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
(cherry picked from commit 318009a0ddf7150e7967f2dc52752cbb469cacd2)
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
A process may send creds message and get exited
so the message will be detected on checkpoint
but we won't be able to queue it back because
process is already dead and such sending is
forbidden by kernel. So just ignore such
packets.
Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
(cherry picked from commit e0e73bcbb8e07e60dbfd4e23cebe2f477a930704)
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
Checkpoint and restore ucreds on unix sockets are not
that trivial: the @pid returned by the kernel upon
message fetching is mapped to current user namespace
so it is not the same as it would be received inside
container. So we need to map real pid returned into
virtual seen from inside, but we know virtual pids
only when complete process tree is built.
Thus what we do -- queue such packets into own
queue and when process tree is build walk over
and transform former pids into virtual ones.
Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
(cherry picked from commit 8f3061c360381894a97edca2ada85466f95e1d88)
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
A socket may support receiving timestamps from the
kernel (see net/socket.c:__sock_recv_timestamp
in the kernel), so simply pass up this data to
userspace.
Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
(cherry picked from commit 1ecd757bf23831d1574e1dca0566dbe26e0fcb49)
Ahmed Elaidy:
- ported as a standalone commit (was previously squashed into the
unix-sockets ucred support); only the SOL_SOCKET timestamp handling
is kept, the netlink pktinfo part of the original is not ported here.
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
When error happened in dump_sk_creds or dumping
in dump_sk_queue passed fine we can leak xmalloc'ed
SkUcredEntry. Fix it.
Note it's not critical anyhow since CRIU will end up
execution in both cases and OS release memory
automatically but still.
Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
(cherry picked from commit 969a2aba0331ff940501205077766859453b9a35)
Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
ucred.pid is zero for kernel messages and in this case it is
impossible to restore it.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
(cherry picked from commit 70948c510699aa8a2d28fc1669ad25dd81a6b102)
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
We need to know a type of unsupported control messages.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
(cherry picked from commit 4ab24ee8840b4d879147442f4c65bb7eac77a8bb)
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
ucred in a netlink message contains the same pid and
it doesn't metter from which pidns it is read.
Cc: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
(cherry picked from commit 66f8f7b2ae51a2cef4044df478389137735e1d6e)
Ahmed Elaidy:
- dropped the ENOBUFS bits (SK_QUEUE_TRACK_ENOBUFS and the int *val
out-parameter): they belong to "netlink: save and generate ENOBUFS
at restore", which needs a non-upstream kernel extension and is
intentionally not ported.
- SK_QUEUE_DUMP_ADDR / the int flags signature come from the preceding
"sk-queue: use flags in dump_sk_queue" cherry-pick rather than being
glued in here.
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
(cherry picked from commit 8b83405614703211fee27f90f08450cba080a44c)
Ahmed Elaidy:
- adapted onto the upstream 2-arg dump_sk_queue(): upstream has no
netlink queue dump, so there was no bool dump_addr argument to
convert; introduce int flags on the 2-arg base and update the only
caller (unix sockets). No sk-netlink.c change for the same reason.
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
The benchmark and its five data generators otherwise remain standalone
tooling, so normal CI would not notice broken integrity checks,
statistics accounting, or compression configuration.
Add a bounded smoke run for zero, mixed, pseudorandom, text, and
ELF-derived mappings. Compare uncompressed, per-page LZ4, and 64 KiB
region images with one warmup and one measured iteration, print the
results, and fail on checksum, accounting, or configuration errors.
Run the helper tests first, then build the pycriu bindings needed by the
live benchmark. Leave the host page cache untouched and enforce a
five-minute timeout. Gate the run on compression support.
Assisted-by: Codex:GPT-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Compression can fall back to raw storage for every block in an entry.
The writer then omits compression metadata so restore can use ordinary
I/O, but that fast path also depends on a page-aligned payload.
Add per-page and region tests with an incompressible mapping. Inspect
the pagemap for an aligned 56-page entry without compression metadata,
while requiring another genuine LZ4 block to prove compression was
active. Restore through direct image I/O, require native AIO when
O_DIRECT is available, and verify the workload contents.
Run the test in CI when page compression is available.
Assisted-by: Codex:GPT-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Successive layers in an incremental dump can use different compression
modes. Restore must interpret each layer through its own inventory and
pagemap metadata instead of applying the final image mode to the parent
chain.
Add chains with two pre-dumps and a final dump for plain-to-page,
page-to-plain, plain-to-region, and region-to-plain transitions. Toggle
a page between layers so every image carries real payload, check the
exact inventory version and compression settings, and restore the ZDTM
workload to verify its memory contents.
Run the test in CI when both page compression and memory dirty tracking
are available.
Assisted-by: Codex:GPT-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Benchmark output can look credible even when command construction,
configuration recovery, archive inspection, accounting, or cleanup has
drifted. Full Podman and model-serving trials are too expensive for
focused checks of those helpers.
Add fast tests that load both serving frontends against their shared
implementation while keeping their mutable state separate. Cover CRIU
option isolation, explicit automatic decompression, port-derived URLs,
inventory validation, runc.conf locking and crash recovery, metadata
preservation, secret redaction, container failure detection, response
integrity, signal handling, and cleanup.
Also verify deterministic workload generation, report normalization,
cache-control failures, and the pagemap evidence required by the
region-cache benchmark. Add the compression benchmark tree to ruff and
provide a dedicated unit target.
Assisted-by: Codex:GPT-5
Assisted-by: Claude:claude-fable-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Serving engines have different memory layouts and restore behavior, so
SGLang results do not establish the cost or correctness of compression
for vLLM.
Add a vLLM frontend to the shared Podman benchmark. Support CPU and GPU
images and the supported server entrypoint forms, compare uncompressed,
per-page LZ4, and region LZ4 images, and verify deterministic inference
after restore. Report archive, checkpoint, restore, and post-restore
request costs, and add a bounded CPU test runner.
Reuse the shared runc.conf transaction, CRIU configuration isolation,
inventory validation, secret redaction, failure diagnostics, and
cleanup semantics so both serving benchmarks follow the same
methodology.
Assisted-by: Codex:GPT-5
Assisted-by: Claude:claude-fable-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Process-only measurements do not show how compressed pages affect a
containerized inference server, where Podman configuration, model
startup, and service readiness are part of the restore path. SGLang
also needs content validation so a quick restore cannot hide damaged
state.
Add a CPU and GPU SGLang benchmark that checkpoints through Podman.
Compare uncompressed, per-page LZ4, and region LZ4 images. Send the same
deterministic chat request before and after restore, compare response
hashes, measure archive and operation costs, and verify the compression
mode and region size recorded in the exported inventory. Derive the
local serving URL from the selected port unless one is supplied.
Podman passes CRIU options through the host-wide runc.conf. Serialize
updates with a canonical lock and crash-recovery journal, preserve file
metadata and xattrs, refuse to overwrite external changes, and restore
the original configuration on success and during error or signal
cleanup. Isolate CRIU from ambient defaults, keep access tokens out of
arguments and diagnostics, detect stopped containers during health
checks, and preserve failed artifacts. Add a bounded CPU test runner.
Assisted-by: Codex:GPT-5
Assisted-by: Claude:claude-fable-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Incremental restore can request alternating pages from one compressed
parent region. Without reuse, each partial request decompresses the same
block again, but a timing result is meaningful only if the images really
create that access pattern.
Add an A/B benchmark that takes a compressed pre-dump, dirties
alternating pages, and compares restore with two CRIU binaries. Publish
the workload mapping address and inspect both pagemaps before restore.
Require the requested region size and a genuine LZ4 parent block.
Require alternating present and parent pages plus at least two parent
slices from the same block.
Record that evidence with each trial, verify the restored mapping with
SHA-256, alternate binary order, and separate warmups from measured
iterations. Emit both machine-readable data and a Markdown summary.
Assisted-by: Codex:GPT-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Compression effectiveness depends on page contents and block size,
while dump and restore costs can move independently of image size. The
series needs a repeatable baseline that measures those trade-offs and
rejects a fast result if restored memory is wrong.
Add a root-only benchmark for zero, mixed, pseudorandom, text, and
ELF-derived mappings. Compare uncompressed images with per-page LZ4 and
a sweep of region sizes, rotate configuration order after a warmup, and
report median storage, latency, and throughput from required CRIU
statistics. Verify every restored mapping with SHA-256 and preserve
artifacts when a trial fails.
Bound workload startup and cleanup, handle termination signals, and
make cache dropping an explicit, checked part of the methodology. Leave
CRIU's compressed-page worker width unchanged unless requested,
preserve an explicit automatic value of zero, and generate deterministic
random input on Python versions before Random.randbytes(). Support JSON
output for longer external runs.
Assisted-by: Codex:GPT-5
Assisted-by: Claude:claude-fable-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
CRIT can edit image metadata but cannot convert the matching page
payloads as one consistent image set. Changing either side alone can
leave pagemap, inventory, and payload data incompatible.
Add compress and decompress commands for checkpoint directories. Match
CRIU's block encoding, raw threshold, alignment, image version, parent
compatibility, and validation rules. Keep hugetlb and external-plugin
ranges raw because CRIU cannot premap them generically, and add the
Python LZ4 binding to supported dependencies.
Stage every output before replacing any image. Preserve ownership,
permissions, timestamps, xattrs, ACLs, and security metadata; create
exclusive hard-link backups; synchronize directory changes; and defer
terminating signals until the transaction has a definite result. Roll
back the complete image set after a failure and retain the recoverable
source if rollback or cleanup also fails.
Reject symlinks, non-regular images, unsupported versions, inconsistent
compression metadata, unknown modes, and truncated payloads. Recheck
source identities before replacement so a changed pathname is not
overwritten. Cover page and region images, parent chains, exceptional
mappings, metadata preservation, signals, races, and rollback failures.
Assisted-by: Codex:GPT-5
Assisted-by: Claude:claude-fable-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
End-to-end restore tests do not isolate codec behavior or worker-pool
decisions, which makes boundary failures difficult to diagnose.
Test per-page and region round trips for zero, repeating, pseudorandom,
and single-byte inputs across several acceleration values and region
sizes. Verify zero detection, deterministic raw fallback, and page-image
offset alignment above 4 GiB.
Exercise serial and parallel LZ4 decoding and zero filling,
deterministic 0/1/N thread selection, effective-capacity gating,
work-based automatic width, growth of a persistent pool, initialization
of the shared batch budget, and return of the CPU budget. Also exercise
nonblocking acquisition and release of the second encoded input slot.
Verify that serial decoding skips caller work, while a parallel batch
runs it once after dispatch. Link the tests only when LZ4 is available.
Assisted-by: Codex:GPT-5
Assisted-by: Claude:claude-fable-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>