* [PATCH V2 1/8] mshare: Add selftests
2025-09-19 13:06 [PATCH V2 0/8] Add selftests for mshare Yongting Lin
@ 2025-09-19 13:06 ` Yongting Lin
2025-09-19 13:06 ` [PATCH V2 2/8] mshare: selftests: Adding config fragments Yongting Lin
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Yongting Lin @ 2025-09-19 13:06 UTC (permalink / raw)
To: anthony.yznaga, khalid, shuah
Cc: linux-kernel, linux-kselftest, akpm, linux-mm, libo.gcs85, Yongting Lin
This patch setup the selftests project for mshare and add a
'hello world' to project.
Signed-off-by: Yongting Lin <linyongting@bytedance.com>
---
tools/testing/selftests/mshare/.gitignore | 3 +++
tools/testing/selftests/mshare/Makefile | 7 +++++++
tools/testing/selftests/mshare/basic.c | 10 ++++++++++
3 files changed, 20 insertions(+)
create mode 100644 tools/testing/selftests/mshare/.gitignore
create mode 100644 tools/testing/selftests/mshare/Makefile
create mode 100644 tools/testing/selftests/mshare/basic.c
diff --git a/tools/testing/selftests/mshare/.gitignore b/tools/testing/selftests/mshare/.gitignore
new file mode 100644
index 000000000000..406f31bd432c
--- /dev/null
+++ b/tools/testing/selftests/mshare/.gitignore
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+basic
diff --git a/tools/testing/selftests/mshare/Makefile b/tools/testing/selftests/mshare/Makefile
new file mode 100644
index 000000000000..651658d091c5
--- /dev/null
+++ b/tools/testing/selftests/mshare/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0
+
+CFLAGS = $(KHDR_INCLUDES) -Wall -g -O2
+
+TEST_GEN_PROGS := basic
+
+include ../lib.mk
diff --git a/tools/testing/selftests/mshare/basic.c b/tools/testing/selftests/mshare/basic.c
new file mode 100644
index 000000000000..482af948878d
--- /dev/null
+++ b/tools/testing/selftests/mshare/basic.c
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include "../kselftest_harness.h"
+
+TEST(basic)
+{
+ printf("Hello mshare\n");
+}
+
+TEST_HARNESS_MAIN
--
2.20.1
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH V2 2/8] mshare: selftests: Adding config fragments
2025-09-19 13:06 [PATCH V2 0/8] Add selftests for mshare Yongting Lin
2025-09-19 13:06 ` [PATCH V2 1/8] mshare: Add selftests Yongting Lin
@ 2025-09-19 13:06 ` Yongting Lin
2025-09-19 13:06 ` [PATCH V2 4/8] mshare: selftests: Add test case shared memory Yongting Lin
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Yongting Lin @ 2025-09-19 13:06 UTC (permalink / raw)
To: anthony.yznaga, khalid, shuah
Cc: linux-kernel, linux-kselftest, akpm, linux-mm, libo.gcs85, Yongting Lin
mshare test cases need pre-required kernel configs for the test
to get pass.
Signed-off-by: Yongting Lin <linyongting@bytedance.com>
---
tools/testing/selftests/mshare/config | 1 +
1 file changed, 1 insertion(+)
create mode 100644 tools/testing/selftests/mshare/config
diff --git a/tools/testing/selftests/mshare/config b/tools/testing/selftests/mshare/config
new file mode 100644
index 000000000000..16fd9a3ca12a
--- /dev/null
+++ b/tools/testing/selftests/mshare/config
@@ -0,0 +1 @@
+CONFIG_MSHARE=y
--
2.20.1
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH V2 4/8] mshare: selftests: Add test case shared memory
2025-09-19 13:06 [PATCH V2 0/8] Add selftests for mshare Yongting Lin
2025-09-19 13:06 ` [PATCH V2 1/8] mshare: Add selftests Yongting Lin
2025-09-19 13:06 ` [PATCH V2 2/8] mshare: selftests: Adding config fragments Yongting Lin
@ 2025-09-19 13:06 ` Yongting Lin
2025-09-19 13:06 ` [PATCH V2 5/8] mshare: selftests: Add test case ioctl unmap Yongting Lin
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Yongting Lin @ 2025-09-19 13:06 UTC (permalink / raw)
To: anthony.yznaga, khalid, shuah
Cc: linux-kernel, linux-kselftest, akpm, linux-mm, libo.gcs85, Yongting Lin
This test case aims to verify the basic functionalities of mshare.
Create a mshare file and use ioctl to create mapping for host mm
with supportive flags, then create processes to map mshare file
to their memory space, and eventually verify the correctiness
of sharing memory.
To ensure these tests can run on any server or device with minimal memory
usage, we follow the steps below:
1. The ftruncate size must be a multiple of the alignment size.
2. In the ioctl(MSHAREFS_CREATE_MAPPING) syscall, which determines the
memory size occupied by an mshare instance, we use 4K/8K for normal
pages and 2M/4M for hugetlb pages.
3. The size used in the mmap syscall must match the ftruncate size.
Signed-off-by: Yongting Lin <linyongting@bytedance.com>
---
tools/testing/selftests/mshare/basic.c | 82 +++++++++++++++++++++++++-
1 file changed, 80 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/mshare/basic.c b/tools/testing/selftests/mshare/basic.c
index 35739b1133f7..54a132a8116c 100644
--- a/tools/testing/selftests/mshare/basic.c
+++ b/tools/testing/selftests/mshare/basic.c
@@ -3,9 +3,87 @@
#include "../kselftest_harness.h"
#include "util.c"
-TEST(basic)
+#define STRING "I am Msharefs"
+
+FIXTURE(basic)
+{
+ char filename[128];
+ size_t align_size;
+};
+
+FIXTURE_VARIANT(basic) {
+ size_t allocate_size;
+ /* flags for ioctl */
+ int map_flags;
+};
+
+FIXTURE_VARIANT_ADD(basic, ANON_4k) {
+ .allocate_size = KB(4),
+ .map_flags = MAP_ANONYMOUS | MAP_SHARED | MAP_FIXED,
+};
+
+FIXTURE_VARIANT_ADD(basic, HUGETLB_2m) {
+ .allocate_size = MB(2),
+ .map_flags = MAP_ANONYMOUS | MAP_HUGETLB | MAP_SHARED | MAP_FIXED,
+};
+
+FIXTURE_VARIANT_ADD(basic, ANON_8k) {
+ .allocate_size = KB(8),
+ .map_flags = MAP_ANONYMOUS | MAP_SHARED | MAP_FIXED,
+};
+
+FIXTURE_VARIANT_ADD(basic, HUGETLB_4m) {
+ .allocate_size = MB(4),
+ .map_flags = MAP_ANONYMOUS | MAP_HUGETLB | MAP_SHARED | MAP_FIXED,
+};
+
+FIXTURE_SETUP(basic)
+{
+ int fd;
+
+ self->align_size = mshare_get_info();
+
+ fd = create_mshare_file(self->filename, sizeof(self->filename));
+ ftruncate(fd, self->align_size);
+
+ if (variant->map_flags & MAP_HUGETLB)
+ ksft_print_msg("Tip: Please enable hugepages before running this test.\n"
+ "For example: sysctl -w vm.nr_hugepages=2\n");
+
+ ASSERT_EQ(mshare_ioctl_mapping(fd, variant->allocate_size, variant->map_flags), 0);
+ close(fd);
+}
+
+FIXTURE_TEARDOWN(basic)
+{
+ ASSERT_EQ(unlink(self->filename), 0);
+}
+
+TEST_F(basic, shared_mem)
{
- printf("Hello mshare\n");
+ int fd;
+ void *addr;
+ pid_t pid = fork();
+
+ ASSERT_NE(pid, -1);
+
+ fd = open(self->filename, O_RDWR, 0600);
+ ASSERT_NE(fd, -1);
+
+ addr = mmap(NULL, self->align_size, PROT_READ | PROT_WRITE,
+ MAP_SHARED, fd, 0);
+ ASSERT_NE(addr, MAP_FAILED);
+
+ if (pid == 0) {
+ /* Child process write date the shared memory */
+ memcpy(addr, STRING, sizeof(STRING));
+ exit(0);
+ }
+
+ ASSERT_NE(waitpid(pid, NULL, 0), -1);
+
+ /* Parent process should retrieve the data from the shared memory */
+ ASSERT_EQ(memcmp(addr, STRING, sizeof(STRING)), 0);
}
TEST_HARNESS_MAIN
--
2.20.1
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH V2 5/8] mshare: selftests: Add test case ioctl unmap
2025-09-19 13:06 [PATCH V2 0/8] Add selftests for mshare Yongting Lin
` (2 preceding siblings ...)
2025-09-19 13:06 ` [PATCH V2 4/8] mshare: selftests: Add test case shared memory Yongting Lin
@ 2025-09-19 13:06 ` Yongting Lin
2025-09-19 13:06 ` [PATCH V2 6/8] mshare: selftests: Add some helper functions for configuring and retrieving cgroup Yongting Lin
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Yongting Lin @ 2025-09-19 13:06 UTC (permalink / raw)
To: anthony.yznaga, khalid, shuah
Cc: linux-kernel, linux-kselftest, akpm, linux-mm, libo.gcs85, Yongting Lin
This test case aims to verify whether the guest VMA will vanish
when corresponding VMA of host mm got ioctl unmap.
Signed-off-by: Yongting Lin <linyongting@bytedance.com>
---
tools/testing/selftests/mshare/basic.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/tools/testing/selftests/mshare/basic.c b/tools/testing/selftests/mshare/basic.c
index 54a132a8116c..043d1f3e1e3e 100644
--- a/tools/testing/selftests/mshare/basic.c
+++ b/tools/testing/selftests/mshare/basic.c
@@ -86,4 +86,24 @@ TEST_F(basic, shared_mem)
ASSERT_EQ(memcmp(addr, STRING, sizeof(STRING)), 0);
}
+TEST_F_SIGNAL(basic, ioctl_unmap, SIGSEGV)
+{
+ char *addr;
+ int fd;
+
+ fd = open(self->filename, O_RDWR, 0600);
+ addr = mmap(NULL, self->align_size, PROT_READ | PROT_WRITE,
+ MAP_SHARED, fd, 0);
+ ASSERT_NE(addr, MAP_FAILED);
+ addr[0] = 'M';
+
+ /* munmap vma for host mm */
+ mshare_ioctl_munmap(fd, variant->allocate_size);
+ /*
+ * Will generate SIGSEGV signal as ioctl has already cleaned
+ * shared page table
+ */
+ addr[0] = 'D';
+}
+
TEST_HARNESS_MAIN
--
2.20.1
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH V2 6/8] mshare: selftests: Add some helper functions for configuring and retrieving cgroup
2025-09-19 13:06 [PATCH V2 0/8] Add selftests for mshare Yongting Lin
` (3 preceding siblings ...)
2025-09-19 13:06 ` [PATCH V2 5/8] mshare: selftests: Add test case ioctl unmap Yongting Lin
@ 2025-09-19 13:06 ` Yongting Lin
2025-09-19 13:06 ` [PATCH V2 7/8] mshare: selftests: Add test case to demostrate the swapping of mshare memory Yongting Lin
2025-09-19 13:06 ` [PATCH V2 8/8] mshare: selftests: Add test case to demostrate that mshare partly supports THP Yongting Lin
6 siblings, 0 replies; 8+ messages in thread
From: Yongting Lin @ 2025-09-19 13:06 UTC (permalink / raw)
To: anthony.yznaga, khalid, shuah
Cc: linux-kernel, linux-kselftest, akpm, linux-mm, libo.gcs85, Yongting Lin
Before verify some complicated memory functionalities such as swap memory
and THP, we need add some helper functions to configure and retrieve cgroups
(specifically, memcg).
These helper functions consist:
Create and destroy individual cgroup for test cases
attach and dettach the test process to specified cgroup
Read swap size and thp size from testing cgroup
Signed-off-by: Yongting Lin <linyongting@bytedance.com>
---
tools/testing/selftests/mshare/util.c | 128 ++++++++++++++++++++++++++
1 file changed, 128 insertions(+)
diff --git a/tools/testing/selftests/mshare/util.c b/tools/testing/selftests/mshare/util.c
index a3c3896bd507..f1db4eb3cd8f 100644
--- a/tools/testing/selftests/mshare/util.c
+++ b/tools/testing/selftests/mshare/util.c
@@ -124,3 +124,131 @@ int mshare_ioctl_munmap(int fd, size_t size)
return ioctl(fd, MSHAREFS_UNMAP, &munmap);
}
+
+/*
+ * Helper functions for cgroup
+ */
+
+#define CGROUP_BASE "/sys/fs/cgroup/"
+#define CGROUP_TEST "mshare-test-XXXXXX"
+
+bool is_cgroup_v2;
+
+__attribute__((constructor))
+void get_cgroup_version(void)
+{
+ if (access(CGROUP_BASE "cgroup.controllers", F_OK) == 0)
+ is_cgroup_v2 = true;
+}
+
+int create_mshare_test_cgroup(char *cgroup, size_t len)
+{
+ if (is_cgroup_v2)
+ snprintf(cgroup, len, "%s/%s", CGROUP_BASE, CGROUP_TEST);
+ else
+ snprintf(cgroup, len, "%s/memory/%s", CGROUP_BASE, CGROUP_TEST);
+
+ char *path = mkdtemp(cgroup);
+
+ if (!path) {
+ perror("mkdtemp");
+ return -1;
+ }
+
+ return 0;
+}
+
+int remove_cgroup(char *cgroup)
+{
+ return rmdir(cgroup);
+}
+
+int write_data_to_cgroup(char *cgroup, char *file, char *data)
+{
+ char filename[128];
+ int fd;
+ int ret;
+
+ snprintf(filename, sizeof(filename), "%s/%s", cgroup, file);
+ fd = open(filename, O_RDWR);
+
+ if (fd == -1)
+ return -1;
+
+ ret = write(fd, data, strlen(data));
+ close(fd);
+
+ return ret;
+}
+
+int attach_to_cgroup(char *cgroup)
+{
+ char pid_str[32];
+
+ snprintf(pid_str, sizeof(pid_str), "%d", getpid());
+ return write_data_to_cgroup(cgroup, "cgroup.procs", pid_str);
+}
+
+/*
+ * Simplely, just move the pid to root memcg as avoid
+ * complicated consideration.
+ */
+int dettach_from_cgroup(char *cgroup)
+{
+ char pid_str[32];
+ char *root_memcg;
+
+ if (is_cgroup_v2)
+ root_memcg = CGROUP_BASE;
+ else
+ root_memcg = CGROUP_BASE "memory";
+
+ snprintf(pid_str, sizeof(pid_str), "%d", getpid());
+ return write_data_to_cgroup(root_memcg, "cgroup.procs", pid_str);
+}
+
+size_t read_data_from_cgroup(char *cgroup, char *file, char *field)
+{
+ char filename[128];
+ FILE *fp;
+ char line[80];
+ size_t size = -1;
+
+ snprintf(filename, sizeof(filename), "%s/%s", cgroup, file);
+ fp = fopen(filename, "r");
+ if (!fp) {
+ perror("fopen");
+ return -1;
+ }
+
+ while (fgets(line, sizeof(line), fp)) {
+ if (!strncmp(line, field, strlen(field))) {
+ char *value = line + strlen(field) + 1;
+
+ size = atol(value);
+ break;
+ }
+ }
+
+ fclose(fp);
+
+ return size;
+}
+
+size_t read_swap_from_cgroup(char *cgroup)
+{
+ if (is_cgroup_v2)
+ return read_data_from_cgroup(cgroup, "memory.stat", "pswpout");
+ else
+ return read_data_from_cgroup(cgroup, "memory.stat", "swap");
+}
+
+size_t read_huge_from_cgroup(char *cgroup)
+{
+ if (is_cgroup_v2)
+ return read_data_from_cgroup(cgroup, "memory.stat", "file_thp")
+ + read_data_from_cgroup(cgroup, "memory.stat", "anon_thp")
+ + read_data_from_cgroup(cgroup, "memory.stat", "shmem_thp");
+ else
+ return read_data_from_cgroup(cgroup, "memory.stat", "rss_huge");
+}
--
2.20.1
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH V2 7/8] mshare: selftests: Add test case to demostrate the swapping of mshare memory
2025-09-19 13:06 [PATCH V2 0/8] Add selftests for mshare Yongting Lin
` (4 preceding siblings ...)
2025-09-19 13:06 ` [PATCH V2 6/8] mshare: selftests: Add some helper functions for configuring and retrieving cgroup Yongting Lin
@ 2025-09-19 13:06 ` Yongting Lin
2025-09-19 13:06 ` [PATCH V2 8/8] mshare: selftests: Add test case to demostrate that mshare partly supports THP Yongting Lin
6 siblings, 0 replies; 8+ messages in thread
From: Yongting Lin @ 2025-09-19 13:06 UTC (permalink / raw)
To: anthony.yznaga, khalid, shuah
Cc: linux-kernel, linux-kselftest, akpm, linux-mm, libo.gcs85, Yongting Lin
This case is quit simple by using madvise(MADV_PAGEOUT), but for verifying
the memory size of being swappd, we need to setup the memcg and attach test
process to this memcg before perform the test.
Signed-off-by: Yongting Lin <linyongting@bytedance.com>
---
tools/testing/selftests/mshare/.gitignore | 1 +
tools/testing/selftests/mshare/Makefile | 2 +-
tools/testing/selftests/mshare/memory.c | 71 +++++++++++++++++++++++
3 files changed, 73 insertions(+), 1 deletion(-)
create mode 100644 tools/testing/selftests/mshare/memory.c
diff --git a/tools/testing/selftests/mshare/.gitignore b/tools/testing/selftests/mshare/.gitignore
index 406f31bd432c..116774fa2b82 100644
--- a/tools/testing/selftests/mshare/.gitignore
+++ b/tools/testing/selftests/mshare/.gitignore
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
basic
+memory
diff --git a/tools/testing/selftests/mshare/Makefile b/tools/testing/selftests/mshare/Makefile
index 651658d091c5..b0418b8c30f2 100644
--- a/tools/testing/selftests/mshare/Makefile
+++ b/tools/testing/selftests/mshare/Makefile
@@ -2,6 +2,6 @@
CFLAGS = $(KHDR_INCLUDES) -Wall -g -O2
-TEST_GEN_PROGS := basic
+TEST_GEN_PROGS := basic memory
include ../lib.mk
diff --git a/tools/testing/selftests/mshare/memory.c b/tools/testing/selftests/mshare/memory.c
new file mode 100644
index 000000000000..4bb0d22b9c03
--- /dev/null
+++ b/tools/testing/selftests/mshare/memory.c
@@ -0,0 +1,71 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/mman.h>
+
+#include "../kselftest_harness.h"
+#include "util.c"
+
+FIXTURE(memory)
+{
+ char filename[128];
+ int fd;
+
+ char cgroup[128];
+
+ void *addr;
+ size_t align_size;
+};
+
+FIXTURE_SETUP(memory)
+{
+ ASSERT_NE(create_mshare_test_cgroup(self->cgroup, sizeof(self->cgroup)), -1);
+
+ attach_to_cgroup(self->cgroup);
+
+ self->align_size = mshare_get_info();
+ self->fd = create_mshare_file(self->filename, sizeof(self->filename));
+ ASSERT_NE(self->fd, -1);
+ ASSERT_NE(ftruncate(self->fd, self->align_size), -1);
+
+ ASSERT_NE(mshare_ioctl_mapping(self->fd, MB(2),
+ MAP_ANONYMOUS | MAP_SHARED | MAP_FIXED),
+ -1);
+ self->addr = mmap(NULL, self->align_size, PROT_READ | PROT_WRITE,
+ MAP_SHARED, self->fd, 0);
+ ASSERT_NE(self->addr, MAP_FAILED);
+}
+
+FIXTURE_TEARDOWN(memory)
+{
+ ASSERT_NE(munmap(self->addr, self->align_size), -1);
+ close(self->fd);
+
+ ASSERT_NE(unlink(self->filename), -1);
+ dettach_from_cgroup(self->cgroup);
+
+ ASSERT_NE(remove_cgroup(self->cgroup), -1);
+}
+
+TEST_F(memory, swap)
+{
+ size_t swap_size;
+
+ /* fill physical memory */
+ memset(self->addr, 0x01, MB(2));
+
+ /* force to reclaim the memory of mshare */
+ ASSERT_NE(madvise(self->addr, MB(2), MADV_PAGEOUT), -1);
+
+ swap_size = read_swap_from_cgroup(self->cgroup);
+ ASSERT_NE(swap_size, -1);
+
+ /* convert to bytes */
+ swap_size *= 4096;
+
+ ksft_print_msg("Tip: Please configure swap space before running this test.\n");
+
+ /* allow an error of 10% */
+ ASSERT_GT(swap_size, MB(2) * 9 / 10);
+}
+
+TEST_HARNESS_MAIN
--
2.20.1
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH V2 8/8] mshare: selftests: Add test case to demostrate that mshare partly supports THP
2025-09-19 13:06 [PATCH V2 0/8] Add selftests for mshare Yongting Lin
` (5 preceding siblings ...)
2025-09-19 13:06 ` [PATCH V2 7/8] mshare: selftests: Add test case to demostrate the swapping of mshare memory Yongting Lin
@ 2025-09-19 13:06 ` Yongting Lin
6 siblings, 0 replies; 8+ messages in thread
From: Yongting Lin @ 2025-09-19 13:06 UTC (permalink / raw)
To: anthony.yznaga, khalid, shuah
Cc: linux-kernel, linux-kselftest, akpm, linux-mm, libo.gcs85, Yongting Lin
Currently, mshare doesn't support madvise(MADV_HUGEPAGE) to make pages
become THP page.
Thus we need to set /sys/kernel/mm/transparent_hugepage/shmem_enabled
to 'always', enabling mshare to acquire THP pages in a best effort way.
This case is quit simple that set up a mshare memory with 2MB size,
than use memset to fill the physical memory and verify whether THP
was allocated by reading memory.stat.
Signed-off-by: Yongting Lin <linyongting@bytedance.com>
---
tools/testing/selftests/mshare/memory.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/tools/testing/selftests/mshare/memory.c b/tools/testing/selftests/mshare/memory.c
index 4bb0d22b9c03..5132210b1465 100644
--- a/tools/testing/selftests/mshare/memory.c
+++ b/tools/testing/selftests/mshare/memory.c
@@ -68,4 +68,22 @@ TEST_F(memory, swap)
ASSERT_GT(swap_size, MB(2) * 9 / 10);
}
+TEST_F(memory, thp)
+{
+ /* fill physical memory */
+ memset(self->addr, 0x01, MB(2));
+
+ size_t huge = read_huge_from_cgroup(self->cgroup);
+
+ /*
+ * mshare only allocate in the best effort way, and
+ * don't support madvise(MADV_HUGEPAGE) to change pages
+ * into THP or khuged to replace pages with THP.
+ */
+ ksft_print_msg("Tip: Please enable transparent hugepages for shmem before running this test.\n"
+ "For example: echo always > /sys/kernel/mm/transparent_hugepage/shmem_enabled\n");
+
+ ASSERT_GE(huge, MB(2));
+}
+
TEST_HARNESS_MAIN
--
2.20.1
^ permalink raw reply [flat|nested] 8+ messages in thread