public inbox for linux-mm@kvack.org
 help / color / mirror / Atom feed
* [PATCH 0/6] selftests/liveupdate: add memfd tests
@ 2026-03-09 11:54 Pratyush Yadav
  2026-03-09 11:54 ` [PATCH 1/6] selftests/liveupdate: add framework for " Pratyush Yadav
                   ` (5 more replies)
  0 siblings, 6 replies; 17+ messages in thread
From: Pratyush Yadav @ 2026-03-09 11:54 UTC (permalink / raw)
  To: Pasha Tatashin, Mike Rapoport, Pratyush Yadav, Shuah Khan,
	Andrew Morton
  Cc: linux-kernel, linux-kselftest, linux-mm

From: "Pratyush Yadav (Google)" <pratyush@kernel.org>

Hi,

This series adds some tests for memfd preservation across a live update.
Currently memfd is only tested indirectly via luo_kexec_simple or
luo_multi_session. Add a dedicated test suite for it.

Patches 1 and 2 are preparatory, adding base framework and helpers, and
the other patches each add a test. Some of the code is taken from the
libluo patches [0] I sent a while ago.

[0] https://lore.kernel.org/linux-mm/20250723144649.1696299-33-pasha.tatashin@soleen.com/

Regards,
Pratyush Yadav

Pratyush Yadav (Google) (6):
  selftests/liveupdate: add framework for memfd tests
  selftests/liveupdate: add helper functions for memfd tests
  selftests/liveupdate: add test for memfd content preservation
  selftests/liveupdate: add test for zero-size memfd preservation
  selftests/liveupdate: add test for operations on a preserved memfd
  selftests/liveupdate: add fallocate test for memfd

 tools/testing/selftests/liveupdate/Makefile   |   2 +
 .../testing/selftests/liveupdate/luo_memfd.c  | 306 ++++++++++++++++++
 .../selftests/liveupdate/luo_test_utils.c     | 175 +++++++++-
 .../selftests/liveupdate/luo_test_utils.h     |   9 +
 4 files changed, 491 insertions(+), 1 deletion(-)
 create mode 100644 tools/testing/selftests/liveupdate/luo_memfd.c


base-commit: 6f04517c06a898228eda00cbd8573d9e84003108
-- 
2.53.0.473.g4a7958ca14-goog



^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 1/6] selftests/liveupdate: add framework for memfd tests
  2026-03-09 11:54 [PATCH 0/6] selftests/liveupdate: add memfd tests Pratyush Yadav
@ 2026-03-09 11:54 ` Pratyush Yadav
  2026-03-10 11:08   ` Usama Arif
  2026-03-18  7:15   ` Mike Rapoport
  2026-03-09 11:54 ` [PATCH 2/6] selftests/liveupdate: add helper functions " Pratyush Yadav
                   ` (4 subsequent siblings)
  5 siblings, 2 replies; 17+ messages in thread
From: Pratyush Yadav @ 2026-03-09 11:54 UTC (permalink / raw)
  To: Pasha Tatashin, Mike Rapoport, Pratyush Yadav, Shuah Khan,
	Andrew Morton
  Cc: linux-kernel, linux-kselftest, linux-mm

From: "Pratyush Yadav (Google)" <pratyush@kernel.org>

Currently memfd preservation using LUO is only tested indirectly via the
luo_multi_session or luo_kexec_simple tests. Their main purpose is to
test other live update functionality.

Add a framework for writing memfd tests. The framework hooks into the
kselftest harness, but adds some things on top to make it suitable for
live update.

The LUO FD (/dev/liveupdate) can only be opened by one process at a
time. Each test runs in its own process. This means the LUO FD must be
owned by the main process and shared to children. main() opens the LUO
FD and shares it to child runners using a global variable.

Live update tests run in two stages. One before kexec and one after.
Detect the stage using a special state session. If the session is
present, it means the test is in post-kexec state.

Additionally, take in an optional --stage argument that lets callers
specify expected stage. This is useful as a safety net to catch LUO core
failures. If LUO core fails to preserve the state session properly, this
option can help detect this and fail early. Since the option is not
recognized by the kselftest harness, remove it from argv before calling
test_harness_run().

Signed-off-by: Pratyush Yadav (Google) <pratyush@kernel.org>
---
 tools/testing/selftests/liveupdate/Makefile   |  1 +
 .../testing/selftests/liveupdate/luo_memfd.c  | 77 +++++++++++++++++++
 2 files changed, 78 insertions(+)
 create mode 100644 tools/testing/selftests/liveupdate/luo_memfd.c

diff --git a/tools/testing/selftests/liveupdate/Makefile b/tools/testing/selftests/liveupdate/Makefile
index 080754787ede..051daae55eec 100644
--- a/tools/testing/selftests/liveupdate/Makefile
+++ b/tools/testing/selftests/liveupdate/Makefile
@@ -6,6 +6,7 @@ TEST_GEN_PROGS += liveupdate
 
 TEST_GEN_PROGS_EXTENDED += luo_kexec_simple
 TEST_GEN_PROGS_EXTENDED += luo_multi_session
+TEST_GEN_PROGS_EXTENDED += luo_memfd
 
 TEST_FILES += do_kexec.sh
 
diff --git a/tools/testing/selftests/liveupdate/luo_memfd.c b/tools/testing/selftests/liveupdate/luo_memfd.c
new file mode 100644
index 000000000000..b779eee18387
--- /dev/null
+++ b/tools/testing/selftests/liveupdate/luo_memfd.c
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright (c) 2026, Google LLC.
+ * Pratyush Yadav (Google) <pratyush@kernel.org>
+ */
+
+/*
+ * Selftests for memfd preservation via LUO.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#include <linux/liveupdate.h>
+
+#include "../kselftest.h"
+#include "../kselftest_harness.h"
+
+#include "luo_test_utils.h"
+
+#define STATE_SESSION_NAME "luo-state"
+#define STATE_MEMFD_TOKEN 1
+
+#define LIVEUPDATE_DEV "/dev/liveupdate"
+static int luo_fd = -1, stage;
+
+int main(int argc, char *argv[])
+{
+	int session, expected_stage = 0;
+
+	/*
+	 * The test takes an optional --stage argument. This lets callers
+	 * provide the expected stage, and if that doesn't match the test errors
+	 * out.
+	 *
+	 * Look for the stage. Since test_harness_run() doesn't recognize it,
+	 * once found, remove it from argv.
+	 */
+	for (int i = 1; i < argc; i++) {
+		if (strcmp(argv[i], "--stage") == 0) {
+			if (i + 1 < argc) {
+				expected_stage = atoi(argv[i + 1]);
+				memmove(&argv[i], &argv[i + 2], (argc - i - 1) * sizeof(char *));
+				argc -= 2;
+				i--;
+			} else {
+				ksft_exit_fail_msg("Option --stage requires an argument\n");
+			}
+		}
+	}
+
+	luo_fd = luo_open_device();
+	if (luo_fd < 0)
+		ksft_exit_skip("Failed to open %s (%s). Is the luo module loaded?\n",
+			       strerror(errno), LUO_DEVICE);
+
+	session = luo_retrieve_session(luo_fd, STATE_SESSION_NAME);
+	if (session == -ENOENT)
+		stage = 1;
+	else if (session >= 0)
+		stage = 2;
+	else
+		fail_exit("Failed to check for state session");
+
+	if (expected_stage && expected_stage != stage)
+		ksft_exit_fail_msg("Stage mismatch: expected %d, got %d\n",
+				   expected_stage, stage);
+
+	if (stage == 1)
+		create_state_file(luo_fd, STATE_SESSION_NAME, STATE_MEMFD_TOKEN, 2);
+
+	test_harness_run(argc, argv);
+}
-- 
2.53.0.473.g4a7958ca14-goog



^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 2/6] selftests/liveupdate: add helper functions for memfd tests
  2026-03-09 11:54 [PATCH 0/6] selftests/liveupdate: add memfd tests Pratyush Yadav
  2026-03-09 11:54 ` [PATCH 1/6] selftests/liveupdate: add framework for " Pratyush Yadav
