aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric B Munson <emunson@mgebm.net>2011-12-07 10:39:00 -0500
committerEric B Munson <emunson@mgebm.net>2011-12-15 14:50:18 -0500
commitecc196be536837d72739f033795553dfdcc328ce (patch)
treeefc9be35bf7dbfe42107cc4eea438ce36fd23fcf
parent9876ed942f134fa1df32b2bba235f58d3a1ea781 (diff)
downloadlibhugetlbfs-ecc196be536837d72739f033795553dfdcc328ce.tar.gz
Add support to hugeadm for configuring transparent huge pages
Transparent huge pages (THP) have two tunables in sysfs used to control the behavior of khugepaged. This patch adds the support for controlling these tunables via hugeadm options. Signed-off-by: Eric B Munson <emunson@mgebm.net> Acked-by: Andrew Hastings <abh@cray.com> Cc: abh@cray.com Cc: daivd@gibson.dropbear.id.au
-rw-r--r--hugeadm.c105
-rw-r--r--man/hugeadm.835
2 files changed, 140 insertions, 0 deletions
diff --git a/hugeadm.c b/hugeadm.c
index 26056e9..781f23c 100644
--- a/hugeadm.c
+++ b/hugeadm.c
@@ -83,6 +83,14 @@ extern char *optarg;
#define SWAP_FREE "SwapFree:"
#define SWAP_TOTAL "SwapTotal:"
+#define ALWAYS "always"
+#define MADVISE "madvise"
+#define NEVER "never"
+#define TRANS_ENABLE "/sys/kernel/mm/transparent_hugepage/enabled"
+#define KHUGE_SCAN_PAGES "/sys/kernel/mm/transparent_hugepage/khugepaged/pages_to_scan"
+#define KHUGE_SCAN_SLEEP "/sys/kernel/mm/transparent_hugepage/khugepaged/scan_sleep_millisecs"
+#define KHUGE_ALLOC_SLEEP "/sys/kernel/mm/transparent_hugepage/khugepaged/alloc_sleep_millisecs"
+
void print_usage()
{
fprintf(stderr, "hugeadm [options]\n");
@@ -97,6 +105,15 @@ void print_usage()
CONT("Adjust pool 'size' lower bound");
OPTION("--obey-mempolicy", "Obey the NUMA memory policy when");
CONT("adjusting the pool 'size' lower bound");
+ OPTION("--thp-always", "Enable transparent huge pages always");
+ OPTION("--thp-madvise", "Enable transparent huge pages with madvise");
+ OPTION("--thp-never", "Disable transparent huge pages");
+ OPTION("--thp-khugepaged-pages <pages to scan>", "Number of pages that khugepaged");
+ CONT("should scan on each pass");
+ OPTION("--thp-khugepaged-scan-sleep <milliseconds>", "Time in ms to sleep between");
+ CONT("khugepaged passes");
+ OPTION("--thp-khugepages-alloc-sleep <milliseconds>", "Time in ms for khugepaged");
+ CONT("to wait if there was a huge page allocation failure");
OPTION("--pool-pages-max <size|DEFAULT>:[+|-]<pagecount|memsize<G|M|K>>", "");
CONT("Adjust pool 'size' upper bound");
OPTION("--set-recommended-min_free_kbytes", "");
@@ -271,6 +288,16 @@ void verbose_expose(void)
#define LONG_EXPLAIN ('e' << 8)
+#define LONG_TRANS ('t' << 8)
+#define LONG_TRANS_ALWAYS (LONG_TRANS|'a')
+#define LONG_TRANS_MADVISE (LONG_TRANS|'m')
+#define LONG_TRANS_NEVER (LONG_TRANS|'n')
+
+#define LONG_KHUGE ('K' << 8)
+#define LONG_KHUGE_PAGES (LONG_KHUGE|'p')
+#define LONG_KHUGE_SCAN (LONG_KHUGE|'s')
+#define LONG_KHUGE_ALLOC (LONG_KHUGE|'a')
+
#define MAX_POOLS 32
static int cmpsizes(const void *p1, const void *p2)
@@ -1062,6 +1089,30 @@ void rem_ramdisk_swap(){
}
}
+void set_trans_opt(const char *file, const char *value)
+{
+ FILE *f;
+
+ if (geteuid() != 0) {
+ ERROR("Transparent huge page options can only be set by root\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (opt_dry_run) {
+ printf("echo '%s' > %s\n", value, file);
+ return;
+ }
+
+ f = fopen(file, "w");
+ if (!f) {
+ ERROR("Couldn't open %s: %s\n", file, strerror(errno));
+ return;
+ }
+
+ fprintf(f, "%s", value);
+ fclose(f);
+}
+
enum {
POOL_MIN,
POOL_MAX,
@@ -1308,7 +1359,10 @@ int main(int argc, char** argv)
int opt_list_mounts = 0, opt_pool_list = 0, opt_create_mounts = 0;
int opt_global_mounts = 0, opt_pgsizes = 0, opt_pgsizes_all = 0;
int opt_explain = 0, minadj_count = 0, maxadj_count = 0;
+ int opt_trans_always = 0, opt_trans_never = 0, opt_trans_madvise = 0;
+ int opt_khuge_pages = 0, opt_khuge_scan = 0, opt_khuge_alloc = 0;
int ret = 0, index = 0;
+ char *khuge_pages = NULL, *khuge_alloc = NULL, *khuge_scan = NULL;
gid_t opt_gid = 0;
struct group *opt_grp = NULL;
int group_invalid = 0;
@@ -1321,6 +1375,12 @@ int main(int argc, char** argv)
{"pool-pages-min", required_argument, NULL, LONG_POOL_MIN_ADJ},
{"pool-pages-max", required_argument, NULL, LONG_POOL_MAX_ADJ},
{"obey-mempolicy", no_argument, NULL, LONG_POOL_MEMPOL},
+ {"thp-always", no_argument, NULL, LONG_TRANS_ALWAYS},
+ {"thp-madvise", no_argument, NULL, LONG_TRANS_MADVISE},
+ {"thp-never", no_argument, NULL, LONG_TRANS_NEVER},
+ {"thp-khugepaged-pages", required_argument, NULL, LONG_KHUGE_PAGES},
+ {"thp-khugepaged-scan-sleep", required_argument, NULL, LONG_KHUGE_SCAN},
+ {"thp-khugepaged-alloc-sleep", required_argument, NULL, LONG_KHUGE_ALLOC},
{"set-recommended-min_free_kbytes", no_argument, NULL, LONG_SET_RECOMMENDED_MINFREEKBYTES},
{"set-recommended-shmmax", no_argument, NULL, LONG_SET_RECOMMENDED_SHMMAX},
{"set-shm-group", required_argument, NULL, LONG_SET_HUGETLB_SHM_GROUP},
@@ -1424,6 +1484,33 @@ int main(int argc, char** argv)
opt_obey_mempolicy = 1;
break;
+ case LONG_TRANS_ALWAYS:
+ opt_trans_always = 1;
+ break;
+
+ case LONG_TRANS_MADVISE:
+ opt_trans_madvise = 1;
+ break;
+
+ case LONG_TRANS_NEVER:
+ opt_trans_never = 1;
+ break;
+
+ case LONG_KHUGE_PAGES:
+ opt_khuge_pages = 1;
+ khuge_pages = optarg;
+ break;
+
+ case LONG_KHUGE_SCAN:
+ opt_khuge_scan = 1;
+ khuge_scan = optarg;
+ break;
+
+ case LONG_KHUGE_ALLOC:
+ opt_khuge_alloc = 1;
+ khuge_alloc = optarg;
+ break;
+
case LONG_POOL_MAX_ADJ:
if (! kernel_has_overcommit()) {
ERROR("kernel does not support overcommit, "
@@ -1534,6 +1621,24 @@ int main(int argc, char** argv)
if (opt_movable != -1)
setup_zone_movable(opt_movable);
+ if (opt_trans_always)
+ set_trans_opt(TRANS_ENABLE, ALWAYS);
+
+ if (opt_trans_madvise)
+ set_trans_opt(TRANS_ENABLE, MADVISE);
+
+ if (opt_trans_never)
+ set_trans_opt(TRANS_ENABLE, NEVER);
+
+ if (opt_khuge_pages)
+ set_trans_opt(KHUGE_SCAN_PAGES, khuge_pages);
+
+ if (opt_khuge_alloc)
+ set_trans_opt(KHUGE_ALLOC_SLEEP, khuge_alloc);
+
+ if (opt_khuge_scan)
+ set_trans_opt(KHUGE_SCAN_SLEEP, khuge_scan);
+
if (opt_set_recommended_minfreekbytes)
set_recommended_minfreekbytes();
diff --git a/man/hugeadm.8 b/man/hugeadm.8
index 0c577bc..28de91e 100644
--- a/man/hugeadm.8
+++ b/man/hugeadm.8
@@ -238,10 +238,45 @@ make the swap space persist after the resize operation is completed. The swap
spaces can later be removed manually using the swapoff command.
.PP
+The following options tune the transparent huge page usage
+
+.TP
+.B --thp-always
+
+Enable transparent huge pages always
+
+.TP
+.B --thp-madvise
+
+Enable transparent huge pages only on madvised regions
+
+.TP
+.B --thp-never
+
+Disable transparent huge pages
+
+.TP
+.B --thp-khugepaged-pages <pages to scan>
+
+Configure the number of pages that khugepaged should scan on each pass
+
+.TP
+.B --thp-khugepaged-scan-sleep <milliseconds>
+
+Configure how many milliseconds khugepaged should wait between passes
+
+.TP
+.B --thp-khugepages-alloc-sleep <milliseconds>
+
+Configure how many milliseconds khugepaged should wait after failing to
+allocate a huge page to throttle the next attempt.
+
+.PP
The following options affect the verbosity of libhugetlbfs.
.TP
.B --verbose <level>, -v
+
The default value for the verbosity level is 1 and the range of the value can
be set with --verbose from 0 to 99. The higher the value, the more verbose the
library will be. 0 is quiet and 3 will output much debugging information. The