1 /* 2 * Copyright (C) 2010-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 * Kernel Samepage Merging (KSM) for Memory Resource Controller and NUMA 15 * 16 * Basic tests were to start several programs with same and different 17 * memory contents and ensure only to merge the ones with the same 18 * contents. When changed the content of one of merged pages in a 19 * process and to the mode "unmerging", it should discard all merged 20 * pages there. Also tested it is possible to disable KSM. There are 21 * also command-line options to specify the memory allocation size, and 22 * number of processes have same memory contents so it is possible to 23 * test more advanced things like KSM + OOM etc. 24 * 25 * Prerequisites: 26 * 27 * 1) ksm and ksmtuned daemons need to be disabled. Otherwise, it could 28 * distrub the testing as they also change some ksm tunables depends 29 * on current workloads. 30 * 31 * The test steps are: 32 * - Check ksm feature and backup current run setting. 33 * - Change run setting to 1 - merging. 34 * - 3 memory allocation programs have the memory contents that 2 of 35 * them are all 'a' and one is all 'b'. 36 * - Check ksm statistics and verify the content. 37 * - 1 program changes the memory content from all 'a' to all 'b'. 38 * - Check ksm statistics and verify the content. 39 * - All programs change the memory content to all 'd'. 40 * - Check ksm statistics and verify the content. 41 * - Change one page of a process. 42 * - Check ksm statistics and verify the content. 43 * - Change run setting to 2 - unmerging. 44 * - Check ksm statistics and verify the content. 45 * - Change run setting to 0 - stop. 46 */ 47 48 #include "config.h" 49 #include <sys/types.h> 50 #include <sys/stat.h> 51 #include <errno.h> 52 #include <fcntl.h> 53 #include <signal.h> 54 #include <stdio.h> 55 #include <unistd.h> 56 #include "mem.h" 57 #include "ksm_common.h" 58 59 #ifdef HAVE_NUMA_V2 60 #include <numaif.h> 61 62 static int cpuset_mounted; 63 static int memcg_mounted; 64 65 static void verify_ksm(void) 66 { 67 unsigned long nmask[MAXNODES / BITS_PER_LONG] = { 0 }; 68 unsigned int node; 69 70 node = get_a_numa_node(); 71 set_node(nmask, node); 72 73 write_memcg(); 74 75 if (set_mempolicy(MPOL_BIND, nmask, MAXNODES) == -1) { 76 if (errno != ENOSYS) 77 tst_brk(TBROK | TERRNO, "set_mempolicy"); 78 else 79 tst_brk(TCONF, "set_mempolicy syscall is not " 80 "implemented on your system."); 81 } 82 create_same_memory(size, num, unit); 83 84 write_cpusets(node); 85 create_same_memory(size, num, unit); 86 } 87 88 static void cleanup(void) 89 { 90 if (access(PATH_KSM "merge_across_nodes", F_OK) == 0) 91 FILE_PRINTF(PATH_KSM "merge_across_nodes", 92 "%d", merge_across_nodes); 93 94 if (cpuset_mounted) 95 umount_mem(CPATH, CPATH_NEW); 96 if (memcg_mounted) 97 umount_mem(MEMCG_PATH, MEMCG_PATH_NEW); 98 } 99 100 static void setup(void) 101 { 102 if (access(PATH_KSM, F_OK) == -1) 103 tst_brk(TCONF, "KSM configuration is not enabled"); 104 105 if (access(PATH_KSM "merge_across_nodes", F_OK) == 0) { 106 SAFE_FILE_SCANF(PATH_KSM "merge_across_nodes", 107 "%d", &merge_across_nodes); 108 SAFE_FILE_PRINTF(PATH_KSM "merge_across_nodes", "1"); 109 } 110 111 parse_ksm_options(opt_sizestr, &size, opt_numstr, &num, opt_unitstr, &unit); 112 113 mount_mem("cpuset", "cpuset", NULL, CPATH, CPATH_NEW); 114 cpuset_mounted = 1; 115 mount_mem("memcg", "cgroup", "memory", MEMCG_PATH, MEMCG_PATH_NEW); 116 memcg_mounted = 1; 117 } 118 119 static struct tst_test test = { 120 .needs_root = 1, 121 .forks_child = 1, 122 .options = ksm_options, 123 .setup = setup, 124 .cleanup = cleanup, 125 .save_restore = save_restore, 126 .test_all = verify_ksm, 127 .min_kver = "2.6.32", 128 }; 129 130 #else 131 TST_TEST_TCONF(NUMA_ERROR_MSG); 132 #endif 133