@ 2026-03-09 11:54 ` Pratyush Yadav
  2026-03-17 11:01   ` Mike Rapoport
  2026-03-18  7:20   ` Mike Rapoport
  2026-03-09 11:54 ` [PATCH 3/6] selftests/liveupdate: add test for memfd content preservation Pratyush Yadav
                   ` (3 subsequent siblings)
  5 siblings, 2 replies; 17+ messages in thread
From: Pratyush Yadav @ 2026-03-09 11:54 UTC (permalink / raw)
  To: Pasha Tatashin, Mike Rapoport, Pratyush Yadav, Shuah Khan,
	Andrew Morton
  Cc: linux-kernel, linux-kselftest, linux-mm

From: "Pratyush Yadav (Google)" <pratyush@kernel.org>

Add some helper functions that will be used by memfd tests. This moves
some of the complexity out of the test itself, which results in better
test readability and less code duplication.

Signed-off-by: Pratyush Yadav <ptyadav@amazon.de>
Signed-off-by: Pratyush Yadav (Google) <pratyush@kernel.org>
---
 .../selftests/liveupdate/luo_test_utils.c     | 175 +++++++++++++++++-
 .../selftests/liveupdate/luo_test_utils.h     |   9 +
 2 files changed, 183 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/liveupdate/luo_test_utils.c b/tools/testing/selftests/liveupdate/luo_test_utils.c
index 3c8721c505df..45ace3697ee6 100644
--- a/tools/testing/selftests/liveupdate/luo_test_utils.c
+++ b/tools/testing/selftests/liveupdate/luo_test_utils.c
@@ -1,8 +1,12 @@
 // SPDX-License-Identifier: GPL-2.0-only
 
 /*
- * Copyright (c) 2025, Google LLC.
+ * Copyright (c) 2025-2026, Google LLC.
  * Pasha Tatashin <pasha.tatashin@soleen.com>
+ * Pratyush Yadav (Google) <pratyush@kernel.org>
+ *
+ * Copyright (C) 2025 Amazon.com Inc. or its affiliates.
+ * Pratyush Yadav <ptyadav@amazon.de>
  */
 
 #define _GNU_SOURCE
@@ -23,6 +27,175 @@
 
 #include "luo_test_utils.h"
 
+/* Read exactly specified size from fd. Any less results in error. */
+int read_size(int fd, char *buffer, size_t size)
+{
+	size_t remain = size;
+	ssize_t bytes_read;
+
+	while (remain) {
+		bytes_read = read(fd, buffer, remain);
+		if (bytes_read == 0)
+			return -ENODATA;
+		if (bytes_read < 0)
+			return -errno;
+
+		remain -= bytes_read;
+	}
+
+	return 0;
+}
+
+/* Write exactly specified size from fd. Any less results in error. */
+int write_size(int fd, const char *buffer, size_t size)
+{
+	size_t remain = size;
+	ssize_t written;
+
+	while (remain) {
+		written = write(fd, buffer, remain);
+		if (written == 0)
+			return -EIO;
+		if (written < 0)
+			return -errno;
+
+		remain -= written;
+	}
+
+	return 0;
+}
+
+int generate_random_data(char *buffer, size_t size)
+{
+	int fd, ret;
+
+	fd = open("/dev/urandom", O_RDONLY);
+	if (fd < 0)
+		return -errno;
+
+	ret = read_size(fd, buffer, size);
+	close(fd);
+	return ret;
+}
+
+int save_test_data(const char *filename, const char *buffer, size_t size)
+{
+	int fd, ret;
+
+	fd = open(filename, O_RDWR | O_CREAT, 0666);
+	if (fd < 0)
+		return -errno;
+
+	ret = write_size(fd, buffer, size);
+	fsync(fd);
+	close(fd);
+	return ret;
+}
+
+int load_test_data(const char *filename, char *buffer, size_t size)
+{
+	int fd, ret;
+
+	fd = open(filename, O_RDONLY);
+	if (fd < 0)
+		return -errno;
+
+	ret = read_size(fd, buffer, size);
+	close(fd);
+	return ret;
+}
+
+/* Create and initialize a memfd with random data. */
+int create_random_memfd(const char *memfd_name, char *buffer, size_t size)
+{
+	int fd;
+	int ret;
+
+	fd = memfd_create(memfd_name, 0);
+	if (fd < 0)
+		return -errno;
+
+	ret = generate_random_data(buffer, size);
+	if (ret < 0) {
+		close(fd);
+		return ret;
+	}
+
+	if (write_size(fd, buffer, size) < 0) {
+		close(fd);
+		return -errno;
+	}
+
+	/* Reset file position to beginning */
+	if (lseek(fd, 0, SEEK_SET) < 0) {
+		close(fd);
+		return -errno;
+	}
+
+	return fd;
+}
+
+/*
+ * Make sure fd contains expected data up to size. Returns 0 on success, 1 on
+ * data mismatch, -errno on error.
+ */
+int verify_fd_content(int fd, const char *expected_data, size_t size)
+{
+	char *buffer;
+	int ret;
+
+	buffer = malloc(size);
+	if (!buffer)
+		return -ENOMEM;
+
+	/* Reset file position to beginning */
+	if (lseek(fd, 0, SEEK_SET) < 0) {
+		ret = -errno;
+		goto out;
+	}
+
+	ret = read_size(fd, buffer, size);
+	if (ret < 0)
+		goto out;
+
+	if (memcmp(buffer, expected_data, size) != 0) {
+		ret = 1;
+		goto out;
+	}
+
+	ret = 0;
+
+out:
+	free(buffer);
+	return ret;
+}
+
+/*
+ * Verify fd content using mmap. Returns 0 on success, 1 on data mismatch,
+ * -errno on error.
+ */
+int verify_fd_content_mmap(int fd, const char *expected_data, size_t size)
+{
+	char *mapped_mem;
+	int ret;
+
+	mapped_mem = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
+	if (mapped_mem == MAP_FAILED)
+		return -errno;
+
+	/* ret = memcmp(mapped_mem, expected_data, size) ? 1 : 0; */
+	ret = 0;
+	for (size_t i = 0; i < size; i++) {
+		if (mapped_mem[i] != expected_data[i]) {
+			ret = 1;
+			break;
+		}
+	}
+
+	munmap(mapped_mem, size);
+	return ret;
+}
+
 int luo_open_device(void)
 {
 	return open(LUO_DEVICE, O_RDWR);
diff --git a/tools/testing/selftests/liveupdate/luo_test_utils.h b/tools/testing/selftests/liveupdate/luo_test_utils.h
index 90099bf49577..d1b85703708b 100644
--- a/tools/testing/selftests/liveupdate/luo_test_utils.h
+++ b/tools/testing/selftests/liveupdate/luo_test_utils.h
@@ -35,6 +35,15 @@ void restore_and_read_stage(int state_session_fd, int token, int *stage);
 
 void daemonize_and_wait(void);
 
+int read_size(int fd, char *buffer, size_t size);
+int write_size(int fd, const char *buffer, size_t size);
+int generate_random_data(char *buffer, size_t size);
+int save_test_data(const char *filename, const char *buffer, size_t size);
+int load_test_data(const char *filename, char *buffer, size_t size);
+int create_random_memfd(const char *memfd_name, char *buffer, size_t size);
+int verify_fd_content(int fd, const char *expected_data, size_t size);
+int verify_fd_content_mmap(int fd, const char *expected_data, size_t size);
+
 typedef void (*luo_test_stage1_fn)(int luo_fd);
 typedef void (*luo_test_stage2_fn)(int luo_fd, int state_session_fd);
 
-- 
2.53.0.473.g4a7958ca14-goog



^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 3/6] selftests/liveupdate: add test for memfd content preservation
  2026-03-09 11:54 [PATCH 0/6] selftests/liveupdate: add memfd tests Pratyush Yadav
  2026-03-09 11:54 ` [PATCH 1/6] selftests/liveupdate: add framework for " Pratyush Yadav
  2026-03-09 11:54 ` [PATCH 2/6] selftests/liveupdate: add helper functions " Pratyush Yadav
@ 2026-03-09 11:54 ` Pratyush Yadav
  2026-03-18  7:31   ` Mike Rapoport
  2026-03-09 11:54 ` [PATCH 4/6] selftests/liveupdate: add test for zero-size memfd preservation Pratyush Yadav
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 17+ messages in thread
From: Pratyush Yadav @ 2026-03-09 11:54 UTC (permalink / raw)
  To: Pasha Tatashin, Mike Rapoport, Pratyush Yadav, Shuah Khan,
	Andrew Morton
  Cc: linux-kernel, linux-kselftest, linux-mm

From: "Pratyush Yadav (Google)" <pratyush@kernel.org>

Add a selftest that makes sure the contents of a memfd are correctly
preserved across a live update. In stage 1, create a memfd and fill it
with random data, and preserve it. Save the random data to the file
system. This will be used by stage 2 to verify the contents are correct.

In stage 2, retrieve the memfd and compare its contents with the
contents saved on the file system.

Signed-off-by: Pratyush Yadav <ptyadav@amazon.de>
Signed-off-by: Pratyush Yadav (Google) <pratyush@kernel.org>
---
 tools/testing/selftests/liveupdate/Makefile   |  1 +
 .../testing/selftests/liveupdate/luo_memfd.c  | 61 +++++++++++++++++++
 2 files changed, 62 insertions(+)

diff --git a/tools/testing/selftests/liveupdate/Makefile b/tools/testing/selftests/liveupdate/Makefile
index 051daae55eec..8e2eb6500c07 100644
--- a/tools/testing/selftests/liveupdate/Makefile
+++ b/tools/testing/selftests/liveupdate/Makefile
@@ -13,6 +13,7 @@ TEST_FILES += do_kexec.sh
 include ../lib.mk
 
 CFLAGS += $(KHDR_INCLUDES)
+CFLAGS += -I$(top_srcdir)/tools/include
 CFLAGS += -Wall -O2 -Wno-unused-function
 CFLAGS += -MD
 
