Home | History | Annotate | Download | only in ksm
      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 
     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 
     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 
    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 
    125 static void usage(void)
    126 {
    127 	printf("  -n x    Allocate x pages memory per node\n");
    128 }
    129 
    130 #else /* no NUMA */
    131 int main(void)
    132 {
    133 	tst_brkm(TCONF, NULL, "no NUMA development packages installed.");
    134 }
    135 #endif
    136