Skip to content

Commit 724bf8c

Browse files
soleenakpm00
authored andcommitted
selftests/liveupdate: add kexec test for multiple and empty sessions
Introduce a new kexec-based selftest, luo_kexec_multi_session, to validate the end-to-end lifecycle of a more complex LUO scenario. While the existing luo_kexec_simple test covers the basic end-to-end lifecycle, it is limited to a single session with one preserved file. This new test significantly expands coverage by verifying LUO's ability to handle a mixed workload involving multiple sessions, some of which are intentionally empty. This ensures that the LUO core correctly preserves and restores the state of all session types across a reboot. The test validates the following sequence: Stage 1 (Pre-kexec): - Creates two empty test sessions (multi-test-empty-1, multi-test-empty-2). - Creates a session with one preserved memfd (multi-test-files-1). - Creates another session with two preserved memfds (multi-test-files-2), each containing unique data. - Creates a state-tracking session to manage the transition to Stage 2. - Executes a kexec reboot via the helper script. Stage 2 (Post-kexec): - Retrieves the state-tracking session to confirm it is in the post-reboot stage. - Retrieves all four test sessions (both the empty and non-empty ones). - For the non-empty sessions, restores the preserved memfds and verifies their contents match the original data patterns. - Finalizes all test sessions and the state session to ensure a clean teardown and that all associated kernel resources are correctly released. This test provides greater confidence in the robustness of the LUO framework by validating its behavior in a more realistic, multi-faceted scenario. Link: https://lkml.kernel.org/r/20251125165850.3389713-19-pasha.tatashin@soleen.com Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com> Reviewed-by: Mike Rapoport (Microsoft) <rppt@kernel.org> Tested-by: David Matlack <dmatlack@google.com> Cc: Aleksander Lobakin <aleksander.lobakin@intel.com> Cc: Alexander Graf <graf@amazon.com> Cc: Alice Ryhl <aliceryhl@google.com> Cc: Andriy Shevchenko <andriy.shevchenko@linux.intel.com> Cc: anish kumar <yesanishhere@gmail.com> Cc: Anna Schumaker <anna.schumaker@oracle.com> Cc: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Borislav Betkov <bp@alien8.de> Cc: Chanwoo Choi <cw00.choi@samsung.com> Cc: Chen Ridong <chenridong@huawei.com> Cc: Chris Li <chrisl@kernel.org> Cc: Christian Brauner <brauner@kernel.org> Cc: Daniel Wagner <wagi@kernel.org> Cc: Danilo Krummrich <dakr@kernel.org> Cc: Dan Williams <dan.j.williams@intel.com> Cc: David Hildenbrand <david@redhat.com> Cc: David Jeffery <djeffery@redhat.com> Cc: David Rientjes <rientjes@google.com> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Guixin Liu <kanie@linux.alibaba.com> Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: Hugh Dickins <hughd@google.com> Cc: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Ira Weiny <ira.weiny@intel.com> Cc: Jann Horn <jannh@google.com> Cc: Jason Gunthorpe <jgg@nvidia.com> Cc: Jens Axboe <axboe@kernel.dk> Cc: Joanthan Cameron <Jonathan.Cameron@huawei.com> Cc: Joel Granados <joel.granados@kernel.org> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Lennart Poettering <lennart@poettering.net> Cc: Leon Romanovsky <leon@kernel.org> Cc: Leon Romanovsky <leonro@nvidia.com> Cc: Lukas Wunner <lukas@wunner.de> Cc: Marc Rutland <mark.rutland@arm.com> Cc: Masahiro Yamada <masahiroy@kernel.org> Cc: Matthew Maurer <mmaurer@google.com> Cc: Miguel Ojeda <ojeda@kernel.org> Cc: Myugnjoo Ham <myungjoo.ham@samsung.com> Cc: Parav Pandit <parav@nvidia.com> Cc: Pratyush Yadav <pratyush@kernel.org> Cc: Pratyush Yadav <ptyadav@amazon.de> Cc: Randy Dunlap <rdunlap@infradead.org> Cc: Roman Gushchin <roman.gushchin@linux.dev> Cc: Saeed Mahameed <saeedm@nvidia.com> Cc: Samiullah Khawaja <skhawaja@google.com> Cc: Song Liu <song@kernel.org> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Stuart Hayes <stuart.w.hayes@gmail.com> Cc: Tejun Heo <tj@kernel.org> Cc: Thomas Gleinxer <tglx@linutronix.de> Cc: Thomas Weißschuh <linux@weissschuh.net> Cc: Vincent Guittot <vincent.guittot@linaro.org> Cc: William Tu <witu@nvidia.com> Cc: Yoann Congal <yoann.congal@smile.fr> Cc: Zhu Yanjun <yanjun.zhu@linux.dev> Cc: Zijun Hu <quic_zijuhu@quicinc.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
1 parent a003bdb commit 724bf8c

