Home | History | Annotate | Download | only in ksm
      1 /*
      2  * Kernel Samepage Merging (KSM) for Memory Resource Controller
      3  *
      4  * Basic tests were to start several programs with same and different
      5  * memory contents and ensure only to merge the ones with the same
      6  * contents. When changed the content of one of merged pages in a
      7  * process and to the mode "unmerging", it should discard all merged
      8  * pages there. Also tested it is possible to disable KSM. There are
      9  * also command-line options to specify the memory allocation size, and
     10  * number of processes have same memory contents so it is possible to
     11  * test more advanced things like KSM + OOM etc.
     12  *
     13  * Prerequisites:
     14  *
     15  * 1) ksm and ksmtuned daemons need to be disabled. Otherwise, it could
     16  *    distrub the testing as they also change some ksm tunables depends
     17  *    on current workloads.
     18  *
     19  * The test steps are:
     20  * - Check ksm feature and backup current run setting.
     21  * - Change run setting to 1 - merging.
     22  * - 3 memory allocation programs have the memory contents that 2 of
     23  *   them are all 'a' and one is all 'b'.
     24  * - Check ksm statistics and verify the content.
     25  * - 1 program changes the memory content from all 'a' to all 'b'.
     26  * - Check ksm statistics and verify the content.
     27  * - All programs change the memory content to all 'd'.
     28  * - Check ksm statistics and verify the content.
     29  * - Change one page of a process.
     30  * - Check ksm statistics and verify the content.
     31  * - Change run setting to 2 - unmerging.
     32  * - Check ksm statistics and verify the content.
     33  * - Change run setting to 0 - stop.
     34  *
     35  * Copyright (C) 2010  Red Hat, Inc.
     36  *
     37  * This program is free software; you can redistribute it and/or
     38  * modify it under the terms of version 2 of the GNU General Public
     39  * License as published by the Free Software Foundation.
     40  *
     41  * This program is distributed in the hope that it would be useful,
     42  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     43  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     44  *
     45  * Further, this software is distributed without any warranty that it
     46  * is free of the rightful claim of any third person regarding
     47  * infringement or the like.  Any license provided herein, whether
     48  * implied or otherwise, applies only to this software file.  Patent
     49  * licenses, if any, provided herein do not apply to combinations of
     50  * this program with other software, or any other product whatsoever.
     51  *
     52  * You should have received a copy of the GNU General Public License
     53  * along with this program; if not, write the Free Software
     54  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
     55  * 02110-1301, USA.
     56  */
     57 
     58 #include <sys/types.h>
     59 #include <sys/mman.h>
     60 #include <sys/stat.h>
     61 #include <sys/wait.h>
     62 #include <errno.h>
     63 #include <fcntl.h>
     64 #include <signal.h>
     65 #include <stdio.h>
     66 #include <stdlib.h>
     67 #include <string.h>
     68 #include <unistd.h>
     69 #include "test.h"
     70 #include "mem.h"
     71 
     72 char *TCID = "ksm03";
     73 int TST_TOTAL = 1;
     74 
     75 static int merge_across_nodes;
     76 
     77 option_t ksm_options[] = {
     78 	{"n:", &opt_num, &opt_numstr},
     79 	{"s:", &opt_size, &opt_sizestr},
     80 	{"u:", &opt_unit, &opt_unitstr},
     81 	{NULL, NULL, NULL}
     82 };
     83 
     84 int main(int argc, char *argv[])
     85 {
     86 	int lc;
     87 	int size = 128, num = 3, unit = 1;
     88 
     89 	tst_parse_opts(argc, argv, ksm_options, ksm_usage);
     90 	setup();
     91 	for (lc = 0; TEST_LOOPING(lc); lc++) {
     92 		tst_count = 0;
     93 		check_ksm_options(&size, &num, &unit);
     94 		write_memcg();
     95 		create_same_memory(size, num, unit);
     96 	}
     97 	cleanup();
     98 	tst_exit();
     99 }
    100 
    101 void setup(void)
    102 {
    103 	tst_require_root();
    104 
    105 	if (tst_kvercmp(2, 6, 32) < 0)
    106 		tst_brkm(TCONF, NULL, "2.6.32 or greater kernel required");
    107 	if (access(PATH_KSM, F_OK) == -1)
    108 		tst_brkm(TCONF, NULL, "KSM configuration is not enabled");
    109 
    110 	if (access(PATH_KSM "merge_across_nodes", F_OK) == 0) {
    111 		SAFE_FILE_SCANF(NULL, PATH_KSM "merge_across_nodes",
    112 				"%d", &merge_across_nodes);
    113 		SAFE_FILE_PRINTF(NULL, PATH_KSM "merge_across_nodes", "1");
    114 	}
    115 
    116 	save_max_page_sharing();
    117 
    118 	mount_mem("memcg", "cgroup", "memory", MEMCG_PATH, MEMCG_PATH_NEW);
    119 	tst_sig(FORK, DEF_HANDLER, NULL);
    120 	TEST_PAUSE;
    121 }
    122 
    123 void cleanup(void)
    124 {
    125 	if (access(PATH_KSM "merge_across_nodes", F_OK) == 0)
    126 		FILE_PRINTF(PATH_KSM "merge_across_nodes",
    127 				 "%d", merge_across_nodes);
    128 
    129 	restore_max_page_sharing();
    130 
    131 	umount_mem(MEMCG_PATH, MEMCG_PATH_NEW);
    132 }
    133