diff --git a/tools/testing/selftests/liveupdate/luo_memfd.c b/tools/testing/selftests/liveupdate/luo_memfd.c
index b779eee18387..52b5f6b16e19 100644
--- a/tools/testing/selftests/liveupdate/luo_memfd.c
+++ b/tools/testing/selftests/liveupdate/luo_memfd.c
@@ -3,6 +3,9 @@
 /*
  * Copyright (c) 2026, Google LLC.
  * Pratyush Yadav (Google) <pratyush@kernel.org>
+ *
+ * Copyright (C) 2025 Amazon.com Inc. or its affiliates.
+ * Pratyush Yadav <ptyadav@amazon.de>
  */
 
 /*
@@ -11,11 +14,14 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#include <stdlib.h>
 #include <string.h>
 #include <sys/ioctl.h>
+#include <sys/mman.h>
 #include <unistd.h>
 
 #include <linux/liveupdate.h>
+#include <linux/sizes.h>
 
 #include "../kselftest.h"
 #include "../kselftest_harness.h"
@@ -25,9 +31,64 @@
 #define STATE_SESSION_NAME "luo-state"
 #define STATE_MEMFD_TOKEN 1
 
+#define MEMFD_DATA_SESSION_NAME "memfd_data_session"
+#define MEMFD_DATA_TOKEN 1
+#define MEMFD_DATA_BUFFER_SIZE SZ_1M
+#define RANDOM_DATA_FILE "luo_random_data.bin"
+
 #define LIVEUPDATE_DEV "/dev/liveupdate"
 static int luo_fd = -1, stage;
 
+/*
+ * Test that a memfd with its data is preserved across live update.
+ */
+TEST(memfd_data)
+{
+	int fd, session;
+	char *buffer;
+	struct liveupdate_session_preserve_fd preserve_arg = { .size = sizeof(preserve_arg) };
+	struct liveupdate_session_retrieve_fd retrieve_arg = { .size = sizeof(retrieve_arg) };
+
+	buffer = malloc(MEMFD_DATA_BUFFER_SIZE);
+	ASSERT_NE(buffer, NULL);
+
+	switch (stage) {
+	case 1:
+		session = luo_create_session(luo_fd, MEMFD_DATA_SESSION_NAME);
+		ASSERT_GE(session, 0);
+
+		fd = create_random_memfd("memfd_data", buffer, MEMFD_DATA_BUFFER_SIZE);
+		ASSERT_GE(fd, 0);
+
+		ASSERT_EQ(save_test_data(RANDOM_DATA_FILE, buffer, MEMFD_DATA_BUFFER_SIZE), 0);
+
+		preserve_arg.fd = fd;
+		preserve_arg.token = MEMFD_DATA_TOKEN;
+		ASSERT_GE(ioctl(session, LIVEUPDATE_SESSION_PRESERVE_FD, &preserve_arg), 0);
+
+		daemonize_and_wait();
+		break;
+	case 2:
+		session = luo_retrieve_session(luo_fd, MEMFD_DATA_SESSION_NAME);
+		ASSERT_GE(session, 0);
+
+		ASSERT_EQ(load_test_data(RANDOM_DATA_FILE, buffer, MEMFD_DATA_BUFFER_SIZE), 0);
+
+		retrieve_arg.token = MEMFD_DATA_TOKEN;
+		ASSERT_GE(ioctl(session, LIVEUPDATE_SESSION_RETRIEVE_FD, &retrieve_arg), 0);
+		fd = retrieve_arg.fd;
+		ASSERT_GE(fd, 0);
+
+		ASSERT_EQ(verify_fd_content(fd, buffer, MEMFD_DATA_BUFFER_SIZE), 0);
+
+		ASSERT_EQ(luo_session_finish(session), 0);
+		break;
+	default:
+		TH_LOG("Unknown stage %d\n", stage);
+		ASSERT_FALSE(true);
+	}
+}
+
 int main(int argc, char *argv[])
 {
 	int session, expected_stage = 0;
-- 
2.53.0.473.g4a7958ca14-goog



^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 4/6] selftests/liveupdate: add test for zero-size memfd preservation
  2026-03-09 11:54 [PATCH 0/6] selftests/liveupdate: add memfd tests Pratyush Yadav
                   ` (2 preceding siblings ...)
  2026-03-09 11:54 ` [PATCH 3/6] selftests/liveupdate: add test for memfd content preservation Pratyush Yadav
@ 2026-03-09 11:54 ` Pratyush Yadav
  2026-03-18  7:35   ` Mike Rapoport
  2026-03-09 11:54 ` [PATCH 5/6] selftests/liveupdate: add test for operations on a preserved memfd Pratyush Yadav
  2026-03-09 11:54 ` [PATCH 6/6] selftests/liveupdate: add fallocate test for memfd Pratyush Yadav
  5 siblings, 1 reply; 17+ messages in thread
From: Pratyush Yadav @ 2026-03-09 11:54 UTC (permalink / raw)
  To: Pasha Tatashin, Mike Rapoport, Pratyush Yadav, Shuah Khan,
	Andrew Morton
  Cc: linux-kernel, linux-kselftest, linux-mm

From: "Pratyush Yadav (Google)" <pratyush@kernel.org>

A zero-size memfd is a special case of memfd preservation. It takes a
different path from normal both during preservation and during restore.
In the serialization structure, the number of folios if zero and the
vmalloc array with folios is empty. The restore logic should check for
this and make sure to not touch the invalid array.

Add a test to make sure this path works as expected. In stage 1, the
test creates and preserves a memfd without any data. In stage 2, the
test retrieves the memfd and makes sure it is still without data.

Signed-off-by: Pratyush Yadav (Google) <pratyush@kernel.org>
---
 .../testing/selftests/liveupdate/luo_memfd.c  | 47 +++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/tools/testing/selftests/liveupdate/luo_memfd.c b/tools/testing/selftests/liveupdate/luo_memfd.c
index 52b5f6b16e19..56106cd09978 100644
--- a/tools/testing/selftests/liveupdate/luo_memfd.c
+++ b/tools/testing/selftests/liveupdate/luo_memfd.c
@@ -36,6 +36,9 @@
 #define MEMFD_DATA_BUFFER_SIZE SZ_1M
 #define RANDOM_DATA_FILE "luo_random_data.bin"
 
+#define ZERO_SESSION_NAME "zero_session"
+#define ZERO_MEMFD_TOKEN 1
+
 #define LIVEUPDATE_DEV "/dev/liveupdate"
 static int luo_fd = -1, stage;
 
@@ -89,6 +92,50 @@ TEST(memfd_data)
 	}
 }
 
+/*
+ * Test that a zero-sized memfd is preserved across live update.
+ */
+TEST(zero_memfd)
+{
+	int zero_fd, session;
+	struct liveupdate_session_preserve_fd preserve_arg = { .size = sizeof(preserve_arg) };
+	struct liveupdate_session_retrieve_fd retrieve_arg = { .size = sizeof(retrieve_arg) };
+
+	switch (stage) {
+	case 1:
+		session = luo_create_session(luo_fd, ZERO_SESSION_NAME);
+		ASSERT_GE(session, 0);
+
+		zero_fd = memfd_create("zero_memfd", 0);
+		ASSERT_GE(zero_fd, 0);
+
+		preserve_arg.fd = zero_fd;
+		preserve_arg.token = ZERO_MEMFD_TOKEN;
+		ASSERT_GE(ioctl(session, LIVEUPDATE_SESSION_PRESERVE_FD, &preserve_arg), 0);
+
+		close(zero_fd);
+		daemonize_and_wait();
+		break;
+	case 2:
+		session = luo_retrieve_session(luo_fd, ZERO_SESSION_NAME);
+		ASSERT_GE(session, 0);
+
+		retrieve_arg.token = ZERO_MEMFD_TOKEN;
+		ASSERT_GE(ioctl(session, LIVEUPDATE_SESSION_RETRIEVE_FD, &retrieve_arg), 0);
+		zero_fd = retrieve_arg.fd;
+		ASSERT_GE(zero_fd, 0);
+
+		ASSERT_EQ(lseek(zero_fd, 0, SEEK_END), 0);
+
+		ASSERT_EQ(luo_session_finish(session), 0);
+		close(zero_fd);
+		break;
+	default:
+		TH_LOG("Unknown stage %d\n", stage);
+		ASSERT_FALSE(true);
+	}
+}
+
 int main(int argc, char *argv[])
 {
 	int session, expected_stage = 0;
-- 
2.53.0.473.g4a7958ca14-goog



^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 5/6] selftests/liveupdate: add test for operations on a preserved memfd
  2026-03-09 11:54 [PATCH 0/6] selftests/liveupdate: add memfd tests Pratyush Yadav
                   ` (3 preceding siblings ...)
  2026-03-09 11:54 ` [PATCH 4/6] selftests/liveupdate: add test for zero-size memfd preservation Pratyush Yadav
