Home | History | Annotate | Download | only in ksm
      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 
     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 	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 
     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