2 files changed

Lines changed: 163 additions & 0 deletions

File tree

tools/testing/selftests/liveupdate/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ LIB_C += luo_test_utils.c
55
TEST_GEN_PROGS += liveupdate
66

77
TEST_GEN_PROGS_EXTENDED += luo_kexec_simple
8+
TEST_GEN_PROGS_EXTENDED += luo_multi_session
89

910
TEST_FILES += do_kexec.sh
1011

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
3+
/*
4+
* Copyright (c) 2025, Google LLC.
5+
* Pasha Tatashin <pasha.tatashin@soleen.com>
6+
*
7+
* A selftest to validate the end-to-end lifecycle of multiple LUO sessions
8+
* across a kexec reboot, including empty sessions and sessions with multiple
9+
* files.
10+
*/
11+
12+
#include "luo_test_utils.h"
13+
14+
#define SESSION_EMPTY_1 "multi-test-empty-1"
15+
#define SESSION_EMPTY_2 "multi-test-empty-2"
16+
#define SESSION_FILES_1 "multi-test-files-1"
17+
#define SESSION_FILES_2 "multi-test-files-2"
18+
19+
#define MFD1_TOKEN 0x1001
20+
#define MFD2_TOKEN 0x2002
21+
#define MFD3_TOKEN 0x3003
22+
23+
#define MFD1_DATA "Data for session files 1"
24+
#define MFD2_DATA "First file for session files 2"
25+
#define MFD3_DATA "Second file for session files 2"
26+
27+
#define STATE_SESSION_NAME "kexec_multi_state"
28+
#define STATE_MEMFD_TOKEN 998
29+
30+
/* Stage 1: Executed before the kexec reboot. */
31+
static void run_stage_1(int luo_fd)
32+
{
33+
int s_empty1_fd, s_empty2_fd, s_files1_fd, s_files2_fd;
34+
35+
ksft_print_msg("[STAGE 1] Starting pre-kexec setup for multi-session test...\n");
36+
37+
ksft_print_msg("[STAGE 1] Creating state file for next stage (2)...\n");
38+
create_state_file(luo_fd, STATE_SESSION_NAME, STATE_MEMFD_TOKEN, 2);
39+
40+
ksft_print_msg("[STAGE 1] Creating empty sessions '%s' and '%s'...\n",
41+
SESSION_EMPTY_1, SESSION_EMPTY_2);
42+
s_empty1_fd = luo_create_session(luo_fd, SESSION_EMPTY_1);
43+
if (s_empty1_fd < 0)
44+
fail_exit("luo_create_session for '%s'", SESSION_EMPTY_1);
45+
46+
s_empty2_fd = luo_create_session(luo_fd, SESSION_EMPTY_2);
47+
if (s_empty2_fd < 0)
48+
fail_exit("luo_create_session for '%s'", SESSION_EMPTY_2);
49+
50+
ksft_print_msg("[STAGE 1] Creating session '%s' with one memfd...\n",
51+
SESSION_FILES_1);
52+
53+
s_files1_fd = luo_create_session(luo_fd, SESSION_FILES_1);
54+
if (s_files1_fd < 0)
55+
fail_exit("luo_create_session for '%s'", SESSION_FILES_1);
56+
if (create_and_preserve_memfd(s_files1_fd, MFD1_TOKEN, MFD1_DATA) < 0) {
57+
fail_exit("create_and_preserve_memfd for token %#x",
58+
MFD1_TOKEN);
59+
}
60+
61+
ksft_print_msg("[STAGE 1] Creating session '%s' with two memfds...\n",
62+
SESSION_FILES_2);
63+
64+
s_files2_fd = luo_create_session(luo_fd, SESSION_FILES_2);
65+
if (s_files2_fd < 0)
66+
fail_exit("luo_create_session for '%s'", SESSION_FILES_2);
67+
if (create_and_preserve_memfd(s_files2_fd, MFD2_TOKEN, MFD2_DATA) < 0) {
68+
fail_exit("create_and_preserve_memfd for token %#x",
69+
MFD2_TOKEN);
70+
}
71+
if (create_and_preserve_memfd(s_files2_fd, MFD3_TOKEN, MFD3_DATA) < 0) {
72+
fail_exit("create_and_preserve_memfd for token %#x",
73+
MFD3_TOKEN);
74+
}
75+
76+
close(luo_fd);
77+
daemonize_and_wait();
78+
}
79+
80+
/* Stage 2: Executed after the kexec reboot. */
81+
static void run_stage_2(int luo_fd, int state_session_fd)
82+
{
83+
int s_empty1_fd, s_empty2_fd, s_files1_fd, s_files2_fd;
84+
int mfd1, mfd2, mfd3, stage;
85+
86+
ksft_print_msg("[STAGE 2] Starting post-kexec verification...\n");
87+
88+
restore_and_read_stage(state_session_fd, STATE_MEMFD_TOKEN, &stage);
89+
if (stage != 2) {
90+
fail_exit("Expected stage 2, but state file contains %d",
91+
stage);
92+
}
93+
94+
ksft_print_msg("[STAGE 2] Retrieving all sessions...\n");
95+
s_empty1_fd = luo_retrieve_session(luo_fd, SESSION_EMPTY_1);
96+
if (s_empty1_fd < 0)
97+
fail_exit("luo_retrieve_session for '%s'", SESSION_EMPTY_1);
98+
99+
s_empty2_fd = luo_retrieve_session(luo_fd, SESSION_EMPTY_2);
100+
if (s_empty2_fd < 0)
101+
fail_exit("luo_retrieve_session for '%s'", SESSION_EMPTY_2);
102+
103+
s_files1_fd = luo_retrieve_session(luo_fd, SESSION_FILES_1);
104+
if (s_files1_fd < 0)
105+
fail_exit("luo_retrieve_session for '%s'", SESSION_FILES_1);
106+
107+
s_files2_fd = luo_retrieve_session(luo_fd, SESSION_FILES_2);
108+
if (s_files2_fd < 0)
109+
fail_exit("luo_retrieve_session for '%s'", SESSION_FILES_2);
110+
111+
ksft_print_msg("[STAGE 2] Verifying contents of session '%s'...\n",
112+
SESSION_FILES_1);
113+
mfd1 = restore_and_verify_memfd(s_files1_fd, MFD1_TOKEN, MFD1_DATA);
114+
if (mfd1 < 0)
115+
fail_exit("restore_and_verify_memfd for token %#x", MFD1_TOKEN);
116+
close(mfd1);
117+
118+
ksft_print_msg("[STAGE 2] Verifying contents of session '%s'...\n",
119+
SESSION_FILES_2);
120+
121+
mfd2 = restore_and_verify_memfd(s_files2_fd, MFD2_TOKEN, MFD2_DATA);
122+
if (mfd2 < 0)
123+
fail_exit("restore_and_verify_memfd for token %#x", MFD2_TOKEN);
124+
close(mfd2);
125+
126+
mfd3 = restore_and_verify_memfd(s_files2_fd, MFD3_TOKEN, MFD3_DATA);
127+
if (mfd3 < 0)
128+
fail_exit("restore_and_verify_memfd for token %#x", MFD3_TOKEN);
129+
close(mfd3);
130+
131+
ksft_print_msg("[STAGE 2] Test data verified successfully.\n");
132+
133+
ksft_print_msg("[STAGE 2] Finalizing all test sessions...\n");
134+
if (luo_session_finish(s_empty1_fd) < 0)
135+
fail_exit("luo_session_finish for '%s'", SESSION_EMPTY_1);
136+
close(s_empty1_fd);
137+
138+
if (luo_session_finish(s_empty2_fd) < 0)
139+
fail_exit("luo_session_finish for '%s'", SESSION_EMPTY_2);
140+
close(s_empty2_fd);
141+
142+
if (luo_session_finish(s_files1_fd) < 0)
143+
fail_exit("luo_session_finish for '%s'", SESSION_FILES_1);
144+
close(s_files1_fd);
145+
146+
if (luo_session_finish(s_files2_fd) < 0)
147+
fail_exit("luo_session_finish for '%s'", SESSION_FILES_2);
148+
close(s_files2_fd);
149+
150+
ksft_print_msg("[STAGE 2] Finalizing state session...\n");
151+
if (luo_session_finish(state_session_fd) < 0)
152+
fail_exit("luo_session_finish for state session");
153+
close(state_session_fd);
154+
155+
ksft_print_msg("\n--- MULTI-SESSION KEXEC TEST PASSED ---\n");
156+
}
157+
158+
int main(int argc, char *argv[])
159+
{
160+
return luo_test(argc, argv, STATE_SESSION_NAME,
161+
run_stage_1, run_stage_2);
162+
}

0 commit comments

Comments
 (0)