@ 2026-03-09 11:54 ` Pratyush Yadav
  2026-03-18  7:38   ` Mike Rapoport
  2026-03-09 11:54 ` [PATCH 6/6] selftests/liveupdate: add fallocate test for memfd Pratyush Yadav
  5 siblings, 1 reply; 17+ messages in thread
From: Pratyush Yadav @ 2026-03-09 11:54 UTC (permalink / raw)
  To: Pasha Tatashin, Mike Rapoport, Pratyush Yadav, Shuah Khan,
	Andrew Morton
  Cc: linux-kernel, linux-kselftest, linux-mm

From: "Pratyush Yadav (Google)" <pratyush@kernel.org>

Once a memfd is preserved, certain operations are not allowed to
succeed since they might make the state of the memfd inconsistent with
the serialized state. Among these operations are truncating or growing
the memfd. Writes and reads to already existing memfd should succeed.

Add a test that makes sure a preserved memfd does not allow growing or
shrinking, but does allow reads and writes to existing memory to go
thorough.

Signed-off-by: Pratyush Yadav <ptyadav@amazon.de>
Signed-off-by: Pratyush Yadav (Google) <pratyush@kernel.org>
---
 .../testing/selftests/liveupdate/luo_memfd.c  | 57 +++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/tools/testing/selftests/liveupdate/luo_memfd.c b/tools/testing/selftests/liveupdate/luo_memfd.c
index 56106cd09978..75f88101e7b5 100644
--- a/tools/testing/selftests/liveupdate/luo_memfd.c
+++ b/tools/testing/selftests/liveupdate/luo_memfd.c
@@ -39,6 +39,10 @@
 #define ZERO_SESSION_NAME "zero_session"
 #define ZERO_MEMFD_TOKEN 1
 
+#define PRESERVED_SESSION_NAME "preserved_session"
+#define PRESERVED_MEMFD_TOKEN 1
+#define PRESERVED_BUFFER_SIZE SZ_1M
+
 #define LIVEUPDATE_DEV "/dev/liveupdate"
 static int luo_fd = -1, stage;
 
@@ -136,6 +140,59 @@ TEST(zero_memfd)
 	}
 }
 
+/*
+ * Test that preserved memfd can't grow or shrink, but reads and writes still
+ * work.
+ */
+TEST(preserved_ops)
+{
+	char write_buffer[128] = {'A'};
+	int fd, session;
+	char *buffer;
+	struct liveupdate_session_preserve_fd preserve_arg = { .size = sizeof(preserve_arg) };
+
+	if (stage != 1)
+		SKIP(return, "test only expected to run on stage 1");
+
+	buffer = malloc(PRESERVED_BUFFER_SIZE);
+	ASSERT_NE(buffer, NULL);
+
+	session = luo_create_session(luo_fd, PRESERVED_SESSION_NAME);
+	ASSERT_GE(session, 0);
+
+	fd = create_random_memfd("preserved_memfd", buffer, PRESERVED_BUFFER_SIZE);
+	ASSERT_GE(fd, 0);
+
+	preserve_arg.fd = fd;
+	preserve_arg.token = PRESERVED_MEMFD_TOKEN;
+	ASSERT_GE(ioctl(session, LIVEUPDATE_SESSION_PRESERVE_FD, &preserve_arg), 0);
+
+	/*
+	 * Write to the preserved memfd (within existing size). This should
+	 * work.
+	 */
+	ASSERT_GE(lseek(fd, 0, SEEK_SET), 0);
+	/* Write buffer is smaller than total file size. */
+	ASSERT_EQ(write_size(fd, write_buffer, sizeof(write_buffer)), 0);
+	ASSERT_EQ(verify_fd_content(fd, write_buffer, sizeof(write_buffer)), 0);
+
+	/* Try to grow the file using write(). */
+
+	/* First, seek to one byte behind initial size. */
+	ASSERT_GE(lseek(fd, PRESERVED_BUFFER_SIZE - 1, SEEK_SET), 0);
+
+	/*
+	 * Then, write some data that should increase the file size. This should
+	 * fail.
+	 */
+	ASSERT_LT(write_size(fd, write_buffer, sizeof(write_buffer)), 0);
+	ASSERT_EQ(lseek(fd, 0, SEEK_END), PRESERVED_BUFFER_SIZE);
+
+	/* Try to shrink the file using truncate. This should also fail. */
+	ASSERT_LT(ftruncate(fd, PRESERVED_BUFFER_SIZE / 2), 0);
+	ASSERT_EQ(lseek(fd, 0, SEEK_END), PRESERVED_BUFFER_SIZE);
+}
+
 int main(int argc, char *argv[])
 {
 	int session, expected_stage = 0;
-- 
2.53.0.473.g4a7958ca14-goog



^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 6/6] selftests/liveupdate: add fallocate test for memfd
  2026-03-09 11:54 [PATCH 0/6] selftests/liveupdate: add memfd tests Pratyush Yadav
                   ` (4 preceding siblings ...)
  2026-03-09 11:54 ` [PATCH 5/6] selftests/liveupdate: add test for operations on a preserved memfd Pratyush Yadav
@ 2026-03-09 11:54 ` Pratyush Yadav
  2026-03-18  7:43   ` Mike Rapoport
  5 siblings, 1 reply; 17+ messages in thread
From: Pratyush Yadav @ 2026-03-09 11:54 UTC (permalink / raw)
  To: Pasha Tatashin, Mike Rapoport, Pratyush Yadav, Shuah Khan,
	Andrew Morton
  Cc: linux-kernel, linux-kselftest, linux-mm

From: "Pratyush Yadav (Google)" <pratyush@kernel.org>

When memory is added to a memfd via fallocate(), it does not get zeroed
immediately. This is tracked by the absence of the uptodate folio flag.
Initially, memfd preservation simply saved the folio flags at preserve
time. This led to a bug, where all writes to un-initialized fallocated
memory after preserve were lost after live update. This is fixed by
patch [0] (not in mainline as of writing this).

Add a test that fallocates some memory in a memfd, preserves it, writes
to it. Then in stage 2 it verifies the written content is still present.

[0] https://lore.kernel.org/linux-mm/20260223173931.2221759-2-pratyush@kernel.org/

Signed-off-by: Pratyush Yadav (Google) <pratyush@kernel.org>
---
 .../testing/selftests/liveupdate/luo_memfd.c  | 64 +++++++++++++++++++
 1 file changed, 64 insertions(+)

diff --git a/tools/testing/selftests/liveupdate/luo_memfd.c b/tools/testing/selftests/liveupdate/luo_memfd.c
index 75f88101e7b5..dde3c78db50e 100644
--- a/tools/testing/selftests/liveupdate/luo_memfd.c
+++ b/tools/testing/selftests/liveupdate/luo_memfd.c
@@ -43,6 +43,11 @@
 #define PRESERVED_MEMFD_TOKEN 1
 #define PRESERVED_BUFFER_SIZE SZ_1M
 
+#define FALLOCATE_SESSION_NAME "fallocate_session"
+#define FALLOCATE_MEMFD_TOKEN 1
+#define FALLOCATE_BUFFER_SIZE SZ_1M
+#define RANDOM_DATA_FILE_FALLOCATE "luo_random_data_fallocate.bin"
+
 #define LIVEUPDATE_DEV "/dev/liveupdate"
 static int luo_fd = -1, stage;
 
@@ -193,6 +198,65 @@ TEST(preserved_ops)
 	ASSERT_EQ(lseek(fd, 0, SEEK_END), PRESERVED_BUFFER_SIZE);
 }
 
+/*
+ * Test that an fallocated memfd is preserved across live update and can be
+ * written to after being preserved.
+ */
+TEST(fallocate_memfd)
+{
+	int fd, session;
+	char *buffer;
+	struct liveupdate_session_preserve_fd preserve_arg = { .size = sizeof(preserve_arg) };
+	struct liveupdate_session_retrieve_fd retrieve_arg = { .size = sizeof(retrieve_arg) };
+
+	buffer = malloc(FALLOCATE_BUFFER_SIZE);
+	ASSERT_NE(buffer, NULL);
+
+	switch (stage) {
+	case 1:
+		session = luo_create_session(luo_fd, FALLOCATE_SESSION_NAME);
+		ASSERT_GE(session, 0);
+
+		fd = memfd_create("fallocate_memfd", 0);
+		ASSERT_GE(fd, 0);
+
+		/* Fallocate memory but do not write to it yet */
+		ASSERT_EQ(fallocate(fd, 0, 0, FALLOCATE_BUFFER_SIZE), 0);
+
+		preserve_arg.fd = fd;
+		preserve_arg.token = FALLOCATE_MEMFD_TOKEN;
+		ASSERT_GE(ioctl(session, LIVEUPDATE_SESSION_PRESERVE_FD, &preserve_arg), 0);
+
+		/* Now write to it after preserving */
+		ASSERT_GE(generate_random_data(buffer, FALLOCATE_BUFFER_SIZE), 0);
+		ASSERT_EQ(save_test_data(RANDOM_DATA_FILE_FALLOCATE, buffer, FALLOCATE_BUFFER_SIZE), 0);
+
+		ASSERT_GE(lseek(fd, 0, SEEK_SET), 0);
+		ASSERT_EQ(write_size(fd, buffer, FALLOCATE_BUFFER_SIZE), 0);
+
+		daemonize_and_wait();
+		break;
+	case 2:
+		session = luo_retrieve_session(luo_fd, FALLOCATE_SESSION_NAME);
+		ASSERT_GE(session, 0);
+
+		ASSERT_EQ(load_test_data(RANDOM_DATA_FILE_FALLOCATE, buffer, FALLOCATE_BUFFER_SIZE), 0);
+
+		retrieve_arg.token = FALLOCATE_MEMFD_TOKEN;
+		ASSERT_GE(ioctl(session, LIVEUPDATE_SESSION_RETRIEVE_FD, &retrieve_arg), 0);
+		fd = retrieve_arg.fd;
+		ASSERT_GE(fd, 0);
+
+		ASSERT_EQ(verify_fd_content(fd, buffer, FALLOCATE_BUFFER_SIZE), 0);
+
+		ASSERT_EQ(luo_session_finish(session), 0);
+		break;
+	default:
+		TH_LOG("Unknown stage %d\n", stage);
+		ASSERT_FALSE(true);
+	}
+}
+
 int main(int argc, char *argv[])
 {
 	int session, expected_stage = 0;
-- 
2.53.0.473.g4a7958ca14-goog



^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH 1/6] selftests/liveupdate: add framework for memfd tests
  2026-03-09 11:54 ` [PATCH 1/6] selftests/liveupdate: add framework for " Pratyush Yadav
