Skip to content

Commit 07115fc

Browse files
Stefan Roeschakpm00
authored andcommitted
selftests/mm: add new selftests for KSM
This adds three new tests to the selftests for KSM. These tests use the new prctl API's to enable and disable KSM. 1) add new prctl flags to prctl header file in tools dir This adds the new prctl flags to the include file prct.h in the tools directory. This makes sure they are available for testing. 2) add KSM prctl merge test to ksm_tests This adds the -t option to the ksm_tests program. The -t flag allows to specify if it should use madvise or prctl ksm merging. 3) add two functions for debugging merge outcome for ksm_tests This adds two functions to report the metrics in /proc/self/ksm_stat and /sys/kernel/debug/mm/ksm. The debug output is enabled with the -d option. 4) add KSM prctl test to ksm_functional_tests This adds a test to the ksm_functional_test that verifies that the prctl system call to enable / disable KSM works. 5) add KSM fork test to ksm_functional_test Add fork test to verify that the MMF_VM_MERGE_ANY flag is inherited by the child process. Link: https://lkml.kernel.org/r/20230418051342.1919757-4-shr@devkernel.io Signed-off-by: Stefan Roesch <shr@devkernel.io> Acked-by: David Hildenbrand <david@redhat.com> Cc: Bagas Sanjaya <bagasdotme@gmail.com> Cc: David Hildenbrand <david@redhat.com> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Michal Hocko <mhocko@suse.com> Cc: Rik van Riel <riel@surriel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
1 parent d21077f commit 07115fc

4 files changed

Lines changed: 228 additions & 39 deletions

File tree

tools/include/uapi/linux/prctl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,4 +290,6 @@ struct prctl_mm_map {
290290
#define PR_SET_VMA 0x53564d41
291291
# define PR_SET_VMA_ANON_NAME 0
292292

293+
#define PR_SET_MEMORY_MERGE 67
294+
#define PR_GET_MEMORY_MERGE 68
293295
#endif /* _LINUX_PRCTL_H */

tools/testing/selftests/mm/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ MACHINE ?= $(shell echo $(uname_M) | sed -e 's/aarch64.*/arm64/' -e 's/ppc64.*/p
2929
# LDLIBS.
3030
MAKEFLAGS += --no-builtin-rules
3131

32-
CFLAGS = -Wall -I $(top_srcdir) $(EXTRA_CFLAGS) $(KHDR_INCLUDES)
32+
CFLAGS = -Wall -I $(top_srcdir) -I $(top_srcdir)/tools/include/uapi $(EXTRA_CFLAGS) $(KHDR_INCLUDES)
3333
LDLIBS = -lrt -lpthread
3434

3535
TEST_GEN_PROGS = cow

tools/testing/selftests/mm/ksm_functional_tests.c

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@
1515
#include <errno.h>
1616
#include <fcntl.h>
1717
#include <sys/mman.h>
18+
#include <sys/prctl.h>
1819
#include <sys/syscall.h>
1920
#include <sys/ioctl.h>
21+
#include <sys/wait.h>
2022
#include <linux/userfaultfd.h>
2123

2224
#include "../kselftest.h"
@@ -237,9 +239,93 @@ static void test_unmerge_uffd_wp(void)
237239
}
238240
#endif
239241

242+
/* Verify that KSM can be enabled / queried with prctl. */
243+
static void test_prctl(void)
244+
{
245+
int ret;
246+
247+
ksft_print_msg("[RUN] %s\n", __func__);
248+
249+
ret = prctl(PR_SET_MEMORY_MERGE, 1, 0, 0, 0);
250+
if (ret < 0 && errno == EINVAL) {
251+
ksft_test_result_skip("PR_SET_MEMORY_MERGE not supported\n");
252+
return;
253+
} else if (ret) {
254+
ksft_test_result_fail("PR_SET_MEMORY_MERGE=1 failed\n");
255+
return;
256+
}
257+
258+
ret = prctl(PR_GET_MEMORY_MERGE, 0, 0, 0, 0);
259+
if (ret < 0) {
260+
ksft_test_result_fail("PR_GET_MEMORY_MERGE failed\n");
261+
return;
262+
} else if (ret != 1) {
263+
ksft_test_result_fail("PR_SET_MEMORY_MERGE=1 not effective\n");
264+
return;
265+
}
266+
267+
ret = prctl(PR_SET_MEMORY_MERGE, 0, 0, 0, 0);
268+
if (ret) {
269+
ksft_test_result_fail("PR_SET_MEMORY_MERGE=0 failed\n");
270+
return;
271+
}
272+
273+
ret = prctl(PR_GET_MEMORY_MERGE, 0, 0, 0, 0);
274+
if (ret < 0) {
275+
ksft_test_result_fail("PR_GET_MEMORY_MERGE failed\n");
276+
return;
277+
} else if (ret != 0) {
278+
ksft_test_result_fail("PR_SET_MEMORY_MERGE=0 not effective\n");
279+
return;
280+
}
281+
282+
ksft_test_result_pass("Setting/clearing PR_SET_MEMORY_MERGE works\n");
283+
}
284+
285+
/* Verify that prctl ksm flag is inherited. */
286+
static void test_prctl_fork(void)
287+
{
288+
int ret, status;
289+
pid_t child_pid;
290+
291+
ksft_print_msg("[RUN] %s\n", __func__);
292+
293+
ret = prctl(PR_SET_MEMORY_MERGE, 1, 0, 0, 0);
294+
if (ret < 0 && errno == EINVAL) {
295+
ksft_test_result_skip("PR_SET_MEMORY_MERGE not supported\n");
296+
return;
297+
} else if (ret) {
298+
ksft_test_result_fail("PR_SET_MEMORY_MERGE=1 failed\n");
299+
return;
300+
}
301+
302+
child_pid = fork();
303+
if (!child_pid) {
304+
exit(prctl(PR_GET_MEMORY_MERGE, 0, 0, 0, 0));
305+
} else if (child_pid < 0) {
306+
ksft_test_result_fail("fork() failed\n");
307+
return;
308+
}
309+
310+
if (waitpid(child_pid, &status, 0) < 0) {
311+
ksft_test_result_fail("waitpid() failed\n");
312+
return;
313+
} else if (WEXITSTATUS(status) != 1) {
314+
ksft_test_result_fail("unexpected PR_GET_MEMORY_MERGE result in child\n");
315+
return;
316+
}
317+
318+
if (prctl(PR_SET_MEMORY_MERGE, 0, 0, 0, 0)) {
319+
ksft_test_result_fail("PR_SET_MEMORY_MERGE=0 failed\n");
320+
return;
321+
}
322+
323+
ksft_test_result_pass("PR_SET_MEMORY_MERGE value is inherited\n");
324+
}
325+
240326
int main(int argc, char **argv)
241327
{
242-
unsigned int tests = 2;
328+
unsigned int tests = 4;
243329
int err;
244330

245331
#ifdef __NR_userfaultfd
@@ -267,6 +353,9 @@ int main(int argc, char **argv)
267353
test_unmerge_uffd_wp();
268354
#endif
269355

356+
test_prctl();
357+
test_prctl_fork();
358+
270359
err = ksft_get_fail_cnt();
271360
if (err)
272361
ksft_exit_fail_msg("%d out of %d tests failed\n",

0 commit comments

Comments
 (0)