Created
October 3, 2017 14:50
-
-
Save mrqwer88/1b5c42dc526e708d7111a1f3ce0c9633 to your computer and use it in GitHub Desktop.
ksmctl from rhel ksm packages with added default params support
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# The maximum number of unswappable kernel pages | |
# which may be allocated by ksm (0 for unlimited) | |
# If unset, defaults to half of total memory | |
# KSM_MAX_KERNEL_PAGES= | |
# KSM_SLEEP_MSECS=20 | |
# KSM_PAGES_TO_SCAN=100 | |
# KSM_MERGE_ACROSS_NODES=1 | |
# KSM_MAX_PAGE_SHARING=256 | |
# KSM_USE_ZERO_PAGES=0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Start/stop KSM, for systemd. | |
* Copyright (C) 2009, 2011 Red Hat, Inc. | |
* Written by Paolo Bonzini <[email protected]>. | |
* Based on the original sysvinit script by Dan Kenigsberg <[email protected]> | |
* This file is distributed under the GNU General Public License, version 2 | |
* or later. */ | |
#include <unistd.h> | |
#include <stdio.h> | |
#include <limits.h> | |
#include <stdint.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#define KSM_MAX_KERNEL_PAGES_FILE "/sys/kernel/mm/ksm/max_kernel_pages" | |
#define KSM_RUN_FILE "/sys/kernel/mm/ksm/run" | |
#define KSM_PAGES_TO_SCAN_FILE "/sys/kernel/mm/ksm/pages_to_scan" | |
#define KSM_SLEEP_MSECS_FILE "/sys/kernel/mm/ksm/sleep_millisecs" | |
#define KSM_MERGE_ACROSS_NODES_FILE "/sys/kernel/mm/ksm/merge_across_nodes" | |
#define KSM_MAX_PAGE_SHARING_FILE "/sys/kernel/mm/ksm/max_page_sharing" | |
#define KSM_USE_ZERO_PAGES_FILE "/sys/kernel/mm/ksm/use_zero_pages" | |
char *program_name; | |
int usage(void) | |
{ | |
fprintf(stderr, "Usage: %s {start|stop}\n", program_name); | |
return 1; | |
} | |
int write_value(uint64_t value, char *filename) | |
{ | |
FILE *fp; | |
if (!(fp = fopen(filename, "w")) || | |
fprintf(fp, "%llu\n", (unsigned long long) value) == EOF || | |
fflush(fp) == EOF || | |
fclose(fp) == EOF) | |
return 1; | |
return 0; | |
} | |
uint64_t ksm_max_kernel_pages() | |
{ | |
char *var = getenv("KSM_MAX_KERNEL_PAGES"); | |
char *endptr; | |
uint64_t value; | |
if (var && *var) { | |
value = strtoll(var, &endptr, 0); | |
if (value < LLONG_MAX && !*endptr) | |
return value; | |
} | |
/* Unless KSM_MAX_KERNEL_PAGES is set, let KSM munch up to half of | |
* total memory. */ | |
return sysconf(_SC_PHYS_PAGES) / 2; | |
} | |
uint64_t ksm_by_unsigned_int(char *env_name, uint64_t default_value){ | |
char *var = getenv(env_name); | |
char *endptr; | |
uint64_t value; | |
if (var && *var) { | |
value = strtoll(var, &endptr, 0); | |
if (value < UINT_MAX && !*endptr) | |
return value; | |
} | |
return default_value; | |
} | |
uint64_t ksm_by_int(char *env_name, uint64_t default_value){ | |
char *var = getenv(env_name); | |
char *endptr; | |
uint64_t value; | |
if (var && *var) { | |
value = strtoll(var, &endptr, 0); | |
if (value < INT_MAX && !*endptr) | |
return value; | |
} | |
return default_value; | |
} | |
int start(void) | |
{ | |
if (access(KSM_MAX_KERNEL_PAGES_FILE, R_OK) >= 0) | |
write_value(ksm_max_kernel_pages(), KSM_MAX_KERNEL_PAGES_FILE); | |
/* Milliseconds ksmd should sleep between batches | |
* static unsigned int ksm_thread_sleep_millisecs = 20; | |
*/ | |
if (getenv("KSM_SLEEP_MSECS") && access(KSM_SLEEP_MSECS_FILE, R_OK) >= 0) | |
write_value(ksm_by_unsigned_int("KSM_SLEEP_MSECS", 20), KSM_SLEEP_MSECS_FILE); | |
/* Number of pages ksmd should scan in one batch | |
* static unsigned int ksm_thread_pages_to_scan = 100; | |
*/ | |
if (getenv("KSM_PAGES_TO_SCAN") && access(KSM_PAGES_TO_SCAN_FILE, R_OK) >= 0) | |
write_value(ksm_by_unsigned_int("KSM_PAGES_TO_SCAN", 100), KSM_PAGES_TO_SCAN_FILE); | |
/* Zeroed when merging across nodes is not allowed | |
* static unsigned int ksm_merge_across_nodes = 1; | |
*/ | |
if (getenv("KSM_MERGE_ACROSS_NODES") && access(KSM_PAGES_TO_SCAN_FILE, R_OK) >= 0) | |
write_value(ksm_by_unsigned_int("KSM_MERGE_ACROSS_NODES", 1), KSM_MERGE_ACROSS_NODES_FILE); | |
/* Maximum number of page slots sharing a stable node | |
* static int ksm_max_page_sharing = 256; | |
*/ | |
if (getenv("KSM_MAX_PAGE_SHARING") && access(KSM_PAGES_TO_SCAN_FILE, R_OK) >= 0) | |
write_value(ksm_by_int("KSM_MAX_PAGE_SHARING", 256), KSM_MAX_PAGE_SHARING_FILE); | |
/* Whether to merge empty (zeroed) pages with actual zero pages | |
* Default to false for backwards compatibility | |
* ksm_use_zero_pages = false; | |
*/ | |
if (getenv("KSM_USE_ZERO_PAGES") && access(KSM_PAGES_TO_SCAN_FILE, R_OK) >= 0) | |
write_value(ksm_by_unsigned_int("KSM_USE_ZERO_PAGES", 0), KSM_USE_ZERO_PAGES_FILE); | |
return write_value(1, KSM_RUN_FILE); | |
} | |
int stop(void) | |
{ | |
return write_value(0, KSM_RUN_FILE); | |
} | |
int main(int argc, char **argv) | |
{ | |
program_name = argv[0]; | |
if (argc < 2) { | |
return usage(); | |
} else if (!strcmp(argv[1], "start")) { | |
return start(); | |
} else if (!strcmp(argv[1], "stop")) { | |
return stop(); | |
} else { | |
return usage(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Comments and default value were gotten from ./mm/kms.c file from 4.13 kernel.