@ 2026-03-10 11:08   ` Usama Arif
  2026-03-13 10:05     ` Pratyush Yadav
  2026-03-18  7:15   ` Mike Rapoport
  1 sibling, 1 reply; 17+ messages in thread
From: Usama Arif @ 2026-03-10 11:08 UTC (permalink / raw)
  To: Pratyush Yadav
  Cc: Usama Arif, Pasha Tatashin, Mike Rapoport, Shuah Khan,
	Andrew Morton, linux-kernel, linux-kselftest, linux-mm

On Mon,  9 Mar 2026 11:54:34 +0000 Pratyush Yadav <pratyush@kernel.org> wrote:

> From: "Pratyush Yadav (Google)" <pratyush@kernel.org>
> 
> Currently memfd preservation using LUO is only tested indirectly via the
> luo_multi_session or luo_kexec_simple tests. Their main purpose is to
> test other live update functionality.
> 
> Add a framework for writing memfd tests. The framework hooks into the
> kselftest harness, but adds some things on top to make it suitable for
> live update.
> 
> The LUO FD (/dev/liveupdate) can only be opened by one process at a
> time. Each test runs in its own process. This means the LUO FD must be
> owned by the main process and shared to children. main() opens the LUO
> FD and shares it to child runners using a global variable.
> 
> Live update tests run in two stages. One before kexec and one after.
> Detect the stage using a special state session. If the session is
> present, it means the test is in post-kexec state.
> 
> Additionally, take in an optional --stage argument that lets callers
> specify expected stage. This is useful as a safety net to catch LUO core
> failures. If LUO core fails to preserve the state session properly, this
> option can help detect this and fail early. Since the option is not
> recognized by the kselftest harness, remove it from argv before calling
> test_harness_run().
> 
> Signed-off-by: Pratyush Yadav (Google) <pratyush@kernel.org>
> ---
>  tools/testing/selftests/liveupdate/Makefile   |  1 +
>  .../testing/selftests/liveupdate/luo_memfd.c  | 77 +++++++++++++++++++
>  2 files changed, 78 insertions(+)
>  create mode 100644 tools/testing/selftests/liveupdate/luo_memfd.c
> 
> diff --git a/tools/testing/selftests/liveupdate/Makefile b/tools/testing/selftests/liveupdate/Makefile
> index 080754787ede..051daae55eec 100644
> --- a/tools/testing/selftests/liveupdate/Makefile
> +++ b/tools/testing/selftests/liveupdate/Makefile
> @@ -6,6 +6,7 @@ TEST_GEN_PROGS += liveupdate
>  
>  TEST_GEN_PROGS_EXTENDED += luo_kexec_simple
>  TEST_GEN_PROGS_EXTENDED += luo_multi_session
> +TEST_GEN_PROGS_EXTENDED += luo_memfd
>  
>  TEST_FILES += do_kexec.sh
>  
> diff --git a/tools/testing/selftests/liveupdate/luo_memfd.c b/tools/testing/selftests/liveupdate/luo_memfd.c
> new file mode 100644
> index 000000000000..b779eee18387
> --- /dev/null
> +++ b/tools/testing/selftests/liveupdate/luo_memfd.c
> @@ -0,0 +1,77 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +/*
> + * Copyright (c) 2026, Google LLC.
> + * Pratyush Yadav (Google) <pratyush@kernel.org>
> + */
> +
> +/*
> + * Selftests for memfd preservation via LUO.
> + */
> +
> +#include <errno.h>
> +#include <fcntl.h>
> +#include <string.h>
> +#include <sys/ioctl.h>
> +#include <unistd.h>
> +
> +#include <linux/liveupdate.h>
> +
> +#include "../kselftest.h"
> +#include "../kselftest_harness.h"
> +
> +#include "luo_test_utils.h"
> +
> +#define STATE_SESSION_NAME "luo-state"
> +#define STATE_MEMFD_TOKEN 1
> +
> +#define LIVEUPDATE_DEV "/dev/liveupdate"

Hello!

LIVEUPDATE_DEV doesn't seem to be used anywhere?

> +static int luo_fd = -1, stage;
> +
> +int main(int argc, char *argv[])
> +{
> +	int session, expected_stage = 0;
> +
> +	/*
> +	 * The test takes an optional --stage argument. This lets callers
> +	 * provide the expected stage, and if that doesn't match the test errors
> +	 * out.
> +	 *
> +	 * Look for the stage. Since test_harness_run() doesn't recognize it,
> +	 * once found, remove it from argv.
> +	 */
> +	for (int i = 1; i < argc; i++) {
> +		if (strcmp(argv[i], "--stage") == 0) {
> +			if (i + 1 < argc) {
> +				expected_stage = atoi(argv[i + 1]);
> +				memmove(&argv[i], &argv[i + 2], (argc - i - 1) * sizeof(char *));
> +				argc -= 2;
> +				i--;
> +			} else {
> +				ksft_exit_fail_msg("Option --stage requires an argument\n");
> +			}
> +		}
> +	}
> +
> +	luo_fd = luo_open_device();
> +	if (luo_fd < 0)
> +		ksft_exit_skip("Failed to open %s (%s). Is the luo module loaded?\n",
> +			       strerror(errno), LUO_DEVICE);

Need to reverse strerror(errno) and LUO_DEVICE?

> +
> +	session = luo_retrieve_session(luo_fd, STATE_SESSION_NAME);
> +	if (session == -ENOENT)
> +		stage = 1;
> +	else if (session >= 0)
> +		stage = 2;
> +	else
> +		fail_exit("Failed to check for state session");
> +
> +	if (expected_stage && expected_stage != stage)
> +		ksft_exit_fail_msg("Stage mismatch: expected %d, got %d\n",
> +				   expected_stage, stage);
> +
> +	if (stage == 1)
> +		create_state_file(luo_fd, STATE_SESSION_NAME, STATE_MEMFD_TOKEN, 2);
> +
> +	test_harness_run(argc, argv);
> +}
> -- 
> 2.53.0.473.g4a7958ca14-goog
> 
> 


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 1/6] selftests/liveupdate: add framework for memfd tests
  2026-03-10 11:08   ` Usama Arif
@ 2026-03-13 10:05     ` Pratyush Yadav
  0 siblings, 0 replies; 17+ messages in thread
From: Pratyush Yadav @ 2026-03-13 10:05 UTC (permalink / raw)
  To: Usama Arif
  Cc: Pratyush Yadav, Pasha Tatashin, Mike Rapoport, Shuah Khan,
	Andrew Morton, linux-kernel, linux-kselftest, linux-mm

On Tue, Mar 10 2026, Usama Arif wrote:

> On Mon,  9 Mar 2026 11:54:34 +0000 Pratyush Yadav <pratyush@kernel.org> wrote:
[...]
>> diff --git a/tools/testing/selftests/liveupdate/luo_memfd.c b/tools/testing/selftests/liveupdate/luo_memfd.c
>> new file mode 100644
>> index 000000000000..b779eee18387
>> --- /dev/null
>> +++ b/tools/testing/selftests/liveupdate/luo_memfd.c
>> @@ -0,0 +1,77 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +
>> +/*
>> + * Copyright (c) 2026, Google LLC.
>> + * Pratyush Yadav (Google) <pratyush@kernel.org>
>> + */
>> +
>> +/*
>> + * Selftests for memfd preservation via LUO.
>> + */
>> +
>> +#include <errno.h>
>> +#include <fcntl.h>
>> +#include <string.h>
>> +#include <sys/ioctl.h>
>> +#include <unistd.h>
>> +
>> +#include <linux/liveupdate.h>
>> +
>> +#include "../kselftest.h"
>> +#include "../kselftest_harness.h"
>> +
>> +#include "luo_test_utils.h"
>> +
>> +#define STATE_SESSION_NAME "luo-state"
>> +#define STATE_MEMFD_TOKEN 1
>> +
>> +#define LIVEUPDATE_DEV "/dev/liveupdate"
>
> Hello!
>
> LIVEUPDATE_DEV doesn't seem to be used anywhere?

Right. This is a leftover from development. Will drop.

>
>> +static int luo_fd = -1, stage;
>> +
>> +int main(int argc, char *argv[])
>> +{
>> +	int session, expected_stage = 0;
>> +
>> +	/*
>> +	 * The test takes an optional --stage argument. This lets callers
>> +	 * provide the expected stage, and if that doesn't match the test errors
>> +	 * out.
>> +	 *
>> +	 * Look for the stage. Since test_harness_run() doesn't recognize it,
>> +	 * once found, remove it from argv.
>> +	 */
>> +	for (int i = 1; i < argc; i++) {
>> +		if (strcmp(argv[i], "--stage") == 0) {
>> +			if (i + 1 < argc) {
>> +				expected_stage = atoi(argv[i + 1]);
>> +				memmove(&argv[i], &argv[i + 2], (argc - i - 1) * sizeof(char *));
>> +				argc -= 2;
>> +				i--;
>> +			} else {
>> +				ksft_exit_fail_msg("Option --stage requires an argument\n");
>> +			}
>> +		}
>> +	}
>> +
>> +	luo_fd = luo_open_device();
>> +	if (luo_fd < 0)
>> +		ksft_exit_skip("Failed to open %s (%s). Is the luo module loaded?\n",
>> +			       strerror(errno), LUO_DEVICE);
>
> Need to reverse strerror(errno) and LUO_DEVICE?

Will fix. Thanks.

>
>> +
>> +	session = luo_retrieve_session(luo_fd, STATE_SESSION_NAME);
>> +	if (session == -ENOENT)
>> +		stage = 1;
>> +	else if (session >= 0)
>> +		stage = 2;
>> +	else
>> +		fail_exit("Failed to check for state session");
>> +
>> +	if (expected_stage && expected_stage != stage)
>> +		ksft_exit_fail_msg("Stage mismatch: expected %d, got %d\n",
>> +				   expected_stage, stage);
>> +
>> +	if (stage == 1)
>> +		create_state_file(luo_fd, STATE_SESSION_NAME, STATE_MEMFD_TOKEN, 2);
>> +
>> +	test_harness_run(argc, argv);
>> +}
>> -- 
>> 2.53.0.473.g4a7958ca14-goog
>> 
>> 

-- 
Regards,
Pratyush Yadav


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 2/6] selftests/liveupdate: add helper functions for memfd tests
  2026-03-09 11:54 ` [PATCH 2/6] selftests/liveupdate: add helper functions " Pratyush Yadav
