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 #if HAVE_NUMA_H 32 #include <numa.h> 33 #endif 34 #if HAVE_NUMAIF_H 35 #include <numaif.h> 36 #endif 37 #include <signal.h> 38 #include <stdio.h> 39 #include <unistd.h> 40 #include <limits.h> 41 42 #include "mem.h" 43 #include "numa_helper.h" 44 45 #if defined(HAVE_NUMA_V2) && defined(HAVE_LINUX_MEMPOLICY_H) 46 47 static int run = -1; 48 static int sleep_millisecs = -1; 49 static int merge_across_nodes = -1; 50 static unsigned long nr_pages; 51 52 static char *n_opt; 53 static struct tst_option ksm_options[] = { 54 {"n:", &n_opt, "-n x Allocate x pages memory per node"}, 55 {NULL, NULL, NULL} 56 }; 57 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 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 save_max_page_sharing(); 74 75 if (!is_numa(NULL, NH_MEMS, 2)) 76 tst_brk(TCONF, "The case needs a NUMA system."); 77 78 /* save the current value */ 79 SAFE_FILE_SCANF(PATH_KSM "run", "%d", &run); 80 SAFE_FILE_SCANF(PATH_KSM "merge_across_nodes", 81 "%d", &merge_across_nodes); 82 SAFE_FILE_SCANF(PATH_KSM "sleep_millisecs", 83 "%d", &sleep_millisecs); 84 } 85 86 static void cleanup(void) 87 { 88 if (merge_across_nodes != -1) { 89 FILE_PRINTF(PATH_KSM "merge_across_nodes", 90 "%d", merge_across_nodes); 91 } 92 93 if (sleep_millisecs != -1) 94 FILE_PRINTF(PATH_KSM "sleep_millisecs", "%d", sleep_millisecs); 95 96 if (run != -1) 97 FILE_PRINTF(PATH_KSM "run", "%d", run); 98 99 restore_max_page_sharing(); 100 } 101 102 static struct tst_test test = { 103 .needs_root = 1, 104 .options = ksm_options, 105 .setup = setup, 106 .cleanup = cleanup, 107 .test_all = test_ksm, 108 }; 109 110 #else 111 TST_TEST_TCONF("test requires libnuma >= 2 and it's development packages"); 112 #endif 113