• 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 static struct tst_option ksm_options[] = {
49 	{"n:", &n_opt,  "-n x    Allocate x pages memory per node"},
50 	{NULL, NULL, NULL}
51 };
52 
53 static const char * const save_restore[] = {
54 	"?/sys/kernel/mm/ksm/max_page_sharing",
55 	NULL,
56 };
57 
test_ksm(void)58 static void test_ksm(void)
59 {
60 	if (n_opt)
61 		nr_pages = SAFE_STRTOUL(n_opt, 0, ULONG_MAX);
62 	else
63 		nr_pages = 100;
64 
65 	test_ksm_merge_across_nodes(nr_pages);
66 }
67 
setup(void)68 static void setup(void)
69 {
70 	if (access(PATH_KSM "merge_across_nodes", F_OK) == -1)
71 		tst_brk(TCONF, "no merge_across_nodes sysfs knob");
72 
73 	if (!is_numa(NULL, NH_MEMS, 2))
74 		tst_brk(TCONF, "The case needs a NUMA system.");
75 
76 	/* save the current value */
77 	SAFE_FILE_SCANF(PATH_KSM "run", "%d", &run);
78 	SAFE_FILE_SCANF(PATH_KSM "merge_across_nodes",
79 			"%d", &merge_across_nodes);
80 	SAFE_FILE_SCANF(PATH_KSM "sleep_millisecs",
81 			"%d", &sleep_millisecs);
82 }
83 
cleanup(void)84 static void cleanup(void)
85 {
86 	if (merge_across_nodes != -1) {
87 		FILE_PRINTF(PATH_KSM "merge_across_nodes",
88 			    "%d", merge_across_nodes);
89 	}
90 
91 	if (sleep_millisecs != -1)
92 		FILE_PRINTF(PATH_KSM "sleep_millisecs", "%d", sleep_millisecs);
93 
94 	if (run != -1)
95 		FILE_PRINTF(PATH_KSM "run", "%d", run);
96 }
97 
98 static struct tst_test test = {
99 	.needs_root = 1,
100 	.options = ksm_options,
101 	.setup = setup,
102 	.cleanup = cleanup,
103 	.save_restore = save_restore,
104 	.test_all = test_ksm,
105 };
106 
107 #else
108 	TST_TEST_TCONF(NUMA_ERROR_MSG);
109 #endif
110