@ 2026-03-17 11:01   ` Mike Rapoport
  2026-03-17 12:21     ` Pratyush Yadav
  2026-03-18  7:20   ` Mike Rapoport
  1 sibling, 1 reply; 17+ messages in thread
From: Mike Rapoport @ 2026-03-17 11:01 UTC (permalink / raw)
  To: Pratyush Yadav
  Cc: Pasha Tatashin, Shuah Khan, Andrew Morton, linux-kernel,
	linux-kselftest, linux-mm

On Mon, Mar 09, 2026 at 11:54:35AM +0000, Pratyush Yadav wrote:
> From: "Pratyush Yadav (Google)" <pratyush@kernel.org>
> 
> Add some helper functions that will be used by memfd tests. This moves
> some of the complexity out of the test itself, which results in better
> test readability and less code duplication.
> 
> Signed-off-by: Pratyush Yadav <ptyadav@amazon.de>
> Signed-off-by: Pratyush Yadav (Google) <pratyush@kernel.org>
> ---
>  .../selftests/liveupdate/luo_test_utils.c     | 175 +++++++++++++++++-
>  .../selftests/liveupdate/luo_test_utils.h     |   9 +
>  2 files changed, 183 insertions(+), 1 deletion(-)

Some review comments from an LLM that make sense to me as well :)
 
> diff --git a/tools/testing/selftests/liveupdate/luo_test_utils.c b/tools/testing/selftests/liveupdate/luo_test_utils.c
> --- a/tools/testing/selftests/liveupdate/luo_test_utils.c
> +++ b/tools/testing/selftests/liveupdate/luo_test_utils.c

[ ... ]

> +/* Read exactly specified size from fd. Any less results in error. */
> +int read_size(int fd, char *buffer, size_t size)
> +{
> +	size_t remain = size;
> +	ssize_t bytes_read;
> +
> +	while (remain) {
> +		bytes_read = read(fd, buffer, remain);
> +		if (bytes_read == 0)
> +			return -ENODATA;
> +		if (bytes_read < 0)
> +			return -errno;
> +
> +		remain -= bytes_read;
> +	}

Should the buffer pointer be advanced after each read()?  As written,
if read() returns a partial result, the next iteration reads into the
same position, overwriting the data just read.  Something like
buffer += bytes_read after remain -= bytes_read seems to be missing.

This is exercised by generate_random_data() which reads from
/dev/urandom, where partial reads are possible for large requests.

> +/* Write exactly specified size from fd. Any less results in error. */
> +int write_size(int fd, const char *buffer, size_t size)
> +{
> +	size_t remain = size;
> +	ssize_t written;
> +
> +	while (remain) {
> +		written = write(fd, buffer, remain);
> +		if (written == 0)
> +			return -EIO;
> +		if (written < 0)
> +			return -errno;
> +
> +		remain -= written;
> +	}

Same issue here: buffer is not advanced after each write(), so on a
partial write the same initial bytes would be re-sent instead of
continuing from where the previous write left off.

-- 
Sincerely yours,
Mike.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 2/6] selftests/liveupdate: add helper functions for memfd tests
  2026-03-17 11:01   ` Mike Rapoport
@ 2026-03-17 12:21     ` Pratyush Yadav
  0 siblings, 0 replies; 17+ messages in thread
From: Pratyush Yadav @ 2026-03-17 12:21 UTC (permalink / raw)
  To: Mike Rapoport
  Cc: Pratyush Yadav, Pasha Tatashin, Shuah Khan, Andrew Morton,
	linux-kernel, linux-kselftest, linux-mm

On Tue, Mar 17 2026, Mike Rapoport wrote:

> On Mon, Mar 09, 2026 at 11:54:35AM +0000, Pratyush Yadav wrote:
>> From: "Pratyush Yadav (Google)" <pratyush@kernel.org>
>> 
>> Add some helper functions that will be used by memfd tests. This moves
>> some of the complexity out of the test itself, which results in better
>> test readability and less code duplication.
>> 
>> Signed-off-by: Pratyush Yadav <ptyadav@amazon.de>
>> Signed-off-by: Pratyush Yadav (Google) <pratyush@kernel.org>
>> ---
>>  .../selftests/liveupdate/luo_test_utils.c     | 175 +++++++++++++++++-
>>  .../selftests/liveupdate/luo_test_utils.h     |   9 +
>>  2 files changed, 183 insertions(+), 1 deletion(-)
>
> Some review comments from an LLM that make sense to me as well :)
>  
>> diff --git a/tools/testing/selftests/liveupdate/luo_test_utils.c b/tools/testing/selftests/liveupdate/luo_test_utils.c
>> --- a/tools/testing/selftests/liveupdate/luo_test_utils.c
>> +++ b/tools/testing/selftests/liveupdate/luo_test_utils.c
>
> [ ... ]
>
>> +/* Read exactly specified size from fd. Any less results in error. */
>> +int read_size(int fd, char *buffer, size_t size)
>> +{
>> +	size_t remain = size;
>> +	ssize_t bytes_read;
>> +
>> +	while (remain) {
>> +		bytes_read = read(fd, buffer, remain);
>> +		if (bytes_read == 0)
>> +			return -ENODATA;
>> +		if (bytes_read < 0)
>> +			return -errno;
>> +
>> +		remain -= bytes_read;
>> +	}
>
> Should the buffer pointer be advanced after each read()?  As written,
> if read() returns a partial result, the next iteration reads into the
> same position, overwriting the data just read.  Something like
> buffer += bytes_read after remain -= bytes_read seems to be missing.
>
> This is exercised by generate_random_data() which reads from
> /dev/urandom, where partial reads are possible for large requests.
>
>> +/* Write exactly specified size from fd. Any less results in error. */
>> +int write_size(int fd, const char *buffer, size_t size)
>> +{
>> +	size_t remain = size;
>> +	ssize_t written;
>> +
>> +	while (remain) {
>> +		written = write(fd, buffer, remain);
>> +		if (written == 0)
>> +			return -EIO;
>> +		if (written < 0)
>> +			return -errno;
>> +
>> +		remain -= written;
>> +	}
>
> Same issue here: buffer is not advanced after each write(), so on a
> partial write the same initial bytes would be re-sent instead of
> continuing from where the previous write left off.

Yeah, good catch on both. Will fix.

-- 
Regards,
Pratyush Yadav


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 1/6] selftests/liveupdate: add framework for memfd tests
  2026-03-09 11:54 ` [PATCH 1/6] selftests/liveupdate: add framework for " Pratyush Yadav
  2026-03-10 11:08   ` Usama Arif
@ 2026-03-18  7:15   ` Mike Rapoport
  1 sibling, 0 replies; 17+ messages in thread
From: Mike Rapoport @ 2026-03-18  7:15 UTC (permalink / raw)
  To: Pratyush Yadav
  Cc: Pasha Tatashin, Shuah Khan, Andrew Morton, linux-kernel,
	linux-kselftest, linux-mm

On Mon, Mar 09, 2026 at 11:54:34AM +0000, Pratyush Yadav wrote:
> From: "Pratyush Yadav (Google)" <pratyush@kernel.org>
> 
> Currently memfd preservation using LUO is only tested indirectly via the
> luo_multi_session or luo_kexec_simple tests. Their main purpose is to
> test other live update functionality.
> 
> Add a framework for writing memfd tests. The framework hooks into the
> kselftest harness, but adds some things on top to make it suitable for
> live update.
> 
> The LUO FD (/dev/liveupdate) can only be opened by one process at a
> time. Each test runs in its own process. This means the LUO FD must be
> owned by the main process and shared to children. main() opens the LUO
> FD and shares it to child runners using a global variable.
> 
> Live update tests run in two stages. One before kexec and one after.
> Detect the stage using a special state session. If the session is
> present, it means the test is in post-kexec state.
> 
> Additionally, take in an optional --stage argument that lets callers
> specify expected stage. This is useful as a safety net to catch LUO core
> failures. If LUO core fails to preserve the state session properly, this
> option can help detect this and fail early. Since the option is not
> recognized by the kselftest harness, remove it from argv before calling
> test_harness_run().
> 
> Signed-off-by: Pratyush Yadav (Google) <pratyush@kernel.org>

Reviewed-by: Mike Rapoport (Microsoft) <rppt@kernel.org>

with a few nits below.

> ---
>  tools/testing/selftests/liveupdate/Makefile   |  1 +
>  .../testing/selftests/liveupdate/luo_memfd.c  | 77 +++++++++++++++++++
>  2 files changed, 78 insertions(+)
>  create mode 100644 tools/testing/selftests/liveupdate/luo_memfd.c
> 
> diff --git a/tools/testing/selftests/liveupdate/Makefile b/tools/testing/selftests/liveupdate/Makefile
> index 080754787ede..051daae55eec 100644
> --- a/tools/testing/selftests/liveupdate/Makefile
> +++ b/tools/testing/selftests/liveupdate/Makefile
> @@ -6,6 +6,7 @@ TEST_GEN_PROGS += liveupdate
>  
>  TEST_GEN_PROGS_EXTENDED += luo_kexec_simple
>  TEST_GEN_PROGS_EXTENDED += luo_multi_session
> +TEST_GEN_PROGS_EXTENDED += luo_memfd
>  
>  TEST_FILES += do_kexec.sh
>  
> diff --git a/tools/testing/selftests/liveupdate/luo_memfd.c b/tools/testing/selftests/liveupdate/luo_memfd.c
> new file mode 100644
> index 000000000000..b779eee18387
> --- /dev/null
> +++ b/tools/testing/selftests/liveupdate/luo_memfd.c
> @@ -0,0 +1,77 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +/*
> + * Copyright (c) 2026, Google LLC.
> + * Pratyush Yadav (Google) <pratyush@kernel.org>
> + */
> +
> +/*
> + * Selftests for memfd preservation via LUO.
> + */
> +
> +#include <errno.h>
> +#include <fcntl.h>
> +#include <string.h>
> +#include <sys/ioctl.h>
> +#include <unistd.h>
> +
> +#include <linux/liveupdate.h>
> +
> +#include "../kselftest.h"
> +#include "../kselftest_harness.h"
> +
> +#include "luo_test_utils.h"
> +
> +#define STATE_SESSION_NAME "luo-state"
> +#define STATE_MEMFD_TOKEN 1
> +
> +#define LIVEUPDATE_DEV "/dev/liveupdate"
> +static int luo_fd = -1, stage;

Nit: declaring stage on a separate line is a bit clearer.

> +
> +int main(int argc, char *argv[])
> +{
> +	int session, expected_stage = 0;

Ditto.

> +
> +	/*
> +	 * The test takes an optional --stage argument. This lets callers
> +	 * provide the expected stage, and if that doesn't match the test errors
> +	 * out.
> +	 *
> +	 * Look for the stage. Since test_harness_run() doesn't recognize it,
> +	 * once found, remove it from argv.
> +	 */
> +	for (int i = 1; i < argc; i++) {
> +		if (strcmp(argv[i], "--stage") == 0) {
> +			if (i + 1 < argc) {
> +				expected_stage = atoi(argv[i + 1]);
> +				memmove(&argv[i], &argv[i + 2], (argc - i - 1) * sizeof(char *));
> +				argc -= 2;
> +				i--;
> +			} else {
> +				ksft_exit_fail_msg("Option --stage requires an argument\n");
> +			}
> +		}
> +	}
> +
> +	luo_fd = luo_open_device();
> +	if (luo_fd < 0)
> +		ksft_exit_skip("Failed to open %s (%s). Is the luo module loaded?\n",

LUO can't be a module :) Maybe

"Is LUO enabled in the kernel?"


> +			       strerror(errno), LUO_DEVICE);
> +
> +	session = luo_retrieve_session(luo_fd, STATE_SESSION_NAME);
> +	if (session == -ENOENT)
> +		stage = 1;
> +	else if (session >= 0)
> +		stage = 2;
> +	else
> +		fail_exit("Failed to check for state session");

There is ksft_exit_fail_perror(), would be more consistent with other exit
paths.

> +
> +	if (expected_stage && expected_stage != stage)
> +		ksft_exit_fail_msg("Stage mismatch: expected %d, got %d\n",
> +				   expected_stage, stage);
> +
> +	if (stage == 1)
> +		create_state_file(luo_fd, STATE_SESSION_NAME, STATE_MEMFD_TOKEN, 2);
> +
> +	test_harness_run(argc, argv);
> +}
> -- 
> 2.53.0.473.g4a7958ca14-goog
> 

-- 
Sincerely yours,
Mike.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 2/6] selftests/liveupdate: add helper functions for memfd tests
  2026-03-09 11:54 ` [PATCH 2/6] selftests/liveupdate: add helper functions " Pratyush Yadav
  2026-03-17 11:01   ` Mike Rapoport
@ 2026-03-18  7:20   ` Mike Rapoport
  1 sibling, 0 replies; 17+ messages in thread
From: Mike Rapoport @ 2026-03-18  7:20 UTC (permalink / raw)
  To: Pratyush Yadav
  Cc: Pasha Tatashin, Shuah Khan, Andrew Morton, linux-kernel,
	linux-kselftest, linux-mm

On Mon, Mar 09, 2026 at 11:54:35AM +0000, Pratyush Yadav wrote:
> From: "Pratyush Yadav (Google)" <pratyush@kernel.org>
> 
> Add some helper functions that will be used by memfd tests. This moves
> some of the complexity out of the test itself, which results in better
> test readability and less code duplication.
> 
> Signed-off-by: Pratyush Yadav <ptyadav@amazon.de>
> Signed-off-by: Pratyush Yadav (Google) <pratyush@kernel.org>
> ---
>  .../selftests/liveupdate/luo_test_utils.c     | 175 +++++++++++++++++-
>  .../selftests/liveupdate/luo_test_utils.h     |   9 +
>  2 files changed, 183 insertions(+), 1 deletion(-)
> 
> diff --git a/tools/testing/selftests/liveupdate/luo_test_utils.c b/tools/testing/selftests/liveupdate/luo_test_utils.c
> index 3c8721c505df..45ace3697ee6 100644

...

> +/*
> + * Make sure fd contains expected data up to size. Returns 0 on success, 1 on
> + * data mismatch, -errno on error.
> + */
> +int verify_fd_content(int fd, const char *expected_data, size_t size)

Maybe verify_fd_content_read() to match _mmap()?

WIth this and write_size() and read_size() fixed

Reviewed-by: Mike Rapoport (Microsoft) <rppt@kernel.org>

-- 
Sincerely yours,
Mike.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 3/6] selftests/liveupdate: add test for memfd content preservation
  2026-03-09 11:54 ` [PATCH 3/6] selftests/liveupdate: add test for memfd content preservation Pratyush Yadav
@ 2026-03-18  7:31   ` Mike Rapoport
  0 siblings, 0 replies; 17+ messages in thread
From: Mike Rapoport @ 2026-03-18  7:31 UTC (permalink / raw)
  To: Pratyush Yadav
  Cc: Pasha Tatashin, Shuah Khan, Andrew Morton, linux-kernel,
	linux-kselftest, linux-mm

On Mon, Mar 09, 2026 at 11:54:36AM +0000, Pratyush Yadav wrote:
> From: "Pratyush Yadav (Google)" <pratyush@kernel.org>
> 
> Add a selftest that makes sure the contents of a memfd are correctly
> preserved across a live update. In stage 1, create a memfd and fill it
> with random data, and preserve it. Save the random data to the file
> system. This will be used by stage 2 to verify the contents are correct.

There's a small caveat here, as some CI systems put selftests in tmpfs, so
creating a file there won't really help.
I think there should be a skip if the test runs of tmpfs. 
 
> In stage 2, retrieve the memfd and compare its contents with the
> contents saved on the file system.
> 
> Signed-off-by: Pratyush Yadav <ptyadav@amazon.de>
> Signed-off-by: Pratyush Yadav (Google) <pratyush@kernel.org>
> ---
>  tools/testing/selftests/liveupdate/Makefile   |  1 +
>  .../testing/selftests/liveupdate/luo_memfd.c  | 61 +++++++++++++++++++
>  2 files changed, 62 insertions(+)
> 
> diff --git a/tools/testing/selftests/liveupdate/Makefile b/tools/testing/selftests/liveupdate/Makefile
> index 051daae55eec..8e2eb6500c07 100644
> --- a/tools/testing/selftests/liveupdate/Makefile
> +++ b/tools/testing/selftests/liveupdate/Makefile
> @@ -13,6 +13,7 @@ TEST_FILES += do_kexec.sh
>  include ../lib.mk
>  
>  CFLAGS += $(KHDR_INCLUDES)
> +CFLAGS += -I$(top_srcdir)/tools/include
>  CFLAGS += -Wall -O2 -Wno-unused-function
>  CFLAGS += -MD
>  
> diff --git a/tools/testing/selftests/liveupdate/luo_memfd.c b/tools/testing/selftests/liveupdate/luo_memfd.c
> index b779eee18387..52b5f6b16e19 100644
> --- a/tools/testing/selftests/liveupdate/luo_memfd.c
> +++ b/tools/testing/selftests/liveupdate/luo_memfd.c
> @@ -3,6 +3,9 @@
>  /*
>   * Copyright (c) 2026, Google LLC.
>   * Pratyush Yadav (Google) <pratyush@kernel.org>
> + *
> + * Copyright (C) 2025 Amazon.com Inc. or its affiliates.
> + * Pratyush Yadav <ptyadav@amazon.de>
>   */
>  
>  /*
> @@ -11,11 +14,14 @@
>  
>  #include <errno.h>
>  #include <fcntl.h>
> +#include <stdlib.h>
>  #include <string.h>
>  #include <sys/ioctl.h>
> +#include <sys/mman.h>
>  #include <unistd.h>
>  
>  #include <linux/liveupdate.h>
> +#include <linux/sizes.h>
>  
>  #include "../kselftest.h"
>  #include "../kselftest_harness.h"
> @@ -25,9 +31,64 @@
>  #define STATE_SESSION_NAME "luo-state"
>  #define STATE_MEMFD_TOKEN 1
>  
> +#define MEMFD_DATA_SESSION_NAME "memfd_data_session"
> +#define MEMFD_DATA_TOKEN 1
> +#define MEMFD_DATA_BUFFER_SIZE SZ_1M
> +#define RANDOM_DATA_FILE "luo_random_data.bin"

Reads to me like a random file containing data :)
Something like FILESYSTEM_DATA_COPY would better express the meaning.

> +
>  #define LIVEUPDATE_DEV "/dev/liveupdate"
>  static int luo_fd = -1, stage;
>  
> +/*
> + * Test that a memfd with its data is preserved across live update.
> + */
> +TEST(memfd_data)
> +{
> +	int fd, session;
> +	char *buffer;
> +	struct liveupdate_session_preserve_fd preserve_arg = { .size = sizeof(preserve_arg) };
> +	struct liveupdate_session_retrieve_fd retrieve_arg = { .size = sizeof(retrieve_arg) };
> +
> +	buffer = malloc(MEMFD_DATA_BUFFER_SIZE);
> +	ASSERT_NE(buffer, NULL);
> +
> +	switch (stage) {
> +	case 1:

Can we please move each state to a helper function?

> +		session = luo_create_session(luo_fd, MEMFD_DATA_SESSION_NAME);
> +		ASSERT_GE(session, 0);
> +
> +		fd = create_random_memfd("memfd_data", buffer, MEMFD_DATA_BUFFER_SIZE);
> +		ASSERT_GE(fd, 0);
> +
> +		ASSERT_EQ(save_test_data(RANDOM_DATA_FILE, buffer, MEMFD_DATA_BUFFER_SIZE), 0);
> +
> +		preserve_arg.fd = fd;
> +		preserve_arg.token = MEMFD_DATA_TOKEN;
> +		ASSERT_GE(ioctl(session, LIVEUPDATE_SESSION_PRESERVE_FD, &preserve_arg), 0);
> +
> +		daemonize_and_wait();
> +		break;
> +	case 2:
> +		session = luo_retrieve_session(luo_fd, MEMFD_DATA_SESSION_NAME);
> +		ASSERT_GE(session, 0);
> +
> +		ASSERT_EQ(load_test_data(RANDOM_DATA_FILE, buffer, MEMFD_DATA_BUFFER_SIZE), 0);
> +
> +		retrieve_arg.token = MEMFD_DATA_TOKEN;
> +		ASSERT_GE(ioctl(session, LIVEUPDATE_SESSION_RETRIEVE_FD, &retrieve_arg), 0);
> +		fd = retrieve_arg.fd;
> +		ASSERT_GE(fd, 0);
> +
> +		ASSERT_EQ(verify_fd_content(fd, buffer, MEMFD_DATA_BUFFER_SIZE), 0);
> +
> +		ASSERT_EQ(luo_session_finish(session), 0);
> +		break;


> +	default:
> +		TH_LOG("Unknown stage %d\n", stage);
> +		ASSERT_FALSE(true);
> +	}
> +}
> +
>  int main(int argc, char *argv[])
>  {
>  	int session, expected_stage = 0;
> -- 
> 2.53.0.473.g4a7958ca14-goog
> 

-- 
Sincerely yours,
Mike.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 4/6] selftests/liveupdate: add test for zero-size memfd preservation
  2026-03-09 11:54 ` [PATCH 4/6] selftests/liveupdate: add test for zero-size memfd preservation Pratyush Yadav
