From: David Matlack <dmatlack@google.com>
To: kexec@lists.infradead.org, linux-kernel@vger.kernel.org,
linux-kselftest@vger.kernel.org, linux-mm@kvack.org
Cc: Andrew Morton <akpm@linux-foundation.org>,
Mike Rapoport <rppt@kernel.org>,
Pasha Tatashin <pasha.tatashin@soleen.com>,
Pratyush Yadav <pratyush@kernel.org>,
Samiullah Khawaja <skhawaja@google.com>,
Shuah Khan <shuah@kernel.org>,
David Matlack <dmatlack@google.com>
Subject: [RFC PATCH 5/5] selftests: liveupdate: Add multi-session test coverage for session_retrieve_into
Date: Tue, 1 Sep 2026 18:07:13 +0000 [thread overview]
Message-ID: <20260901180713.4185641-6-dmatlack@google.com> (raw)
In-Reply-To: <20260901180713.4185641-1-dmatlack@google.com>
Extend the multi-session Live Update test to specifically verify the new
LIVEUPDATE_SESSION_RETRIEVE_INTO_FD ioctl path. In Stage 2 of the kexec
workflow, the test explicitly delegates topology by allocating a clean
tmpfs target and driving the folios into it through the new API,
verifying that the data preserves identically to the native KHO mapping.
Signed-off-by: David Matlack <dmatlack@google.com>
---
.../liveupdate/lib/include/libliveupdate.h | 1 +
.../selftests/liveupdate/lib/lu_utils.c | 33 +++++++++++
.../selftests/liveupdate/luo_multi_session.c | 56 ++++++++++++++++---
3 files changed, 83 insertions(+), 7 deletions(-)
diff --git a/tools/testing/selftests/liveupdate/lib/include/libliveupdate.h b/tools/testing/selftests/liveupdate/lib/include/libliveupdate.h
index fa07fed08364..8ab1e662eeaa 100644
--- a/tools/testing/selftests/liveupdate/lib/include/libliveupdate.h
+++ b/tools/testing/selftests/liveupdate/lib/include/libliveupdate.h
@@ -33,6 +33,7 @@ int luo_session_retrieve_fd(int session_fd, __u64 token);
int create_and_preserve_memfd(int session_fd, int token, const char *data);
int restore_and_verify_memfd(int session_fd, int token, const char *expected_data);
+int luo_verify_retrieve_into_memfd(int session_fd, int token, int mfd, const char *expected_data);
void create_state_file(int luo_fd, const char *session_name, int token,
int next_stage);
diff --git a/tools/testing/selftests/liveupdate/lib/lu_utils.c b/tools/testing/selftests/liveupdate/lib/lu_utils.c
index 74d41115c281..8ed9c367f92e 100644
--- a/tools/testing/selftests/liveupdate/lib/lu_utils.c
+++ b/tools/testing/selftests/liveupdate/lib/lu_utils.c
@@ -324,3 +324,36 @@ int luo_test(int argc, char *argv[],
return 0;
}
+
+int luo_verify_retrieve_into_memfd(int session_fd, int token, int mfd,
+ const char *expected_data)
+{
+ struct liveupdate_session_retrieve_into_fd retrieve_args = {
+ .size = sizeof(retrieve_args),
+ .token = token,
+ .fd = mfd,
+ };
+ long page_size = getpagesize();
+ void *map = MAP_FAILED;
+ int ret = -1;
+
+ ret = ioctl(session_fd, LIVEUPDATE_SESSION_RETRIEVE_INTO_FD, &retrieve_args);
+ if (ret < 0) {
+ ksft_print_msg("ioctl LIVEUPDATE_SESSION_RETRIEVE_INTO_FD failed\n");
+ return -errno;
+ }
+
+ map = mmap(NULL, page_size, PROT_READ, MAP_SHARED, mfd, 0);
+ if (map == MAP_FAILED)
+ return -errno;
+
+ if (expected_data && strcmp(expected_data, map) != 0) {
+ ksft_print_msg("Data mismatch! Expected '%s', Got '%s'\n",
+ expected_data, (char *)map);
+ munmap(map, page_size);
+ return -EINVAL;
+ }
+
+ munmap(map, page_size);
+ return 0;
+}
diff --git a/tools/testing/selftests/liveupdate/luo_multi_session.c b/tools/testing/selftests/liveupdate/luo_multi_session.c
index aac24a5f5ce3..7882f49aadaf 100644
--- a/tools/testing/selftests/liveupdate/luo_multi_session.c
+++ b/tools/testing/selftests/liveupdate/luo_multi_session.c
@@ -1,4 +1,9 @@
// SPDX-License-Identifier: GPL-2.0-only
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
/*
* Copyright (c) 2025, Google LLC.
@@ -31,6 +36,8 @@
static void run_stage_1(int luo_fd)
{
int s_empty1_fd, s_empty2_fd, s_files1_fd, s_files2_fd;
+ int tmpfs_fd;
+ void *map;
ksft_print_msg("[STAGE 1] Starting pre-kexec setup for multi-session test...\n");
@@ -53,25 +60,50 @@ static void run_stage_1(int luo_fd)
s_files1_fd = luo_create_session(luo_fd, SESSION_FILES_1);
if (s_files1_fd < 0)
fail_exit("luo_create_session for '%s'", SESSION_FILES_1);
+ ksft_print_msg(" -> Preserving memfd (token %#x, content: \"%s\")\n",
+ MFD1_TOKEN, MFD1_DATA);
if (create_and_preserve_memfd(s_files1_fd, MFD1_TOKEN, MFD1_DATA) < 0) {
fail_exit("create_and_preserve_memfd for token %#x",
MFD1_TOKEN);
}
- ksft_print_msg("[STAGE 1] Creating session '%s' with two memfds...\n",
+ ksft_print_msg("[STAGE 1] Creating session '%s' with memfd and tmpfs file...\n",
SESSION_FILES_2);
s_files2_fd = luo_create_session(luo_fd, SESSION_FILES_2);
if (s_files2_fd < 0)
fail_exit("luo_create_session for '%s'", SESSION_FILES_2);
+ ksft_print_msg(" -> Preserving memfd (token %#x, content: \"%s\")\n",
+ MFD2_TOKEN, MFD2_DATA);
if (create_and_preserve_memfd(s_files2_fd, MFD2_TOKEN, MFD2_DATA) < 0) {
fail_exit("create_and_preserve_memfd for token %#x",
MFD2_TOKEN);
}
- if (create_and_preserve_memfd(s_files2_fd, MFD3_TOKEN, MFD3_DATA) < 0) {
- fail_exit("create_and_preserve_memfd for token %#x",
- MFD3_TOKEN);
- }
+ ksft_print_msg(" -> Populating custom tmpfs file at /mnt/mfd3_source...\n");
+ mkdir("/mnt", 0777);
+ mount("tmpfs", "/mnt", "tmpfs", 0, NULL);
+ tmpfs_fd = open("/mnt/mfd3_source", O_CREAT | O_RDWR, 0666);
+ if (tmpfs_fd < 0)
+ fail_exit("failed to open tmpfs_fd");
+ ksft_print_msg(" -> Preserving generic tmpfs file (token %#x, content: \"%s\")\n",
+ MFD3_TOKEN, MFD3_DATA);
+ if (ftruncate(tmpfs_fd, getpagesize()) < 0)
+ fail_exit("ftruncate tmpfs_fd");
+ map = mmap(NULL, getpagesize(), PROT_WRITE, MAP_SHARED, tmpfs_fd, 0);
+ if (map == MAP_FAILED)
+ fail_exit("mmap tmpfs_fd");
+ strcpy(map, MFD3_DATA);
+ munmap(map, getpagesize());
+
+ struct liveupdate_session_preserve_fd preserve_args = {
+ .size = sizeof(preserve_args),
+ .token = MFD3_TOKEN,
+ .fd = tmpfs_fd,
+ };
+ if (ioctl(s_files2_fd, LIVEUPDATE_SESSION_PRESERVE_FD, &preserve_args) < 0)
+ fail_exit("preserve tmpfs fd");
+
+ close(tmpfs_fd);
close(luo_fd);
daemonize_and_wait();
@@ -110,6 +142,7 @@ static void run_stage_2(int luo_fd, int state_session_fd)
ksft_print_msg("[STAGE 2] Verifying contents of session '%s'...\n",
SESSION_FILES_1);
+ ksft_print_msg(" -> Retrieving memfd (token %#x) from session...\n", MFD1_TOKEN);
mfd1 = restore_and_verify_memfd(s_files1_fd, MFD1_TOKEN, MFD1_DATA);
if (mfd1 < 0)
fail_exit("restore_and_verify_memfd for token %#x", MFD1_TOKEN);
@@ -118,14 +151,23 @@ static void run_stage_2(int luo_fd, int state_session_fd)
ksft_print_msg("[STAGE 2] Verifying contents of session '%s'...\n",
SESSION_FILES_2);
+ ksft_print_msg(" -> Retrieving memfd (token %#x) from session...\n", MFD2_TOKEN);
mfd2 = restore_and_verify_memfd(s_files2_fd, MFD2_TOKEN, MFD2_DATA);
if (mfd2 < 0)
fail_exit("restore_and_verify_memfd for token %#x", MFD2_TOKEN);
close(mfd2);
- mfd3 = restore_and_verify_memfd(s_files2_fd, MFD3_TOKEN, MFD3_DATA);
+ ksft_print_msg(" -> Creating empty tmpfs file at /mnt/mfd3_target...\n");
+ mkdir("/mnt", 0777);
+ mount("tmpfs", "/mnt", "tmpfs", 0, NULL);
+ mfd3 = open("/mnt/mfd3_target", O_CREAT | O_RDWR, 0666);
if (mfd3 < 0)
- fail_exit("restore_and_verify_memfd for token %#x", MFD3_TOKEN);
+ fail_exit("open tmpfs target for retrieve_into");
+
+ ksft_print_msg(" -> Validating LIVEUPDATE_SESSION_RETRIEVE_INTO_FD (token %#x)...\n",
+ MFD3_TOKEN);
+ if (luo_verify_retrieve_into_memfd(s_files2_fd, MFD3_TOKEN, mfd3, MFD3_DATA) < 0)
+ fail_exit("luo_verify_retrieve_into_memfd for token %#x", MFD3_TOKEN);
close(mfd3);
ksft_print_msg("[STAGE 2] Test data verified successfully.\n");
--
2.55.0.966.g6673acef38-goog
prev parent reply other threads:[~2026-09-01 18:07 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-01 18:07 [RFC PATCH 0/5] liveupdate: LIVEUPDATE_SESSION_RETRIEVE_INTO_FD David Matlack
2026-09-01 18:07 ` [RFC PATCH 1/5] liveupdate: Extract luo_file token lookup logic into helper function David Matlack
2026-09-01 18:07 ` [RFC PATCH 2/5] liveupdate: Introduce SESSION_RETRIEVE_INTO_FD API and core support David Matlack
2026-09-01 18:07 ` [RFC PATCH 3/5] mm/memfd_luo: Implement retrieve_into callback for shmem folios David Matlack
2026-09-01 18:07 ` [RFC PATCH 4/5] mm/memfd_luo: Expand support beyond memfd to all generic shmem inodes David Matlack
2026-09-01 18:07 ` David Matlack [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260901180713.4185641-6-dmatlack@google.com \
--to=dmatlack@google.com \
--cc=akpm@linux-foundation.org \
--cc=kexec@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=pasha.tatashin@soleen.com \
--cc=pratyush@kernel.org \
--cc=rppt@kernel.org \
--cc=shuah@kernel.org \
--cc=skhawaja@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox