xref: /linux/tools/testing/selftests/liveupdate/luo_stress_sessions.c (revision 3432292fb9130191dca57953941f7ae3888d52d8)
1 // SPDX-License-Identifier: GPL-2.0-only
2 
3 /*
4  * Copyright (c) 2026, Google LLC.
5  * Pasha Tatashin <pasha.tatashin@soleen.com>
6  *
7  * Validate that LUO can handle a large number of sessions across a kexec
8  * reboot.
9  */
10 
11 #include <stdio.h>
12 #include <unistd.h>
13 #include "luo_test_utils.h"
14 
15 #define NUM_SESSIONS 2000
16 #define STATE_SESSION_NAME "kexec_many_state"
17 #define STATE_MEMFD_TOKEN 999
18 
19 /* Stage 1: Executed before the kexec reboot. */
20 static void run_stage_1(int luo_fd)
21 {
22 	int ret, i;
23 
24 	ksft_print_msg("[STAGE 1] Increasing ulimit for open files...\n");
25 	ret = luo_ensure_nofile_limit(NUM_SESSIONS);
26 	if (ret == -EPERM)
27 		ksft_exit_skip("Insufficient privileges to set RLIMIT_NOFILE\n");
28 	if (ret < 0)
29 		ksft_exit_fail_msg("luo_ensure_nofile_limit failed: %s\n", strerror(-ret));
30 
31 	ksft_print_msg("[STAGE 1] Creating state file for next stage (2)...\n");
32 	create_state_file(luo_fd, STATE_SESSION_NAME, STATE_MEMFD_TOKEN, 2);
33 
34 	ksft_print_msg("[STAGE 1] Creating %d sessions...\n", NUM_SESSIONS);
35 
36 	for (i = 0; i < NUM_SESSIONS; i++) {
37 		char name[LIVEUPDATE_SESSION_NAME_LENGTH];
38 		int s_fd;
39 
40 		snprintf(name, sizeof(name), "many-test-%d", i);
41 		s_fd = luo_create_session(luo_fd, name);
42 		if (s_fd < 0) {
43 			fail_exit("luo_create_session for '%s' at index %d",
44 				  name, i);
45 		}
46 	}
47 
48 	ksft_print_msg("[STAGE 1] Successfully created %d sessions.\n",
49 		       NUM_SESSIONS);
50 
51 	close(luo_fd);
52 	daemonize_and_wait();
53 }
54 
55 /* Stage 2: Executed after the kexec reboot. */
56 static void run_stage_2(int luo_fd, int state_session_fd)
57 {
58 	int i, stage;
59 
60 	ksft_print_msg("[STAGE 2] Starting post-kexec verification...\n");
61 
62 	restore_and_read_stage(state_session_fd, STATE_MEMFD_TOKEN, &stage);
63 	if (stage != 2) {
64 		fail_exit("Expected stage 2, but state file contains %d",
65 			  stage);
66 	}
67 
68 	ksft_print_msg("[STAGE 2] Retrieving and finishing %d sessions...\n",
69 		       NUM_SESSIONS);
70 
71 	for (i = 0; i < NUM_SESSIONS; i++) {
72 		char name[LIVEUPDATE_SESSION_NAME_LENGTH];
73 		int s_fd;
74 
75 		snprintf(name, sizeof(name), "many-test-%d", i);
76 		s_fd = luo_retrieve_session(luo_fd, name);
77 		if (s_fd < 0) {
78 			fail_exit("luo_retrieve_session for '%s' at index %d",
79 				  name, i);
80 		}
81 
82 		if (luo_session_finish(s_fd) < 0) {
83 			fail_exit("luo_session_finish for '%s' at index %d",
84 				  name, i);
85 		}
86 		close(s_fd);
87 	}
88 
89 	ksft_print_msg("[STAGE 2] Finalizing state session...\n");
90 	if (luo_session_finish(state_session_fd) < 0)
91 		fail_exit("luo_session_finish for state session");
92 	close(state_session_fd);
93 
94 	ksft_print_msg("\n--- MANY-SESSIONS KEXEC TEST PASSED (%d sessions) ---\n",
95 		       NUM_SESSIONS);
96 }
97 
98 int main(int argc, char *argv[])
99 {
100 	return luo_test(argc, argv, STATE_SESSION_NAME,
101 			run_stage_1, run_stage_2);
102 }
103