• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013-2017  Red Hat, Inc.
3  *
4  * This program is free software;  you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY;  without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
12  * the GNU General Public License for more details.
13  */
14 
15 /*
16  * The case is designed to test new sysfs boolean knob
17  * /sys/kernel/mm/ksm/merge_across_nodes, which was introduced by
18  * commit 90bd6fd31c8097ee (ksm: allow trees per NUMA node).
19  * when merge_across_nodes is set to zero only pages from the same
20  * node are merged, otherwise pages from all nodes can be merged
21  * together.
22  */
23 
24 #include "config.h"
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <sys/mman.h>
28 #include <limits.h>
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <signal.h>
32 #include <stdio.h>
33 #include <unistd.h>
34 #include <limits.h>
35 
36 #include "mem.h"
37 #include "numa_helper.h"
38 
39 #ifdef HAVE_NUMA_V2
40 #include <numaif.h>
41 
42 static int run = -1;
43 static int sleep_millisecs = -1;
44 static int merge_across_nodes = -1;
45 static unsigned long nr_pages;
46 
47 static char *n_opt;
48 
test_ksm(void)49 static void test_ksm(void)
50 {
51 	if (n_opt)
52 		nr_pages = SAFE_STRTOUL(n_opt, 0, ULONG_MAX);
53 	else
54 		nr_pages = 100;
55 
56 	test_ksm_merge_across_nodes(nr_pages);
57 }
58 
setup(void)59 static void setup(void)
60 {
61 	if (access(PATH_KSM "merge_across_nodes", F_OK) == -1)
62 		tst_brk(TCONF, "no merge_across_nodes sysfs knob");
63 
64 	if (!is_numa(NULL, NH_MEMS, 2))
65 		tst_brk(TCONF, "The case needs a NUMA system.");
66 
67 	/* save the current value */
68 	SAFE_FILE_SCANF(PATH_KSM "run", "%d", &run);
69 	SAFE_FILE_SCANF(PATH_KSM "merge_across_nodes",
70 			"%d", &merge_across_nodes);
71 	SAFE_FILE_SCANF(PATH_KSM "sleep_millisecs",
72 			"%d", &sleep_millisecs);
73 }
74 
cleanup(void)75 static void cleanup(void)
76 {
77 	if (merge_across_nodes != -1) {
78 		FILE_PRINTF(PATH_KSM "merge_across_nodes",
79 			    "%d", merge_across_nodes);
80 	}
81 
82 	if (sleep_millisecs != -1)
83 		FILE_PRINTF(PATH_KSM "sleep_millisecs", "%d", sleep_millisecs);
84 
85 	if (run != -1)
86 		FILE_PRINTF(PATH_KSM "run", "%d", run);
87 }
88 
89 static struct tst_test test = {
90 	.needs_root = 1,
91 	.options = (struct tst_option[]) {
92 		{"n:", &n_opt,  "Allocate x pages memory per node"},
93 		{}
94 	},
95 	.setup = setup,
96 	.cleanup = cleanup,
97 	.save_restore = (const char * const[]) {
98 		"?/sys/kernel/mm/ksm/max_page_sharing",
99 		NULL,
100 	},
101 	.test_all = test_ksm,
102 };
103 
104 #else
105 	TST_TEST_TCONF(NUMA_ERROR_MSG);
106 #endif
107