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