1 /*
2 * Copyright (C) 2013 Linux Test Project
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of version 2 of the GNU General Public
6 * License as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it would be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * Further, this software is distributed without any warranty that it
13 * is free of the rightful claim of any third person regarding
14 * infringement or the like. Any license provided herein, whether
15 * implied or otherwise, applies only to this software file. Patent
16 * licenses, if any, provided herein do not apply to combinations of
17 * this program with other software, or any other product whatsoever.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 * 02110-1301, USA.
23 */
24
25 /*
26 * The case is designed to test new sysfs boolean knob
27 * /sys/kernel/mm/ksm/merge_across_nodes, which was introduced by
28 * commit 90bd6fd31c8097ee (ksm: allow trees per NUMA node).
29 * when merge_across_nodes is set to zero only pages from the same
30 * node are merged, otherwise pages from all nodes can be merged
31 * together.
32 */
33
34 #include "config.h"
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <sys/mman.h>
38 #include <errno.h>
39 #include <fcntl.h>
40 #if HAVE_NUMAIF_H
41 #include <numaif.h>
42 #endif
43 #include <signal.h>
44 #include <stdio.h>
45 #include <unistd.h>
46 #include "numa_helper.h"
47 #include "test.h"
48 #include "safe_macros.h"
49 #include "mem.h"
50
51 char *TCID = "ksm06";
52 int TST_TOTAL = 1;
53
54 #if HAVE_NUMA_H && HAVE_LINUX_MEMPOLICY_H && HAVE_NUMAIF_H \
55 && HAVE_MPOL_CONSTANTS
56
57 static int run;
58 static int sleep_millisecs;
59 static int merge_across_nodes;
60 static int n_flag;
61 static unsigned long nr_pages;
62
63 static char *n_opt;
64 option_t options[] = {
65 { "n:", &n_flag, &n_opt },
66 { NULL, NULL, NULL }
67 };
68 static void usage(void);
69
main(int argc,char * argv[])70 int main(int argc, char *argv[])
71 {
72 int lc;
73
74 tst_parse_opts(argc, argv, options, &usage);
75
76 if (n_flag)
77 nr_pages = SAFE_STRTOUL(NULL, n_opt, 0, ULONG_MAX);
78 else
79 nr_pages = 100;
80
81 setup();
82
83 for (lc = 0; TEST_LOOPING(lc); lc++) {
84 tst_count = 0;
85
86 test_ksm_merge_across_nodes(nr_pages);
87 }
88
89 cleanup();
90 tst_exit();
91 }
92
setup(void)93 void setup(void)
94 {
95 if (access(PATH_KSM "merge_across_nodes", F_OK) == -1)
96 tst_brkm(TCONF, NULL, "no merge_across_nodes sysfs knob");
97
98 if (!is_numa(NULL, NH_MEMS, 2))
99 tst_brkm(TCONF, NULL, "The case needs a NUMA system.");
100
101 /* save the current value */
102 SAFE_FILE_SCANF(NULL, PATH_KSM "run", "%d", &run);
103 SAFE_FILE_SCANF(NULL, PATH_KSM "merge_across_nodes",
104 "%d", &merge_across_nodes);
105 SAFE_FILE_SCANF(NULL, PATH_KSM "sleep_millisecs",
106 "%d", &sleep_millisecs);
107
108 save_max_page_sharing();
109
110 tst_sig(FORK, DEF_HANDLER, cleanup);
111 TEST_PAUSE;
112 }
113
cleanup(void)114 void cleanup(void)
115 {
116 FILE_PRINTF(PATH_KSM "merge_across_nodes",
117 "%d", merge_across_nodes);
118 FILE_PRINTF(PATH_KSM "sleep_millisecs",
119 "%d", sleep_millisecs);
120 FILE_PRINTF(PATH_KSM "run", "%d", run);
121
122 restore_max_page_sharing();
123 }
124
usage(void)125 static void usage(void)
126 {
127 printf(" -n x Allocate x pages memory per node\n");
128 }
129
130 #else /* no NUMA */
main(void)131 int main(void)
132 {
133 tst_brkm(TCONF, NULL, "no NUMA development packages installed.");
134 }
135 #endif
136