From 9952f1768ff597bb54d36c24046246574de467c1 Mon Sep 17 00:00:00 2001 From: Denis Aleksandrov Date: Thu, 9 Apr 2026 17:53:46 -0400 Subject: [PATCH 1/7] Implement kexec support for SSH mode do_kexec_reboot() was a stub that always fell back to a full reboot. Implement it properly for SSH mode, where CRIU is not involved and kexec is safe to use. Add kexec_load_kernel() to lib.sh which validates that the kernel and initramfs files exist, reads the current command line from /proc/cmdline, and loads the new kernel into memory with kexec -l. Add kab_kexec() which executes the loaded kernel via reboot_and_wait. In local/CRIU mode, kexec bypasses the normal boot sequence that CRIU relies on to restart the daemon, so the existing fallback to full reboot is preserved. Co-Authored-By: Claude Sonnet 4.6 --- handlers/reboot_handler.sh | 17 +++++++++++++---- lib.sh | 28 ++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/handlers/reboot_handler.sh b/handlers/reboot_handler.sh index 5daee2a..05d0c77 100755 --- a/handlers/reboot_handler.sh +++ b/handlers/reboot_handler.sh @@ -33,8 +33,17 @@ do_full_reboot() { } do_kexec_reboot() { - log "Strategy: kexec not supported with CRIU checkpointing, using full reboot..." - # kexec bypasses the normal boot process, which would prevent the CRIU daemon - # from properly restoring the process. Fall back to full reboot. - do_full_reboot + if [[ -z $KAB_TEST_HOST ]]; then + log "Strategy: kexec not supported with CRIU checkpointing, using full reboot..." + do_full_reboot + return + fi + + log "Strategy: Performing kexec reboot (fast reboot)" + if ! kexec_load_kernel "$TESTED_KERNEL"; then + log "Falling back to full reboot" + kab_reboot + return + fi + kab_kexec } diff --git a/lib.sh b/lib.sh index e6ff31f..31de1d3 100644 --- a/lib.sh +++ b/lib.sh @@ -155,6 +155,34 @@ reboot_and_wait() { done } +kexec_load_kernel() { + local kernel_release="$1" + local vmlinuz="/boot/vmlinuz-${kernel_release}" + local initramfs="/boot/initramfs-${kernel_release}.img" + local cmdline + + if ! run_cmd test -f "$vmlinuz"; then + log "ERROR: Kernel not found: $vmlinuz" + return 1 + fi + if ! run_cmd test -f "$initramfs"; then + log "ERROR: Initramfs not found: $initramfs" + return 1 + fi + + cmdline=$(run_cmd cat /proc/cmdline) + log "Loading kernel ${kernel_release} into kexec" + if ! run_cmd kexec -l "$vmlinuz" --initrd="$initramfs" --append="$cmdline"; then + log "ERROR: Failed to load kernel into kexec" + return 1 + fi + log "Kernel loaded into kexec successfully" +} + +kab_kexec() { + reboot_and_wait kexec -e +} + prepare_reboot() { # try to reboot to current EFI bootloader entry next time run_cmd command -v rstrnt-prepare-reboot &>/dev/null && run_cmd rstrnt-prepare-reboot >/dev/null From e4cea27a3c871705d92e97cfaf62d89702b14a52 Mon Sep 17 00:00:00 2001 From: Denis Aleksandrov Date: Thu, 9 Apr 2026 17:54:13 -0400 Subject: [PATCH 2/7] install_from_rpm: redirect dnf output on the test host The dnf install output was being redirected to /var/log/install.log on the controller machine (local shell redirect), which fails when the controller runs as a non-root user. Pass the redirect as an argument to run_cmd so it is evaluated on the test host, consistent with how install_from_git handles its build log. Co-Authored-By: Claude Sonnet 4.6 --- handlers/install_handler.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/handlers/install_handler.sh b/handlers/install_handler.sh index d0f1805..3d6792f 100755 --- a/handlers/install_handler.sh +++ b/handlers/install_handler.sh @@ -211,7 +211,7 @@ install_from_rpm() { fi done - if ! run_cmd dnf install -y "${rpms_to_install[@]}" >"/var/log/install.log" 2>&1; then do_abort "RPM install failed."; fi + if ! run_cmd dnf install -y "${rpms_to_install[@]}" ">/var/log/install.log" '2>&1'; then do_abort "RPM install failed."; fi TESTED_KERNEL="$release" [[ $_kernel_name_prefix == kernel-rt ]] && TESTED_KERNEL+=+rt } From 20de737b720817a761469d34a23c9a8465f3372a Mon Sep 17 00:00:00 2001 From: Denis Aleksandrov Date: Thu, 16 Apr 2026 17:26:01 -0400 Subject: [PATCH 3/7] kexec: support CRIU mode and use --reuse-cmdline Two improvements based on review feedback: Use kexec --reuse-cmdline instead of reading /proc/cmdline manually. This avoids passing bootloader-specific parameters like BOOT_IMAGE= that kexec does not need and which can vary across boot environments. Extend kexec support to local/CRIU mode. kexec still performs a full Linux boot, so the CRIU daemon restarts via cron and can restore the bisect process normally. kab_kexec() now signals the daemon with a "kexec" checkpoint type, which triggers kexec -e after checkpointing. criu-daemon.sh is updated to recognise and allow kexec -e commands. do_kexec_reboot() no longer special-cases CRIU mode. Co-Authored-By: Claude Sonnet 4.6 --- criu-daemon.sh | 2 +- handlers/reboot_handler.sh | 8 +------- lib.sh | 12 ++++++++---- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/criu-daemon.sh b/criu-daemon.sh index 5dba8d2..9b1e4b8 100755 --- a/criu-daemon.sh +++ b/criu-daemon.sh @@ -100,7 +100,7 @@ handle_checkpoint() { rm -f "$CHECKPOINT_SIGNAL" log "Received checkpoint+panic request" - if ! grep -e sysrq-trigger -e reboot "$_cmd_file"; then + if ! grep -e sysrq-trigger -e reboot -e 'kexec -e' "$_cmd_file"; then return 1 fi if do_checkpoint; then diff --git a/handlers/reboot_handler.sh b/handlers/reboot_handler.sh index 05d0c77..c7f9acc 100755 --- a/handlers/reboot_handler.sh +++ b/handlers/reboot_handler.sh @@ -33,16 +33,10 @@ do_full_reboot() { } do_kexec_reboot() { - if [[ -z $KAB_TEST_HOST ]]; then - log "Strategy: kexec not supported with CRIU checkpointing, using full reboot..." - do_full_reboot - return - fi - log "Strategy: Performing kexec reboot (fast reboot)" if ! kexec_load_kernel "$TESTED_KERNEL"; then log "Falling back to full reboot" - kab_reboot + do_full_reboot return fi kab_kexec diff --git a/lib.sh b/lib.sh index 31de1d3..f1da811 100644 --- a/lib.sh +++ b/lib.sh @@ -83,6 +83,8 @@ signal_checkpoint() { printf "sync\n %s" "${_reboot_cmd}" >"$CHECKPOINT_SIGNAL" elif [[ $1 == panic ]]; then printf "sync\n echo 1 > /proc/sys/kernel/sysrq\n echo c > /proc/sysrq-trigger" >"$CHECKPOINT_SIGNAL" + elif [[ $1 == kexec ]]; then + printf "sync\n kexec -e" >"$CHECKPOINT_SIGNAL" fi # Wait for the daemon to process our request and reboot/panic the system @@ -159,7 +161,6 @@ kexec_load_kernel() { local kernel_release="$1" local vmlinuz="/boot/vmlinuz-${kernel_release}" local initramfs="/boot/initramfs-${kernel_release}.img" - local cmdline if ! run_cmd test -f "$vmlinuz"; then log "ERROR: Kernel not found: $vmlinuz" @@ -170,9 +171,8 @@ kexec_load_kernel() { return 1 fi - cmdline=$(run_cmd cat /proc/cmdline) log "Loading kernel ${kernel_release} into kexec" - if ! run_cmd kexec -l "$vmlinuz" --initrd="$initramfs" --append="$cmdline"; then + if ! run_cmd kexec -l "$vmlinuz" --initrd="$initramfs" --reuse-cmdline; then log "ERROR: Failed to load kernel into kexec" return 1 fi @@ -180,7 +180,11 @@ kexec_load_kernel() { } kab_kexec() { - reboot_and_wait kexec -e + if [[ -z $KAB_TEST_HOST ]]; then + signal_checkpoint "kexec" + else + reboot_and_wait kexec -e + fi } prepare_reboot() { From e01a93090f2d93a8660639a0f7c6952cd45d2f8c Mon Sep 17 00:00:00 2001 From: Denis Aleksandrov Date: Thu, 16 Apr 2026 17:26:06 -0400 Subject: [PATCH 4/7] tests/kab_ssh: enable kexec reboot strategy Set REBOOT_STRATEGY="kexec" in the SSH integration test so that the kexec code path gets exercised on every test run. Co-Authored-By: Claude Sonnet 4.6 --- tests/kab_ssh/test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/kab_ssh/test.sh b/tests/kab_ssh/test.sh index a98ff92..3946f70 100755 --- a/tests/kab_ssh/test.sh +++ b/tests/kab_ssh/test.sh @@ -28,7 +28,7 @@ if echo "${CLIENTS}" | grep -qi "${HOSTNAME}"; then cat <"$CONF_FILE" INSTALL_STRATEGY="rpm" TEST_STRATEGY="panic" -REBOOT_STRATEGY= +REBOOT_STRATEGY="kexec" RPM_CACHE_DIR="/var/cache/kdump-bisect-rpms" GOOD_COMMIT=$GOOD_COMMIT BAD_COMMIT=$BAD_COMMIT From beac310387d8dad40bb745caa4fc6144255ccba9 Mon Sep 17 00:00:00 2001 From: Denis Aleksandrov Date: Thu, 23 Apr 2026 18:33:09 -0400 Subject: [PATCH 5/7] kexec: install kexec-tools when REBOOT_STRATEGY=kexec kexec-tools was only installed as part of kdump setup, which only runs when TEST_STRATEGY="panic". A user running REBOOT_STRATEGY="kexec" with TEST_STRATEGY="simple" would get a missing kexec binary. Install kexec-tools at the start of setup_kdump() whenever REBOOT_STRATEGY="kexec" is set, independent of the test strategy. Co-Authored-By: Claude Sonnet 4.6 --- lib.sh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib.sh b/lib.sh index f1da811..6a29a60 100644 --- a/lib.sh +++ b/lib.sh @@ -453,6 +453,15 @@ END } setup_kdump() { + if [[ "$REBOOT_STRATEGY" == "kexec" ]]; then + if ! run_cmd command -v kexec &>/dev/null; then + if ! run_cmd dnf install kexec-tools -yq; then + log "Failed to install kexec-tools!" + exit 1 + fi + fi + fi + if [[ "$TEST_STRATEGY" == "panic" ]]; then if ! run_cmd command -v kdumpctl &>/dev/null; then if ! run_cmd dnf install kdump-utils -yq && ! run_cmd dnf install kexec-tools -yq; then From 055b637859dfdf45854c666d29eaab0686c072e9 Mon Sep 17 00:00:00 2001 From: Denis Aleksandrov Date: Fri, 24 Apr 2026 12:23:22 -0400 Subject: [PATCH 6/7] tests/kab_criu: enable kexec reboot strategy Set REBOOT_STRATEGY="kexec" so the CRIU integration test exercises the kexec+CRIU code path: the kernel is loaded via kexec -l and the CRIU daemon checkpoints kab before executing kexec -e, then restores it after the system comes back up. Co-Authored-By: Claude Sonnet 4.6 --- tests/kab_criu/test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/kab_criu/test.sh b/tests/kab_criu/test.sh index a669260..1746ffe 100755 --- a/tests/kab_criu/test.sh +++ b/tests/kab_criu/test.sh @@ -52,7 +52,7 @@ done cat <$CONF_FILE" INSTALL_STRATEGY="rpm" TEST_STRATEGY="panic" -REBOOT_STRATEGY= +REBOOT_STRATEGY="kexec" RPM_CACHE_DIR="/var/cache/kdump-bisect-rpms" BAD_COMMIT=$BAD_COMMIT REPRODUCER_SCRIPT=$TEST_SCRIPT From 547c4552c3b88e69dc6cbdd1a7624eb82e72c2c7 Mon Sep 17 00:00:00 2001 From: Denis Aleksandrov Date: Wed, 10 Jun 2026 17:42:09 -0400 Subject: [PATCH 7/7] Replaces all instances of \`kexec -e\` with \`systemctl kexec\` Signed-off-by: Denis Aleksandrov --- bisect.conf | 2 +- criu-daemon.sh | 2 +- lib.sh | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bisect.conf b/bisect.conf index 196f0f7..4439a5e 100755 --- a/bisect.conf +++ b/bisect.conf @@ -21,7 +21,7 @@ TEST_STRATEGY="panic" # REBOOT_STRATEGY: 'reboot' or 'kexec' # 'reboot': Performs a full, normal system reboot. -# 'kexec': Uses 'kexec -e' for a faster reboot (requires kexec to be configured). +# 'kexec': Uses 'systemctl kexec' for a faster reboot (requires kexec to be configured). REBOOT_STRATEGY="reboot" # === Git Repository (for INSTALL_STRATEGY="git" or auto mode) === diff --git a/criu-daemon.sh b/criu-daemon.sh index 9b1e4b8..3bb4d60 100755 --- a/criu-daemon.sh +++ b/criu-daemon.sh @@ -100,7 +100,7 @@ handle_checkpoint() { rm -f "$CHECKPOINT_SIGNAL" log "Received checkpoint+panic request" - if ! grep -e sysrq-trigger -e reboot -e 'kexec -e' "$_cmd_file"; then + if ! grep -e sysrq-trigger -e reboot -e 'systemctl kexec' "$_cmd_file"; then return 1 fi if do_checkpoint; then diff --git a/lib.sh b/lib.sh index 6a29a60..aaf7a89 100644 --- a/lib.sh +++ b/lib.sh @@ -84,7 +84,7 @@ signal_checkpoint() { elif [[ $1 == panic ]]; then printf "sync\n echo 1 > /proc/sys/kernel/sysrq\n echo c > /proc/sysrq-trigger" >"$CHECKPOINT_SIGNAL" elif [[ $1 == kexec ]]; then - printf "sync\n kexec -e" >"$CHECKPOINT_SIGNAL" + printf "sync\n systemctl kexec" >"$CHECKPOINT_SIGNAL" fi # Wait for the daemon to process our request and reboot/panic the system @@ -183,7 +183,7 @@ kab_kexec() { if [[ -z $KAB_TEST_HOST ]]; then signal_checkpoint "kexec" else - reboot_and_wait kexec -e + reboot_and_wait systemctl kexec fi }