@ 2026-03-18  7:35   ` Mike Rapoport
  0 siblings, 0 replies; 17+ messages in thread
From: Mike Rapoport @ 2026-03-18  7:35 UTC (permalink / raw)
  To: Pratyush Yadav
  Cc: Pasha Tatashin, Shuah Khan, Andrew Morton, linux-kernel,
	linux-kselftest, linux-mm

On Mon, Mar 09, 2026 at 11:54:37AM +0000, Pratyush Yadav wrote:
> From: "Pratyush Yadav (Google)" <pratyush@kernel.org>
> 
> A zero-size memfd is a special case of memfd preservation. It takes a
> different path from normal both during preservation and during restore.
> In the serialization structure, the number of folios if zero and the

                                                       ^ typo: is

> vmalloc array with folios is empty. The restore logic should check for
> this and make sure to not touch the invalid array.
> 
> Add a test to make sure this path works as expected. In stage 1, the
> test creates and preserves a memfd without any data. In stage 2, the
> test retrieves the memfd and makes sure it is still without data.
> 
> Signed-off-by: Pratyush Yadav (Google) <pratyush@kernel.org>
> ---
>  .../testing/selftests/liveupdate/luo_memfd.c  | 47 +++++++++++++++++++
>  1 file changed, 47 insertions(+)
> 
> diff --git a/tools/testing/selftests/liveupdate/luo_memfd.c b/tools/testing/selftests/liveupdate/luo_memfd.c
> index 52b5f6b16e19..56106cd09978 100644
> --- a/tools/testing/selftests/liveupdate/luo_memfd.c
> +++ b/tools/testing/selftests/liveupdate/luo_memfd.c
> @@ -36,6 +36,9 @@
>  #define MEMFD_DATA_BUFFER_SIZE SZ_1M
>  #define RANDOM_DATA_FILE "luo_random_data.bin"
>  
> +#define ZERO_SESSION_NAME "zero_session"
> +#define ZERO_MEMFD_TOKEN 1
> +
>  #define LIVEUPDATE_DEV "/dev/liveupdate"
>  static int luo_fd = -1, stage;
>  
> @@ -89,6 +92,50 @@ TEST(memfd_data)
>  	}
>  }
>  
> +/*
> + * Test that a zero-sized memfd is preserved across live update.
> + */
> +TEST(zero_memfd)
> +{
> +	int zero_fd, session;
> +	struct liveupdate_session_preserve_fd preserve_arg = { .size = sizeof(preserve_arg) };
> +	struct liveupdate_session_retrieve_fd retrieve_arg = { .size = sizeof(retrieve_arg) };
> +
> +	switch (stage) {
> +	case 1:

Helper functions?  And in other tests that do save and restore too?

Otherwise

Reviewed-by: Mike Rapoport (Microsoft) <rppt@kernel.org>


> +		session = luo_create_session(luo_fd, ZERO_SESSION_NAME);
> +		ASSERT_GE(session, 0);
> +

-- 
Sincerely yours,
Mike.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 5/6] selftests/liveupdate: add test for operations on a preserved memfd
  2026-03-09 11:54 ` [PATCH 5/6] selftests/liveupdate: add test for operations on a preserved memfd Pratyush Yadav
@ 2026-03-18  7:38   ` Mike Rapoport
  0 siblings, 0 replies; 17+ messages in thread
From: Mike Rapoport @ 2026-03-18  7:38 UTC (permalink / raw)
  To: Pratyush Yadav
  Cc: Pasha Tatashin, Shuah Khan, Andrew Morton, linux-kernel,
	linux-kselftest, linux-mm

On Mon, Mar 09, 2026 at 11:54:38AM +0000, Pratyush Yadav wrote:
> From: "Pratyush Yadav (Google)" <pratyush@kernel.org>
> 
> Once a memfd is preserved, certain operations are not allowed to
> succeed since they might make the state of the memfd inconsistent with
> the serialized state. Among these operations are truncating or growing
> the memfd. Writes and reads to already existing memfd should succeed.
> 
> Add a test that makes sure a preserved memfd does not allow growing or
> shrinking, but does allow reads and writes to existing memory to go
> thorough.
> 
> Signed-off-by: Pratyush Yadav <ptyadav@amazon.de>
> Signed-off-by: Pratyush Yadav (Google) <pratyush@kernel.org>

Reviewed-by: Mike Rapoport (Microsoft) <rppt@kernel.org>

-- 
Sincerely yours,
Mike.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 6/6] selftests/liveupdate: add fallocate test for memfd
  2026-03-09 11:54 ` [PATCH 6/6] selftests/liveupdate: add fallocate test for memfd Pratyush Yadav
@ 2026-03-18  7:43   ` Mike Rapoport
  0 siblings, 0 replies; 17+ messages in thread
From: Mike Rapoport @ 2026-03-18  7:43 UTC (permalink / raw)
  To: Pratyush Yadav
  Cc: Pasha Tatashin, Shuah Khan, Andrew Morton, linux-kernel,
	linux-kselftest, linux-mm

On Mon, Mar 09, 2026 at 11:54:39AM +0000, Pratyush Yadav wrote:
> From: "Pratyush Yadav (Google)" <pratyush@kernel.org>
> 
> When memory is added to a memfd via fallocate(), it does not get zeroed
> immediately. This is tracked by the absence of the uptodate folio flag.
> Initially, memfd preservation simply saved the folio flags at preserve
> time. This led to a bug, where all writes to un-initialized fallocated
> memory after preserve were lost after live update. This is fixed by
> patch [0] (not in mainline as of writing this).
> 
> Add a test that fallocates some memory in a memfd, preserves it, writes
> to it. Then in stage 2 it verifies the written content is still present.
> 
> [0] https://lore.kernel.org/linux-mm/20260223173931.2221759-2-pratyush@kernel.org/

Looks like it's already in mm-stable, so it's sha should be stable already.
 
> Signed-off-by: Pratyush Yadav (Google) <pratyush@kernel.org>
> ---
>  .../testing/selftests/liveupdate/luo_memfd.c  | 64 +++++++++++++++++++
>  1 file changed, 64 insertions(+)
> 
> diff --git a/tools/testing/selftests/liveupdate/luo_memfd.c b/tools/testing/selftests/liveupdate/luo_memfd.c
> index 75f88101e7b5..dde3c78db50e 100644
> --- a/tools/testing/selftests/liveupdate/luo_memfd.c
> +++ b/tools/testing/selftests/liveupdate/luo_memfd.c
> @@ -43,6 +43,11 @@
>  #define PRESERVED_MEMFD_TOKEN 1
>  #define PRESERVED_BUFFER_SIZE SZ_1M
>  
> +#define FALLOCATE_SESSION_NAME "fallocate_session"
> +#define FALLOCATE_MEMFD_TOKEN 1
> +#define FALLOCATE_BUFFER_SIZE SZ_1M
> +#define RANDOM_DATA_FILE_FALLOCATE "luo_random_data_fallocate.bin"

FILESYSTEM_COPY_ or something like that?

> +
>  #define LIVEUPDATE_DEV "/dev/liveupdate"
>  static int luo_fd = -1, stage;
>  
> @@ -193,6 +198,65 @@ TEST(preserved_ops)
>  	ASSERT_EQ(lseek(fd, 0, SEEK_END), PRESERVED_BUFFER_SIZE);
>  }
>  
> +/*
> + * Test that an fallocated memfd is preserved across live update and can be
> + * written to after being preserved.
> + */
> +TEST(fallocate_memfd)
> +{
> +	int fd, session;
> +	char *buffer;
> +	struct liveupdate_session_preserve_fd preserve_arg = { .size = sizeof(preserve_arg) };
> +	struct liveupdate_session_retrieve_fd retrieve_arg = { .size = sizeof(retrieve_arg) };
> +
> +	buffer = malloc(FALLOCATE_BUFFER_SIZE);
> +	ASSERT_NE(buffer, NULL);
> +
> +	switch (stage) {
> +	case 1:

Functions again :)

Reviewed-by: Mike Rapoport (Microsoft) <rppt@kernel.org>

-- 
Sincerely yours,
Mike.


^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2026-03-18  7:43 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-09 11:54 [PATCH 0/6] selftests/liveupdate: add memfd tests Pratyush Yadav
2026-03-09 11:54 ` [PATCH 1/6] selftests/liveupdate: add framework for " Pratyush Yadav
2026-03-10 11:08   ` Usama Arif
2026-03-13 10:05     ` Pratyush Yadav
2026-03-18  7:15   ` Mike Rapoport
2026-03-09 11:54 ` [PATCH 2/6] selftests/liveupdate: add helper functions " Pratyush Yadav
2026-03-17 11:01   ` Mike Rapoport
2026-03-17 12:21     ` Pratyush Yadav
2026-03-18  7:20   ` Mike Rapoport
2026-03-09 11:54 ` [PATCH 3/6] selftests/liveupdate: add test for memfd content preservation Pratyush Yadav
2026-03-18  7:31   ` Mike Rapoport
2026-03-09 11:54 ` [PATCH 4/6] selftests/liveupdate: add test for zero-size memfd preservation Pratyush Yadav
2026-03-18  7:35   ` Mike Rapoport
2026-03-09 11:54 ` [PATCH 5/6] selftests/liveupdate: add test for operations on a preserved memfd Pratyush Yadav
2026-03-18  7:38   ` Mike Rapoport
2026-03-09 11:54 ` [PATCH 6/6] selftests/liveupdate: add fallocate test for memfd Pratyush Yadav
2026-03-18  7:43   ` Mike Rapoport

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox