|
Packit Service |
b439df |
/***************************************************************************
|
|
Packit Service |
b439df |
* User front end for using huge pages Copyright (C) 2008, IBM *
|
|
Packit Service |
b439df |
* *
|
|
Packit Service |
b439df |
* This program is free software; you can redistribute it and/or modify *
|
|
Packit Service |
b439df |
* it under the terms of the Lesser GNU General Public License as *
|
|
Packit Service |
b439df |
* published by the Free Software Foundation; either version 2.1 of the *
|
|
Packit Service |
b439df |
* License, or at your option) any later version. *
|
|
Packit Service |
b439df |
* *
|
|
Packit Service |
b439df |
* This program is distributed in the hope that it will be useful, *
|
|
Packit Service |
b439df |
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
Packit Service |
b439df |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
Packit Service |
b439df |
* GNU Lesser General Public License for more details. *
|
|
Packit Service |
b439df |
* *
|
|
Packit Service |
b439df |
* You should have received a copy of the Lesser GNU General Public *
|
|
Packit Service |
b439df |
* License along with this program; if not, write to the *
|
|
Packit Service |
b439df |
* Free Software Foundation, Inc., *
|
|
Packit Service |
b439df |
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
|
Packit Service |
b439df |
***************************************************************************/
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
/*
|
|
Packit Service |
b439df |
* hugeadm is designed to make an administrators life simpler, to automate
|
|
Packit Service |
b439df |
* and simplify basic system configuration as it relates to hugepages. It
|
|
Packit Service |
b439df |
* is designed to help with pool and mount configuration.
|
|
Packit Service |
b439df |
*/
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
#include <stdlib.h>
|
|
Packit Service |
b439df |
#include <stdio.h>
|
|
Packit Service |
b439df |
#include <errno.h>
|
|
Packit Service |
b439df |
#include <string.h>
|
|
Packit Service |
b439df |
#include <limits.h>
|
|
Packit Service |
b439df |
#include <mntent.h>
|
|
Packit Service |
b439df |
#include <unistd.h>
|
|
Packit Service |
b439df |
#include <grp.h>
|
|
Packit Service |
b439df |
#include <pwd.h>
|
|
Packit Service |
b439df |
#include <fcntl.h>
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
#include <sys/stat.h>
|
|
Packit Service |
b439df |
#include <sys/types.h>
|
|
Packit Service |
b439df |
#include <sys/mount.h>
|
|
Packit Service |
b439df |
#include <sys/swap.h>
|
|
Packit Service |
b439df |
#include <sys/wait.h>
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
#define _GNU_SOURCE /* for getopt_long */
|
|
Packit Service |
b439df |
#include <unistd.h>
|
|
Packit Service |
b439df |
#include <getopt.h>
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
#define KB (1024)
|
|
Packit Service |
b439df |
#define MB (1024*KB)
|
|
Packit Service |
b439df |
#define GB (1024*MB)
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
#define REPORT_UTIL "hugeadm"
|
|
Packit Service |
b439df |
#define REPORT(level, prefix, format, ...) \
|
|
Packit Service |
b439df |
do { \
|
|
Packit Service |
b439df |
if (verbose_level >= level) \
|
|
Packit Service |
b439df |
fprintf(stderr, "hugeadm:" prefix ": " format, \
|
|
Packit Service |
b439df |
##__VA_ARGS__); \
|
|
Packit Service |
b439df |
} while (0);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
#include "libhugetlbfs_internal.h"
|
|
Packit Service |
b439df |
#include "hugetlbfs.h"
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
extern int optind;
|
|
Packit Service |
b439df |
extern char *optarg;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
#define OPTION(opts, text) fprintf(stderr, " %-25s %s\n", opts, text)
|
|
Packit Service |
b439df |
#define CONT(text) fprintf(stderr, " %-25s %s\n", "", text)
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
#define MOUNT_DIR "/var/lib/hugetlbfs"
|
|
Packit Service |
b439df |
#define OPT_MAX 4096
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
#define PROCMOUNTS "/proc/mounts"
|
|
Packit Service |
b439df |
#define PROCHUGEPAGES_MOVABLE "/proc/sys/vm/hugepages_treat_as_movable"
|
|
Packit Service |
b439df |
#define PROCMINFREEKBYTES "/proc/sys/vm/min_free_kbytes"
|
|
Packit Service |
b439df |
#define PROCSHMMAX "/proc/sys/kernel/shmmax"
|
|
Packit Service |
b439df |
#define PROCHUGETLBGROUP "/proc/sys/vm/hugetlb_shm_group"
|
|
Packit Service |
b439df |
#define PROCZONEINFO "/proc/zoneinfo"
|
|
Packit Service |
b439df |
#define FS_NAME "hugetlbfs"
|
|
Packit Service |
b439df |
#define MIN_COL 20
|
|
Packit Service |
b439df |
#define MAX_SIZE_MNTENT (64 + PATH_MAX + 32 + 128 + 2 * sizeof(int))
|
|
Packit Service |
b439df |
#define FORMAT_LEN 20
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
#define MEM_TOTAL "MemTotal:"
|
|
Packit Service |
b439df |
#define SWAP_FREE "SwapFree:"
|
|
Packit Service |
b439df |
#define SWAP_TOTAL "SwapTotal:"
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
#define ALWAYS "always"
|
|
Packit Service |
b439df |
#define MADVISE "madvise"
|
|
Packit Service |
b439df |
#define NEVER "never"
|
|
Packit Service |
b439df |
#define TRANS_ENABLE "/sys/kernel/mm/transparent_hugepage/enabled"
|
|
Packit Service |
b439df |
#define KHUGE_SCAN_PAGES "/sys/kernel/mm/transparent_hugepage/khugepaged/pages_to_scan"
|
|
Packit Service |
b439df |
#define KHUGE_SCAN_SLEEP "/sys/kernel/mm/transparent_hugepage/khugepaged/scan_sleep_millisecs"
|
|
Packit Service |
b439df |
#define KHUGE_ALLOC_SLEEP "/sys/kernel/mm/transparent_hugepage/khugepaged/alloc_sleep_millisecs"
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
void print_usage()
|
|
Packit Service |
b439df |
{
|
|
Packit Service |
b439df |
fprintf(stderr, "hugeadm [options]\n");
|
|
Packit Service |
b439df |
fprintf(stderr, "options:\n");
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
OPTION("--list-all-mounts", "List all current hugetlbfs mount points");
|
|
Packit Service |
b439df |
OPTION("--pool-list", "List all pools");
|
|
Packit Service |
b439df |
OPTION("--hard", "specified with --pool-pages-min to make");
|
|
Packit Service |
b439df |
CONT("multiple attempts at adjusting the pool size to the");
|
|
Packit Service |
b439df |
CONT("specified count on failure");
|
|
Packit Service |
b439df |
OPTION("--pool-pages-min <size|DEFAULT>:[+|-]<pagecount|memsize<G|M|K>>", "");
|
|
Packit Service |
b439df |
CONT("Adjust pool 'size' lower bound");
|
|
Packit Service |
b439df |
OPTION("--obey-mempolicy", "Obey the NUMA memory policy when");
|
|
Packit Service |
b439df |
CONT("adjusting the pool 'size' lower bound");
|
|
Packit Service |
b439df |
OPTION("--thp-always", "Enable transparent huge pages always");
|
|
Packit Service |
b439df |
OPTION("--thp-madvise", "Enable transparent huge pages with madvise");
|
|
Packit Service |
b439df |
OPTION("--thp-never", "Disable transparent huge pages");
|
|
Packit Service |
b439df |
OPTION("--thp-khugepaged-pages <pages to scan>", "Number of pages that khugepaged");
|
|
Packit Service |
b439df |
CONT("should scan on each pass");
|
|
Packit Service |
b439df |
OPTION("--thp-khugepaged-scan-sleep <milliseconds>", "Time in ms to sleep between");
|
|
Packit Service |
b439df |
CONT("khugepaged passes");
|
|
Packit Service |
65d968 |
OPTION("--thp-khugepaged-alloc-sleep <milliseconds>", "Time in ms for khugepaged");
|
|
Packit Service |
b439df |
CONT("to wait if there was a huge page allocation failure");
|
|
Packit Service |
b439df |
OPTION("--pool-pages-max <size|DEFAULT>:[+|-]<pagecount|memsize<G|M|K>>", "");
|
|
Packit Service |
b439df |
CONT("Adjust pool 'size' upper bound");
|
|
Packit Service |
b439df |
OPTION("--set-recommended-min_free_kbytes", "");
|
|
Packit Service |
b439df |
CONT("Sets min_free_kbytes to a recommended value to improve availability of");
|
|
Packit Service |
b439df |
CONT("huge pages at runtime");
|
|
Packit Service |
b439df |
OPTION("--set-recommended-shmmax", "Sets shmmax to a recommended value to");
|
|
Packit Service |
b439df |
CONT("maximise the size possible for shared memory pools");
|
|
Packit Service |
b439df |
OPTION("--set-shm-group <gid|groupname>", "Sets hugetlb_shm_group to the");
|
|
Packit Service |
b439df |
CONT("specified group, which has permission to use hugetlb shared memory pools");
|
|
Packit Service |
b439df |
OPTION("--add-temp-swap[=count]", "Specified with --pool-pages-min to create");
|
|
Packit Service |
b439df |
CONT("temporary swap space for the duration of the pool resize. Default swap");
|
|
Packit Service |
b439df |
CONT("size is 5 huge pages. Optional arg sets size to 'count' huge pages");
|
|
Packit Service |
b439df |
OPTION("--add-ramdisk-swap", "Specified with --pool-pages-min to create");
|
|
Packit Service |
b439df |
CONT("swap space on ramdisks. By default, swap is removed after the resize.");
|
|
Packit Service |
b439df |
OPTION("--persist", "Specified with --add-temp-swap or --add-ramdisk-swap");
|
|
Packit Service |
b439df |
CONT("options to make swap space persist after the resize.");
|
|
Packit Service |
b439df |
OPTION("--enable-zone-movable", "Use ZONE_MOVABLE for huge pages");
|
|
Packit Service |
b439df |
OPTION("--disable-zone-movable", "Do not use ZONE_MOVABLE for huge pages");
|
|
Packit Service |
b439df |
OPTION("--create-mounts", "Creates a mount point for each available");
|
|
Packit Service |
b439df |
CONT("huge page size on this system under /var/lib/hugetlbfs");
|
|
Packit Service |
b439df |
OPTION("--create-user-mounts <user>", "");
|
|
Packit Service |
b439df |
CONT("Creates a mount point for each available huge");
|
|
Packit Service |
b439df |
CONT("page size under /var/lib/hugetlbfs/<user>");
|
|
Packit Service |
b439df |
CONT("usable by user <user>");
|
|
Packit Service |
b439df |
OPTION("--create-group-mounts <group>", "");
|
|
Packit Service |
b439df |
CONT("Creates a mount point for each available huge");
|
|
Packit Service |
b439df |
CONT("page size under /var/lib/hugetlbfs/<group>");
|
|
Packit Service |
b439df |
CONT("usable by group <group>");
|
|
Packit Service |
b439df |
OPTION("--create-global-mounts", "");
|
|
Packit Service |
b439df |
CONT("Creates a mount point for each available huge");
|
|
Packit Service |
b439df |
CONT("page size under /var/lib/hugetlbfs/global");
|
|
Packit Service |
b439df |
CONT("usable by anyone");
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
OPTION("--max-size <size<G|M|K>>", "Limit the filesystem size of a new mount point");
|
|
Packit Service |
b439df |
OPTION("--max-inodes <number>", "Limit the number of inodes on a new mount point");
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
OPTION("--page-sizes", "Display page sizes that a configured pool");
|
|
Packit Service |
b439df |
OPTION("--page-sizes-all",
|
|
Packit Service |
b439df |
"Display page sizes support by the hardware");
|
|
Packit Service |
b439df |
OPTION("--dry-run", "Print the equivalent shell commands for what");
|
|
Packit Service |
b439df |
CONT("the specified options would have done without");
|
|
Packit Service |
b439df |
CONT("taking any action");
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
OPTION("--explain", "Gives a overview of the status of the system");
|
|
Packit Service |
b439df |
CONT("with respect to huge page availability");
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
OPTION("--verbose <level>, -v", "Increases/sets tracing levels");
|
|
Packit Service |
b439df |
OPTION("--help, -h", "Prints this message");
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
int opt_dry_run = 0;
|
|
Packit Service |
b439df |
int opt_hard = 0;
|
|
Packit Service |
b439df |
int opt_movable = -1;
|
|
Packit Service |
b439df |
int opt_set_recommended_minfreekbytes = 0;
|
|
Packit Service |
b439df |
int opt_set_recommended_shmmax = 0;
|
|
Packit Service |
b439df |
int opt_set_hugetlb_shm_group = 0;
|
|
Packit Service |
b439df |
int opt_temp_swap = 0;
|
|
Packit Service |
b439df |
int opt_ramdisk_swap = 0;
|
|
Packit Service |
b439df |
int opt_swap_persist = 0;
|
|
Packit Service |
b439df |
int opt_obey_mempolicy = 0;
|
|
Packit Service |
b439df |
unsigned long opt_limit_mount_size = 0;
|
|
Packit Service |
b439df |
int opt_limit_mount_inodes = 0;
|
|
Packit Service |
b439df |
int verbose_level = VERBOSITY_DEFAULT;
|
|
Packit Service |
b439df |
char ramdisk_list[PATH_MAX] = "";
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
void setup_environment(char *var, char *val)
|
|
Packit Service |
b439df |
{
|
|
Packit Service |
b439df |
if (opt_dry_run) {
|
|
Packit Service |
b439df |
printf("%s='%s'\n", var, val);
|
|
Packit Service |
b439df |
return;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
setenv(var, val, 1);
|
|
Packit Service |
b439df |
DEBUG("%s='%s'\n", var, val);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
/* Enable/disable allocation of hugepages from ZONE_MOVABLE */
|
|
Packit Service |
b439df |
void setup_zone_movable(int able)
|
|
Packit Service |
b439df |
{
|
|
Packit Service |
b439df |
if (opt_dry_run) {
|
|
Packit Service |
b439df |
printf("echo %d > %s\n", able, PROCHUGEPAGES_MOVABLE);
|
|
Packit Service |
b439df |
return;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
DEBUG("Setting %s to %d\n", PROCHUGEPAGES_MOVABLE, able);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
/* libhugetlbfs reports any error that occurs */
|
|
Packit Service |
b439df |
file_write_ulong(PROCHUGEPAGES_MOVABLE, (unsigned long)able);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
void verbose_init(void)
|
|
Packit Service |
b439df |
{
|
|
Packit Service |
b439df |
char *env;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
env = getenv("HUGETLB_VERBOSE");
|
|
Packit Service |
b439df |
if (env)
|
|
Packit Service |
b439df |
verbose_level = atoi(env);
|
|
Packit Service |
b439df |
env = getenv("HUGETLB_DEBUG");
|
|
Packit Service |
b439df |
if (env)
|
|
Packit Service |
b439df |
verbose_level = VERBOSITY_MAX;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
void verbose(char *which)
|
|
Packit Service |
b439df |
{
|
|
Packit Service |
b439df |
int new_level;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (which) {
|
|
Packit Service |
b439df |
new_level = atoi(which);
|
|
Packit Service |
b439df |
if (new_level < 0 || new_level > 99) {
|
|
Packit Service |
b439df |
ERROR("%d: verbosity out of range 0-99\n",
|
|
Packit Service |
b439df |
new_level);
|
|
Packit Service |
b439df |
exit(EXIT_FAILURE);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
} else {
|
|
Packit Service |
b439df |
new_level = verbose_level + 1;
|
|
Packit Service |
b439df |
if (new_level == 100) {
|
|
Packit Service |
b439df |
WARNING("verbosity limited to 99\n");
|
|
Packit Service |
b439df |
new_level--;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
verbose_level = new_level;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
void verbose_expose(void)
|
|
Packit Service |
b439df |
{
|
|
Packit Service |
b439df |
char level[3];
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (verbose_level == 99) {
|
|
Packit Service |
b439df |
setup_environment("HUGETLB_DEBUG", "yes");
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
snprintf(level, sizeof(level), "%d", verbose_level);
|
|
Packit Service |
b439df |
setup_environment("HUGETLB_VERBOSE", level);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
/*
|
|
Packit Service |
b439df |
* getopts return values for options which are long only.
|
|
Packit Service |
b439df |
*/
|
|
Packit Service |
b439df |
#define LONG_POOL ('p' << 8)
|
|
Packit Service |
b439df |
#define LONG_POOL_LIST (LONG_POOL|'l')
|
|
Packit Service |
b439df |
#define LONG_POOL_MIN_ADJ (LONG_POOL|'m')
|
|
Packit Service |
b439df |
#define LONG_POOL_MAX_ADJ (LONG_POOL|'M')
|
|
Packit Service |
b439df |
#define LONG_POOL_MEMPOL (LONG_POOL|'p')
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
#define LONG_SET_RECOMMENDED_MINFREEKBYTES ('k' << 8)
|
|
Packit Service |
b439df |
#define LONG_SET_RECOMMENDED_SHMMAX ('x' << 8)
|
|
Packit Service |
b439df |
#define LONG_SET_HUGETLB_SHM_GROUP ('R' << 8)
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
#define LONG_MOVABLE ('z' << 8)
|
|
Packit Service |
b439df |
#define LONG_MOVABLE_ENABLE (LONG_MOVABLE|'e')
|
|
Packit Service |
b439df |
#define LONG_MOVABLE_DISABLE (LONG_MOVABLE|'d')
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
#define LONG_HARD ('h' << 8)
|
|
Packit Service |
b439df |
#define LONG_SWAP ('s' << 8)
|
|
Packit Service |
b439df |
#define LONG_SWAP_DISK (LONG_SWAP|'d')
|
|
Packit Service |
b439df |
#define LONG_SWAP_RAMDISK (LONG_SWAP|'r')
|
|
Packit Service |
b439df |
#define LONG_SWAP_PERSIST (LONG_SWAP|'p')
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
#define LONG_PAGE ('P' << 8)
|
|
Packit Service |
b439df |
#define LONG_PAGE_SIZES (LONG_PAGE|'s')
|
|
Packit Service |
b439df |
#define LONG_PAGE_AVAIL (LONG_PAGE|'a')
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
#define LONG_MOUNTS ('m' << 8)
|
|
Packit Service |
b439df |
#define LONG_CREATE_MOUNTS (LONG_MOUNTS|'C')
|
|
Packit Service |
b439df |
#define LONG_CREATE_USER_MOUNTS (LONG_MOUNTS|'U')
|
|
Packit Service |
b439df |
#define LONG_CREATE_GROUP_MOUNTS (LONG_MOUNTS|'g')
|
|
Packit Service |
b439df |
#define LONG_CREATE_GLOBAL_MOUNTS (LONG_MOUNTS|'G')
|
|
Packit Service |
b439df |
#define LONG_LIST_ALL_MOUNTS (LONG_MOUNTS|'A')
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
#define LONG_LIMITS ('l' << 8)
|
|
Packit Service |
b439df |
#define LONG_LIMIT_SIZE (LONG_LIMITS|'S')
|
|
Packit Service |
b439df |
#define LONG_LIMIT_INODES (LONG_LIMITS|'I')
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
#define LONG_EXPLAIN ('e' << 8)
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
#define LONG_TRANS ('t' << 8)
|
|
Packit Service |
b439df |
#define LONG_TRANS_ALWAYS (LONG_TRANS|'a')
|
|
Packit Service |
b439df |
#define LONG_TRANS_MADVISE (LONG_TRANS|'m')
|
|
Packit Service |
b439df |
#define LONG_TRANS_NEVER (LONG_TRANS|'n')
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
#define LONG_KHUGE ('K' << 8)
|
|
Packit Service |
b439df |
#define LONG_KHUGE_PAGES (LONG_KHUGE|'p')
|
|
Packit Service |
b439df |
#define LONG_KHUGE_SCAN (LONG_KHUGE|'s')
|
|
Packit Service |
b439df |
#define LONG_KHUGE_ALLOC (LONG_KHUGE|'a')
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
#define MAX_POOLS 32
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
static int cmpsizes(const void *p1, const void *p2)
|
|
Packit Service |
b439df |
{
|
|
Packit Service |
b439df |
return ((struct hpage_pool *)p1)->pagesize >
|
|
Packit Service |
b439df |
((struct hpage_pool *)p2)->pagesize;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
void pool_list(void)
|
|
Packit Service |
b439df |
{
|
|
Packit Service |
b439df |
struct hpage_pool pools[MAX_POOLS];
|
|
Packit Service |
b439df |
int pos;
|
|
Packit Service |
b439df |
int cnt;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
cnt = hpool_sizes(pools, MAX_POOLS);
|
|
Packit Service |
b439df |
if (cnt < 0) {
|
|
Packit Service |
b439df |
ERROR("unable to obtain pools list");
|
|
Packit Service |
b439df |
exit(EXIT_FAILURE);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
qsort(pools, cnt, sizeof(pools[0]), cmpsizes);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
printf("%10s %8s %8s %8s %8s\n",
|
|
Packit Service |
b439df |
"Size", "Minimum", "Current", "Maximum", "Default");
|
|
Packit Service |
b439df |
for (pos = 0; cnt--; pos++) {
|
|
Packit Service |
b439df |
printf("%10ld %8ld %8ld %8ld %8s\n", pools[pos].pagesize,
|
|
Packit Service |
b439df |
pools[pos].minimum, pools[pos].size,
|
|
Packit Service |
b439df |
pools[pos].maximum, (pools[pos].is_default) ? "*" : "");
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
struct mount_list
|
|
Packit Service |
b439df |
{
|
|
Packit Service |
b439df |
struct mntent entry;
|
|
Packit Service |
b439df |
char data[MAX_SIZE_MNTENT];
|
|
Packit Service |
b439df |
struct mount_list *next;
|
|
Packit Service |
b439df |
};
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
void print_mounts(struct mount_list *current, int longest)
|
|
Packit Service |
b439df |
{
|
|
Packit Service |
b439df |
char format_str[FORMAT_LEN];
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
snprintf(format_str, FORMAT_LEN, "%%-%ds %%s\n", longest);
|
|
Packit Service |
b439df |
printf(format_str, "Mount Point", "Options");
|
|
Packit Service |
b439df |
while (current) {
|
|
Packit Service |
b439df |
printf(format_str, current->entry.mnt_dir,
|
|
Packit Service |
b439df |
current->entry.mnt_opts);
|
|
Packit Service |
b439df |
current = current->next;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
/*
|
|
Packit Service |
b439df |
* collect_active_mounts returns a list of active hugetlbfs
|
|
Packit Service |
b439df |
* mount points, and, if longest is not NULL, the number of
|
|
Packit Service |
b439df |
* characters in the longest mount point to ease output
|
|
Packit Service |
b439df |
* formatting. Caller is expected to free the list of mounts.
|
|
Packit Service |
b439df |
*/
|
|
Packit Service |
b439df |
struct mount_list *collect_active_mounts(int *longest)
|
|
Packit Service |
b439df |
{
|
|
Packit Service |
b439df |
FILE *mounts;
|
|
Packit Service |
b439df |
struct mount_list *list, *current, *previous = NULL;
|
|
Packit Service |
b439df |
int length;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
/* First try /proc/mounts, then /etc/mtab */
|
|
Packit Service |
b439df |
mounts = setmntent(PROCMOUNTS, "r");
|
|
Packit Service |
b439df |
if (!mounts) {
|
|
Packit Service |
b439df |
mounts = setmntent(MOUNTED, "r");
|
|
Packit Service |
b439df |
if (!mounts) {
|
|
Packit Service |
b439df |
ERROR("unable to open %s or %s for reading",
|
|
Packit Service |
b439df |
PROCMOUNTS, MOUNTED);
|
|
Packit Service |
b439df |
exit(EXIT_FAILURE);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
list = malloc(sizeof(struct mount_list));
|
|
Packit Service |
b439df |
if (!list) {
|
|
Packit Service |
b439df |
ERROR("out of memory");
|
|
Packit Service |
b439df |
exit(EXIT_FAILURE);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
list->next = NULL;
|
|
Packit Service |
b439df |
current = list;
|
|
Packit Service |
b439df |
while (getmntent_r(mounts, &(current->entry), current->data, MAX_SIZE_MNTENT)) {
|
|
Packit Service |
b439df |
if (strcasecmp(current->entry.mnt_type, FS_NAME) == 0) {
|
|
Packit Service |
b439df |
length = strlen(current->entry.mnt_dir);
|
|
Packit Service |
b439df |
if (longest && length > *longest)
|
|
Packit Service |
b439df |
*longest = length;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
current->next = malloc(sizeof(struct mount_list));
|
|
Packit Service |
b439df |
if (!current->next) {
|
|
Packit Service |
b439df |
ERROR("out of memory");
|
|
Packit Service |
b439df |
exit(EXIT_FAILURE);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
previous = current;
|
|
Packit Service |
b439df |
current = current->next;
|
|
Packit Service |
b439df |
current->next = NULL;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
endmntent(mounts);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (previous) {
|
|
Packit Service |
b439df |
free(previous->next);
|
|
Packit Service |
b439df |
previous->next = NULL;
|
|
Packit Service |
b439df |
return list;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
return NULL;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
void mounts_list_all(void)
|
|
Packit Service |
b439df |
{
|
|
Packit Service |
b439df |
struct mount_list *list, *previous;
|
|
Packit Service |
b439df |
int longest = MIN_COL;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
list = collect_active_mounts(&longest);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (!list) {
|
|
Packit Service |
b439df |
ERROR("No hugetlbfs mount points found\n");
|
|
Packit Service |
b439df |
return;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
print_mounts(list, longest);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
while (list) {
|
|
Packit Service |
b439df |
previous = list;
|
|
Packit Service |
b439df |
list = list->next;
|
|
Packit Service |
b439df |
free(previous);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
int make_dir(char *path, mode_t mode, uid_t uid, gid_t gid)
|
|
Packit Service |
b439df |
{
|
|
Packit Service |
b439df |
struct passwd *pwd;
|
|
Packit Service |
b439df |
struct group *grp;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (opt_dry_run) {
|
|
Packit Service |
b439df |
pwd = getpwuid(uid);
|
|
Packit Service |
b439df |
grp = getgrgid(gid);
|
|
Packit Service |
b439df |
printf("if [ ! -e %s ]\n", path);
|
|
Packit Service |
b439df |
printf("then\n");
|
|
Packit Service |
b439df |
printf(" mkdir %s\n", path);
|
|
Packit Service |
b439df |
printf(" chown %s:%s %s\n", pwd->pw_name, grp->gr_name, path);
|
|
Packit Service |
b439df |
printf(" chmod %o %s\n", mode, path);
|
|
Packit Service |
b439df |
printf("fi\n");
|
|
Packit Service |
b439df |
return 0;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (mkdir(path, mode)) {
|
|
Packit Service |
b439df |
if (errno != EEXIST) {
|
|
Packit Service |
b439df |
ERROR("Unable to create dir %s, error: %s\n",
|
|
Packit Service |
b439df |
path, strerror(errno));
|
|
Packit Service |
b439df |
return 1;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
} else {
|
|
Packit Service |
b439df |
if (chown(path, uid, gid)) {
|
|
Packit Service |
b439df |
ERROR("Unable to change ownership of %s, error: %s\n",
|
|
Packit Service |
b439df |
path, strerror(errno));
|
|
Packit Service |
b439df |
return 1;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (chmod(path, mode)) {
|
|
Packit Service |
b439df |
ERROR("Unable to change permission on %s, error: %s\n",
|
|
Packit Service |
b439df |
path, strerror(errno));
|
|
Packit Service |
b439df |
return 1;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
return 0;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
/**
|
|
Packit Service |
b439df |
* ensure_dir will build the entire directory structure up to and
|
|
Packit Service |
b439df |
* including path, all directories built will be owned by
|
|
Packit Service |
b439df |
* user:group and permissions will be set to mode.
|
|
Packit Service |
b439df |
*/
|
|
Packit Service |
b439df |
int ensure_dir(char *path, mode_t mode, uid_t uid, gid_t gid)
|
|
Packit Service |
b439df |
{
|
|
Packit Service |
b439df |
char *idx;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (!path || strlen(path) == 0)
|
|
Packit Service |
b439df |
return 0;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
idx = strchr(path + 1, '/');
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
do {
|
|
Packit Service |
b439df |
if (idx)
|
|
Packit Service |
b439df |
*idx = '\0';
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (make_dir(path, mode, uid, gid))
|
|
Packit Service |
b439df |
return 1;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (idx) {
|
|
Packit Service |
b439df |
*idx = '/';
|
|
Packit Service |
b439df |
idx++;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
} while ((idx = strchr(idx, '/')) != NULL);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (make_dir(path, mode, uid, gid))
|
|
Packit Service |
b439df |
return 1;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
return 0;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
int check_if_already_mounted(struct mount_list *list, char *path)
|
|
Packit Service |
b439df |
{
|
|
Packit Service |
b439df |
while (list) {
|
|
Packit Service |
b439df |
if (!strcmp(list->entry.mnt_dir, path))
|
|
Packit Service |
b439df |
return 1;
|
|
Packit Service |
b439df |
list = list->next;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
return 0;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
int mount_dir(char *path, char *options, mode_t mode, uid_t uid, gid_t gid)
|
|
Packit Service |
b439df |
{
|
|
Packit Service |
b439df |
struct passwd *pwd;
|
|
Packit Service |
b439df |
struct group *grp;
|
|
Packit Service |
b439df |
struct mntent entry;
|
|
Packit Service |
b439df |
FILE *mounts;
|
|
Packit Service |
b439df |
char dummy;
|
|
Packit Service |
b439df |
int useMtab;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
struct mount_list *list, *previous;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
list = collect_active_mounts(NULL);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (list && check_if_already_mounted(list, path)) {
|
|
Packit Service |
b439df |
WARNING("Directory %s is already mounted.\n", path);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
while (list) {
|
|
Packit Service |
b439df |
previous = list;
|
|
Packit Service |
b439df |
list = list->next;
|
|
Packit Service |
b439df |
free(previous);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
return 0;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
while (list) {
|
|
Packit Service |
b439df |
previous = list;
|
|
Packit Service |
b439df |
list = list->next;
|
|
Packit Service |
b439df |
free(previous);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (opt_dry_run) {
|
|
Packit Service |
b439df |
pwd = getpwuid(uid);
|
|
Packit Service |
b439df |
grp = getgrgid(gid);
|
|
Packit Service |
b439df |
printf("mount -t %s none %s -o %s\n", FS_NAME,
|
|
Packit Service |
b439df |
path, options);
|
|
Packit Service |
b439df |
printf("chown %s:%s %s\n", pwd->pw_name, grp->gr_name,
|
|
Packit Service |
b439df |
path);
|
|
Packit Service |
b439df |
printf("chmod %o %s\n", mode, path);
|
|
Packit Service |
b439df |
} else {
|
|
Packit Service |
b439df |
if (mount("none", path, FS_NAME, 0, options)) {
|
|
Packit Service |
b439df |
ERROR("Unable to mount %s, error: %s\n",
|
|
Packit Service |
b439df |
path, strerror(errno));
|
|
Packit Service |
b439df |
return 1;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
/* Check if mtab is a symlink */
|
|
Packit Service |
b439df |
useMtab = (readlink(MOUNTED, &dummy, 1) < 0);
|
|
Packit Service |
b439df |
if (useMtab) {
|
|
Packit Service |
b439df |
mounts = setmntent(MOUNTED, "a+");
|
|
Packit Service |
b439df |
if (mounts) {
|
|
Packit Service |
b439df |
entry.mnt_fsname = FS_NAME;
|
|
Packit Service |
b439df |
entry.mnt_dir = path;
|
|
Packit Service |
b439df |
entry.mnt_type = FS_NAME;
|
|
Packit Service |
b439df |
entry.mnt_opts = options;
|
|
Packit Service |
b439df |
entry.mnt_freq = 0;
|
|
Packit Service |
b439df |
entry.mnt_passno = 0;
|
|
Packit Service |
b439df |
if (addmntent(mounts, &entry))
|
|
Packit Service |
b439df |
WARNING("Unable to add entry %s to %s, error: %s\n",
|
|
Packit Service |
b439df |
path, MOUNTED, strerror(errno));
|
|
Packit Service |
b439df |
endmntent(mounts);
|
|
Packit Service |
b439df |
} else {
|
|
Packit Service |
b439df |
WARNING("Unable to open %s, error: %s\n",
|
|
Packit Service |
b439df |
MOUNTED, strerror(errno));
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (chown(path, uid, gid)) {
|
|
Packit Service |
b439df |
ERROR("Unable to change ownership of %s, error: %s\n",
|
|
Packit Service |
b439df |
path, strerror(errno));
|
|
Packit Service |
b439df |
return 1;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (chmod(path, mode)) {
|
|
Packit Service |
b439df |
ERROR("Unable to set permissions on %s, error: %s\n",
|
|
Packit Service |
b439df |
path, strerror(errno));
|
|
Packit Service |
b439df |
return 1;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
return 0;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
void scale_size(char *buf, unsigned long pagesize)
|
|
Packit Service |
b439df |
{
|
|
Packit Service |
b439df |
if(pagesize >= GB)
|
|
Packit Service |
b439df |
snprintf(buf, OPT_MAX, "%luGB", pagesize / GB);
|
|
Packit Service |
b439df |
else if(pagesize >= MB)
|
|
Packit Service |
b439df |
snprintf(buf, OPT_MAX, "%luMB", pagesize / MB);
|
|
Packit Service |
b439df |
else
|
|
Packit Service |
b439df |
snprintf(buf, OPT_MAX, "%luKB", pagesize / KB);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
void create_mounts(char *user, char *group, char *base, mode_t mode)
|
|
Packit Service |
b439df |
{
|
|
Packit Service |
b439df |
struct hpage_pool pools[MAX_POOLS];
|
|
Packit Service |
b439df |
char path[PATH_MAX];
|
|
Packit Service |
b439df |
char options[OPT_MAX];
|
|
Packit Service |
b439df |
char limits[OPT_MAX];
|
|
Packit Service |
b439df |
char scaled[OPT_MAX];
|
|
Packit Service |
b439df |
int cnt, pos;
|
|
Packit Service |
b439df |
struct passwd *pwd;
|
|
Packit Service |
b439df |
struct group *grp;
|
|
Packit Service |
b439df |
uid_t uid = 0;
|
|
Packit Service |
b439df |
gid_t gid = 0;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (geteuid() != 0) {
|
|
Packit Service |
b439df |
ERROR("Mounts can only be created by root\n");
|
|
Packit Service |
b439df |
exit(EXIT_FAILURE);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (user) {
|
|
Packit Service |
b439df |
pwd = getpwnam(user);
|
|
Packit Service |
b439df |
if (!pwd) {
|
|
Packit Service |
b439df |
ERROR("Could not find specified user %s\n", user);
|
|
Packit Service |
b439df |
exit(EXIT_FAILURE);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
uid = pwd->pw_uid;
|
|
Packit Service |
b439df |
} else if (group) {
|
|
Packit Service |
b439df |
grp = getgrnam(group);
|
|
Packit Service |
b439df |
if (!grp) {
|
|
Packit Service |
b439df |
ERROR("Could not find specified group %s\n", group);
|
|
Packit Service |
b439df |
exit(EXIT_FAILURE);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
gid = grp->gr_gid;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (ensure_dir(base,
|
|
Packit Service |
b439df |
S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH, 0, 0))
|
|
Packit Service |
b439df |
exit(EXIT_FAILURE);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
cnt = hpool_sizes(pools, MAX_POOLS);
|
|
Packit Service |
b439df |
if (cnt < 0) {
|
|
Packit Service |
b439df |
ERROR("Unable to obtain pools list\n");
|
|
Packit Service |
b439df |
exit(EXIT_FAILURE);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
for (pos=0; cnt--; pos++) {
|
|
Packit Service |
b439df |
scaled[0] = 0;
|
|
Packit Service |
b439df |
scale_size(scaled, pools[pos].pagesize);
|
|
Packit Service |
b439df |
if (user)
|
|
Packit Service |
b439df |
snprintf(path, PATH_MAX, "%s/%s/pagesize-%s",
|
|
Packit Service |
b439df |
base, user, scaled);
|
|
Packit Service |
b439df |
else if (group)
|
|
Packit Service |
b439df |
snprintf(path, PATH_MAX, "%s/%s/pagesize-%s",
|
|
Packit Service |
b439df |
base, group, scaled);
|
|
Packit Service |
b439df |
else
|
|
Packit Service |
b439df |
snprintf(path, PATH_MAX, "%s/pagesize-%s",
|
|
Packit Service |
b439df |
base, scaled);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
snprintf(options, OPT_MAX, "pagesize=%ld",
|
|
Packit Service |
b439df |
pools[pos].pagesize);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
/* Yes, this could be cleverer */
|
|
Packit Service |
b439df |
if (opt_limit_mount_size && opt_limit_mount_inodes)
|
|
Packit Service |
b439df |
snprintf(limits, OPT_MAX, ",size=%lu,nr_inodes=%d",
|
|
Packit Service |
b439df |
opt_limit_mount_size, opt_limit_mount_inodes);
|
|
Packit Service |
b439df |
else {
|
|
Packit Service |
b439df |
if (opt_limit_mount_size)
|
|
Packit Service |
b439df |
snprintf(limits, OPT_MAX, ",size=%lu",
|
|
Packit Service |
b439df |
opt_limit_mount_size);
|
|
Packit Service |
b439df |
if (opt_limit_mount_inodes)
|
|
Packit Service |
b439df |
snprintf(limits, OPT_MAX, ",nr_inodes=%d",
|
|
Packit Service |
b439df |
opt_limit_mount_inodes);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
/* Append limits if specified */
|
|
Packit Service |
b439df |
if (limits[0] != 0) {
|
|
Packit Service |
b439df |
size_t maxlen = OPT_MAX - strlen(options);
|
|
Packit Service |
b439df |
if (maxlen > strlen(limits))
|
|
Packit Service |
b439df |
strcat(options, limits);
|
|
Packit Service |
b439df |
else
|
|
Packit Service |
b439df |
WARNING("String limitations met, cannot append limitations onto mount options string. Increase OPT_MAX");
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (ensure_dir(path, mode, uid, gid))
|
|
Packit Service |
b439df |
exit(EXIT_FAILURE);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (mount_dir(path, options, mode, uid, gid))
|
|
Packit Service |
b439df |
exit(EXIT_FAILURE);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
/**
|
|
Packit Service |
b439df |
* show_mem shouldn't change the behavior of any of its
|
|
Packit Service |
b439df |
* callers, it only prints a message to the user showing the
|
|
Packit Service |
b439df |
* total amount of memory in the system (in megabytes).
|
|
Packit Service |
b439df |
*/
|
|
Packit Service |
b439df |
void show_mem()
|
|
Packit Service |
b439df |
{
|
|
Packit Service |
b439df |
long mem_total;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
mem_total = read_meminfo(MEM_TOTAL);
|
|
Packit Service |
b439df |
printf("Total System Memory: %ld MB\n\n", mem_total / 1024);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
/**
|
|
Packit Service |
b439df |
* check_swap shouldn't change the behavior of any of its
|
|
Packit Service |
b439df |
* callers, it only prints a message to the user if something
|
|
Packit Service |
b439df |
* is being done that might fail without swap available. i.e.
|
|
Packit Service |
b439df |
* resizing a huge page pool
|
|
Packit Service |
b439df |
*/
|
|
Packit Service |
b439df |
void check_swap()
|
|
Packit Service |
b439df |
{
|
|
Packit Service |
b439df |
long swap_sz;
|
|
Packit Service |
b439df |
long swap_total;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
swap_total = read_meminfo(SWAP_TOTAL);
|
|
Packit Service |
b439df |
if (swap_total <= 0) {
|
|
Packit Service |
b439df |
WARNING("There is no swap space configured, resizing hugepage pool may fail\n");
|
|
Packit Service |
b439df |
WARNING("Use --add-temp-swap option to temporarily add swap during the resize\n");
|
|
Packit Service |
b439df |
return;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
swap_sz = read_meminfo(SWAP_FREE);
|
|
Packit Service |
b439df |
/* meminfo keeps values in kb, but we use bytes for hpage sizes */
|
|
Packit Service |
b439df |
swap_sz *= 1024;
|
|
Packit Service |
b439df |
if (swap_sz <= gethugepagesize()) {
|
|
Packit Service |
b439df |
WARNING("There is very little swap space free, resizing hugepage pool may fail\n");
|
|
Packit Service |
b439df |
WARNING("Use --add-temp-swap option to temporarily add swap during the resize\n");
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
#define ZONEINFO_LINEBUF 1024
|
|
Packit Service |
b439df |
long recommended_minfreekbytes(void)
|
|
Packit Service |
b439df |
{
|
|
Packit Service |
b439df |
FILE *f;
|
|
Packit Service |
b439df |
char buf[ZONEINFO_LINEBUF];
|
|
Packit Service |
b439df |
int nr_zones = 0;
|
|
Packit Service |
b439df |
long recommended_min;
|
|
Packit Service |
b439df |
long pageblock_kbytes = kernel_default_hugepage_size() / 1024;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
/* Detect the number of zones in the system */
|
|
Packit Service |
b439df |
f = fopen(PROCZONEINFO, "r");
|
|
Packit Service |
b439df |
if (f == NULL) {
|
|
Packit Service |
b439df |
WARNING("Unable to open " PROCZONEINFO);
|
|
Packit Service |
b439df |
return 0;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
while (fgets(buf, ZONEINFO_LINEBUF, f) != NULL) {
|
|
Packit Service |
b439df |
if (strncmp(buf, "Node ", 5) == 0)
|
|
Packit Service |
b439df |
nr_zones++;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
fclose(f);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
/* Make sure at least 2 pageblocks are free for MIGRATE_RESERVE */
|
|
Packit Service |
b439df |
recommended_min = pageblock_kbytes * nr_zones * 2;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
/*
|
|
Packit Service |
b439df |
* Make sure that on average at least two pageblocks are almost free
|
|
Packit Service |
b439df |
* of another type, one for a migratetype to fall back to and a
|
|
Packit Service |
b439df |
* second to avoid subsequent fallbacks of other types There are 3
|
|
Packit Service |
b439df |
* MIGRATE_TYPES we care about.
|
|
Packit Service |
b439df |
*/
|
|
Packit Service |
b439df |
recommended_min += pageblock_kbytes * nr_zones * 3 * 3;
|
|
Packit Service |
b439df |
return recommended_min;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
void set_recommended_minfreekbytes(void)
|
|
Packit Service |
b439df |
{
|
|
Packit Service |
b439df |
long recommended_min = recommended_minfreekbytes();
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (opt_dry_run) {
|
|
Packit Service |
b439df |
printf("echo \"%ld\" > %s\n", recommended_min,
|
|
Packit Service |
b439df |
PROCMINFREEKBYTES);
|
|
Packit Service |
b439df |
return;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
DEBUG("Setting min_free_kbytes to %ld\n", recommended_min);
|
|
Packit Service |
b439df |
file_write_ulong(PROCMINFREEKBYTES, (unsigned long)recommended_min);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
/*
|
|
Packit Service |
b439df |
* check_minfreekbytes does not alter the value of min_free_kbytes. It just
|
|
Packit Service |
b439df |
* reports what the current value is and what it should be
|
|
Packit Service |
b439df |
*/
|
|
Packit Service |
b439df |
void check_minfreekbytes(void)
|
|
Packit Service |
b439df |
{
|
|
Packit Service |
b439df |
long min_free_kbytes = file_read_ulong(PROCMINFREEKBYTES, NULL);
|
|
Packit Service |
b439df |
long recommended_min = recommended_minfreekbytes();
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
/* There should be at least one pageblock free per zone in the system */
|
|
Packit Service |
b439df |
if (recommended_min > min_free_kbytes) {
|
|
Packit Service |
b439df |
printf("\n");
|
|
Packit Service |
b439df |
printf("The " PROCMINFREEKBYTES " of %ld is too small. To maximiuse efficiency\n", min_free_kbytes);
|
|
Packit Service |
b439df |
printf("of fragmentation avoidance, there should be at least one huge page free per zone\n");
|
|
Packit Service |
b439df |
printf("in the system which minimally requires a min_free_kbytes value of %ld\n", recommended_min);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
unsigned long long recommended_shmmax(void)
|
|
Packit Service |
b439df |
{
|
|
Packit Service |
b439df |
struct hpage_pool pools[MAX_POOLS];
|
|
Packit Service |
b439df |
unsigned long long recommended_shmmax = 0;
|
|
Packit Service |
b439df |
int pos, cnt;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
cnt = hpool_sizes(pools, MAX_POOLS);
|
|
Packit Service |
b439df |
if (cnt < 0) {
|
|
Packit Service |
b439df |
ERROR("unable to obtain pools list");
|
|
Packit Service |
b439df |
exit(EXIT_FAILURE);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
for (pos = 0; cnt--; pos++)
|
|
Packit Service |
b439df |
recommended_shmmax += ((unsigned long long)pools[pos].maximum *
|
|
Packit Service |
b439df |
pools[pos].pagesize);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
return recommended_shmmax;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
void set_recommended_shmmax(void)
|
|
Packit Service |
b439df |
{
|
|
Packit Service |
b439df |
int ret;
|
|
Packit Service |
b439df |
unsigned long max_recommended = -1UL;
|
|
Packit Service |
b439df |
unsigned long long recommended = recommended_shmmax();
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (recommended == 0) {
|
|
Packit Service |
b439df |
printf("\n");
|
|
Packit Service |
b439df |
WARNING("We can only set a recommended shmmax when huge pages are configured!\n");
|
|
Packit Service |
b439df |
return;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (recommended > max_recommended)
|
|
Packit Service |
b439df |
recommended = max_recommended;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
DEBUG("Setting shmmax to %llu\n", recommended);
|
|
Packit Service |
b439df |
ret = file_write_ulong(PROCSHMMAX, (unsigned long)recommended);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (!ret) {
|
|
Packit Service |
b439df |
INFO("To make shmmax settings persistent, add the following line to /etc/sysctl.conf:\n");
|
|
Packit Service |
b439df |
INFO(" kernel.shmmax = %llu\n", recommended);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
void check_shmmax(void)
|
|
Packit Service |
b439df |
{
|
|
Packit Service |
b439df |
long current_shmmax = file_read_ulong(PROCSHMMAX, NULL);
|
|
Packit Service |
b439df |
long recommended = recommended_shmmax();
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (current_shmmax != recommended) {
|
|
Packit Service |
b439df |
printf("\n");
|
|
Packit Service |
b439df |
printf("A " PROCSHMMAX " value of %ld bytes may be sub-optimal. To maximise\n", current_shmmax);
|
|
Packit Service |
b439df |
printf("shared memory usage, this should be set to the size of the largest shared memory\n");
|
|
Packit Service |
b439df |
printf("segment size you want to be able to use. Alternatively, set it to a size matching\n");
|
|
Packit Service |
b439df |
printf("the maximum possible allocation size of all huge pages. This can be done\n");
|
|
Packit Service |
b439df |
printf("automatically, using the --set-recommended-shmmax option.\n");
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (recommended == 0) {
|
|
Packit Service |
b439df |
printf("\n");
|
|
Packit Service |
b439df |
WARNING("We can't make a shmmax recommendation until huge pages are configured!\n");
|
|
Packit Service |
b439df |
return;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
printf("\n");
|
|
Packit Service |
b439df |
printf("The recommended shmmax for your currently allocated huge pages is %ld bytes.\n", recommended);
|
|
Packit Service |
b439df |
printf("To make shmmax settings persistent, add the following line to /etc/sysctl.conf:\n");
|
|
Packit Service |
b439df |
printf(" kernel.shmmax = %ld\n", recommended);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
void set_hugetlb_shm_group(gid_t gid, char *group)
|
|
Packit Service |
b439df |
{
|
|
Packit Service |
b439df |
int ret;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
DEBUG("Setting hugetlb_shm_group to %d (%s)\n", gid, group);
|
|
Packit Service |
b439df |
ret = file_write_ulong(PROCHUGETLBGROUP, (unsigned long)gid);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (!ret) {
|
|
Packit Service |
b439df |
INFO("To make hugetlb_shm_group settings persistent, add the following line to /etc/sysctl.conf:\n");
|
|
Packit Service |
b439df |
INFO(" vm.hugetlb_shm_group = %d\n", gid);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
/* heisted from shadow-utils/libmisc/list.c::is_on_list() */
|
|
Packit Service |
b439df |
static int user_in_group(char *const *list, const char *member)
|
|
Packit Service |
b439df |
{
|
|
Packit Service |
b439df |
while (*list != NULL) {
|
|
Packit Service |
b439df |
if (strcmp(*list, member) == 0) {
|
|
Packit Service |
b439df |
return 1;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
list++;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
return 0;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
void check_user(void)
|
|
Packit Service |
b439df |
{
|
|
Packit Service |
b439df |
uid_t uid;
|
|
Packit Service |
b439df |
gid_t gid;
|
|
Packit Service |
b439df |
struct passwd *pwd;
|
|
Packit Service |
b439df |
struct group *grp;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
gid = (gid_t)file_read_ulong(PROCHUGETLBGROUP, NULL);
|
|
Packit Service |
b439df |
grp = getgrgid(gid);
|
|
Packit Service |
b439df |
if (!grp) {
|
|
Packit Service |
b439df |
printf("\n");
|
|
Packit Service |
b439df |
WARNING("Group ID %d in hugetlb_shm_group doesn't appear to be a valid group!\n", gid);
|
|
Packit Service |
b439df |
return;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
uid = getuid();
|
|
Packit Service |
b439df |
pwd = getpwuid(uid);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
/* Don't segfault if user does not have a passwd entry. */
|
|
Packit Service |
b439df |
if (!pwd) {
|
|
Packit Service |
b439df |
printf("\n");
|
|
Packit Service |
b439df |
WARNING("User uid %d is not in the password file!\n", uid);
|
|
Packit Service |
b439df |
return;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (gid != pwd->pw_gid && !user_in_group(grp->gr_mem, pwd->pw_name) && uid != 0) {
|
|
Packit Service |
b439df |
printf("\n");
|
|
Packit Service |
b439df |
WARNING("User %s (uid: %d) is not a member of the hugetlb_shm_group %s (gid: %d)!\n", pwd->pw_name, uid, grp->gr_name, gid);
|
|
Packit Service |
b439df |
} else {
|
|
Packit Service |
b439df |
printf("\n");
|
|
Packit Service |
b439df |
printf("To make your hugetlb_shm_group settings persistent, add the following line to /etc/sysctl.conf:\n");
|
|
Packit Service |
b439df |
printf(" vm.hugetlb_shm_group = %d\n", gid);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
void add_temp_swap(long page_size)
|
|
Packit Service |
b439df |
{
|
|
Packit Service |
b439df |
char path[PATH_MAX];
|
|
Packit Service |
b439df |
char file[PATH_MAX];
|
|
Packit Service |
b439df |
char mkswap_cmd[PATH_MAX];
|
|
Packit Service |
b439df |
FILE *f;
|
|
Packit Service |
b439df |
char *buf;
|
|
Packit Service |
b439df |
long swap_size;
|
|
Packit Service |
b439df |
long pid;
|
|
Packit Service |
b439df |
int ret;
|
|
Packit Service |
b439df |
int num_pages;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (geteuid() != 0) {
|
|
Packit Service |
b439df |
ERROR("Swap can only be manipulated by root\n");
|
|
Packit Service |
b439df |
exit(EXIT_FAILURE);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
pid = getpid();
|
|
Packit Service |
b439df |
snprintf(path, PATH_MAX, "%s/swap/temp", MOUNT_DIR);
|
|
Packit Service |
b439df |
snprintf(file, PATH_MAX, "%s/swapfile-%ld", path, pid);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
/* swapsize is 5 hugepages */
|
|
Packit Service |
b439df |
if (opt_temp_swap == -1)
|
|
Packit Service |
b439df |
num_pages = 5;
|
|
Packit Service |
b439df |
else
|
|
Packit Service |
b439df |
num_pages = opt_temp_swap;
|
|
Packit Service |
b439df |
swap_size = num_pages * page_size;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (ensure_dir(path, S_IRWXU | S_IRGRP | S_IXGRP, 0, 0))
|
|
Packit Service |
b439df |
exit(EXIT_FAILURE);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (opt_dry_run) {
|
|
Packit Service |
b439df |
printf("dd bs=1024 count=%ld if=/dev/zero of=%s\n",
|
|
Packit Service |
b439df |
swap_size / 1024, file);
|
|
Packit Service |
b439df |
printf("mkswap %s\nswapon %s\n", file, file);
|
|
Packit Service |
b439df |
return;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
f = fopen(file, "wx");
|
|
Packit Service |
b439df |
if (!f) {
|
|
Packit Service |
b439df |
WARNING("Couldn't open %s: %s\n", file, strerror(errno));
|
|
Packit Service |
b439df |
opt_temp_swap = 0;
|
|
Packit Service |
b439df |
return;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
buf = malloc(swap_size);
|
|
Packit Service |
b439df |
memset(buf, 0, swap_size);
|
|
Packit Service |
b439df |
fwrite(buf, sizeof(char), swap_size, f);
|
|
Packit Service |
b439df |
free(buf);
|
|
Packit Service |
b439df |
fclose(f);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
snprintf(mkswap_cmd, PATH_MAX, "mkswap %s", file);
|
|
Packit Service |
b439df |
ret = system(mkswap_cmd);
|
|
Packit Service |
b439df |
if (WIFSIGNALED(ret)) {
|
|
Packit Service |
b439df |
WARNING("Call to mkswap failed\n");
|
|
Packit Service |
b439df |
opt_temp_swap = 0;
|
|
Packit Service |
b439df |
return;
|
|
Packit Service |
b439df |
} else if (WIFEXITED(ret)) {
|
|
Packit Service |
b439df |
ret = WEXITSTATUS(ret);
|
|
Packit Service |
b439df |
if (ret) {
|
|
Packit Service |
b439df |
WARNING("Call to mkswap failed\n");
|
|
Packit Service |
b439df |
opt_temp_swap = 0;
|
|
Packit Service |
b439df |
return;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
DEBUG("swapon %s\n", file);
|
|
Packit Service |
b439df |
if (swapon(file, 0)) {
|
|
Packit Service |
b439df |
WARNING("swapon on %s failed: %s\n", file, strerror(errno));
|
|
Packit Service |
b439df |
opt_temp_swap = 0;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
void rem_temp_swap() {
|
|
Packit Service |
b439df |
char file[PATH_MAX];
|
|
Packit Service |
b439df |
long pid;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
pid = getpid();
|
|
Packit Service |
b439df |
snprintf(file, PATH_MAX, "%s/swap/temp/swapfile-%ld", MOUNT_DIR, pid);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (opt_dry_run) {
|
|
Packit Service |
b439df |
printf("swapoff %s\nrm -f %s\n", file, file);
|
|
Packit Service |
b439df |
return;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (swapoff(file))
|
|
Packit Service |
b439df |
WARNING("swapoff on %s failed: %s\n", file, strerror(errno));
|
|
Packit Service |
b439df |
remove(file);
|
|
Packit Service |
b439df |
DEBUG("swapoff %s\n", file);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
void add_ramdisk_swap(long page_size) {
|
|
Packit Service |
b439df |
char ramdisk[PATH_MAX];
|
|
Packit Service |
b439df |
char mkswap_cmd[PATH_MAX];
|
|
Packit Service |
b439df |
int disk_num=0;
|
|
Packit Service |
b439df |
int count = 0;
|
|
Packit Service |
b439df |
long ramdisk_size;
|
|
Packit Service |
b439df |
int ret;
|
|
Packit Service |
b439df |
int fd;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
snprintf(ramdisk, PATH_MAX, "/dev/ram%i", disk_num);
|
|
Packit Service |
b439df |
fd = open(ramdisk, O_RDONLY);
|
|
Packit Service |
b439df |
ioctl(fd, BLKGETSIZE, &ramdisk_size);
|
|
Packit Service |
b439df |
close(fd);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
ramdisk_size = ramdisk_size * 512;
|
|
Packit Service |
b439df |
count = (page_size/ramdisk_size) + 1;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (count > 1) {
|
|
Packit Service |
b439df |
INFO("Swap will be initialized on multiple ramdisks because\n\
|
|
Packit Service |
b439df |
ramdisk size is less than huge page size. To avoid\n\
|
|
Packit Service |
b439df |
this in the future, use kernel command line parameter\n\
|
|
Packit Service |
b439df |
ramdisk_size=N, to set ramdisk size to N blocks.\n");
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
while (count > 0) {
|
|
Packit Service |
b439df |
snprintf(ramdisk, PATH_MAX, "/dev/ram%i", disk_num);
|
|
Packit Service |
b439df |
if (access(ramdisk, F_OK) != 0){
|
|
Packit Service |
b439df |
break;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
disk_num++;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (opt_dry_run) {
|
|
Packit Service |
b439df |
printf("mkswap %s\nswapon %s\n", ramdisk, ramdisk);
|
|
Packit Service |
b439df |
} else {
|
|
Packit Service |
b439df |
snprintf(mkswap_cmd, PATH_MAX, "mkswap %s", ramdisk);
|
|
Packit Service |
b439df |
ret = system(mkswap_cmd);
|
|
Packit Service |
b439df |
if (WIFSIGNALED(ret)) {
|
|
Packit Service |
b439df |
WARNING("Call to mkswap failed\n");
|
|
Packit Service |
b439df |
continue;
|
|
Packit Service |
b439df |
} else if (WIFEXITED(ret)) {
|
|
Packit Service |
b439df |
ret = WEXITSTATUS(ret);
|
|
Packit Service |
b439df |
if (ret) {
|
|
Packit Service |
b439df |
WARNING("Call to mkswap failed\n");
|
|
Packit Service |
b439df |
continue;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
DEBUG("swapon %s\n", ramdisk);
|
|
Packit Service |
b439df |
if (swapon(ramdisk, 0)) {
|
|
Packit Service |
b439df |
WARNING("swapon on %s failed: %s\n", ramdisk, strerror(errno));
|
|
Packit Service |
b439df |
opt_temp_swap = 0;
|
|
Packit Service |
b439df |
continue;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
count--;
|
|
Packit Service |
b439df |
strcat(ramdisk_list, " ");
|
|
Packit Service |
b439df |
strcat(ramdisk_list, ramdisk);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
void rem_ramdisk_swap(){
|
|
Packit Service |
b439df |
char *ramdisk;
|
|
Packit Service |
b439df |
char *iter = NULL;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
ramdisk = strtok_r(ramdisk_list, " ", &iter);
|
|
Packit Service |
b439df |
while (ramdisk != NULL) {
|
|
Packit Service |
b439df |
if (opt_dry_run) {
|
|
Packit Service |
b439df |
printf("swapoff %s\n", ramdisk);
|
|
Packit Service |
b439df |
} else {
|
|
Packit Service |
b439df |
DEBUG("swapoff %s\n", ramdisk);
|
|
Packit Service |
b439df |
if (swapoff(ramdisk)) {
|
|
Packit Service |
b439df |
WARNING("swapoff on %s failed: %s\n", ramdisk, strerror(errno));
|
|
Packit Service |
b439df |
continue;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
ramdisk = strtok_r(NULL, " ", &iter);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
void set_trans_opt(const char *file, const char *value)
|
|
Packit Service |
b439df |
{
|
|
Packit Service |
b439df |
FILE *f;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (geteuid() != 0) {
|
|
Packit Service |
b439df |
ERROR("Transparent huge page options can only be set by root\n");
|
|
Packit Service |
b439df |
exit(EXIT_FAILURE);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (opt_dry_run) {
|
|
Packit Service |
b439df |
printf("echo '%s' > %s\n", value, file);
|
|
Packit Service |
b439df |
return;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
f = fopen(file, "w");
|
|
Packit Service |
b439df |
if (!f) {
|
|
Packit Service |
b439df |
ERROR("Couldn't open %s: %s\n", file, strerror(errno));
|
|
Packit Service |
b439df |
return;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
fprintf(f, "%s", value);
|
|
Packit Service |
b439df |
fclose(f);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
enum {
|
|
Packit Service |
b439df |
POOL_MIN,
|
|
Packit Service |
b439df |
POOL_MAX,
|
|
Packit Service |
b439df |
POOL_BOTH,
|
|
Packit Service |
b439df |
};
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
static long value_adjust(char *adjust_str, long base, long page_size)
|
|
Packit Service |
b439df |
{
|
|
Packit Service |
b439df |
long long adjust;
|
|
Packit Service |
b439df |
char *iter;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
/* Convert and validate the adjust. */
|
|
Packit Service |
b439df |
errno = 0;
|
|
Packit Service |
b439df |
adjust = strtol(adjust_str, &iter, 0);
|
|
Packit Service |
b439df |
/* Catch strtol errors and sizes that overflow the native word size */
|
|
Packit Service |
b439df |
if (errno || adjust_str == iter) {
|
|
Packit Service |
b439df |
if (errno == ERANGE)
|
|
Packit Service |
b439df |
errno = EOVERFLOW;
|
|
Packit Service |
b439df |
else
|
|
Packit Service |
b439df |
errno = EINVAL;
|
|
Packit Service |
b439df |
ERROR("%s: invalid adjustment\n", adjust_str);
|
|
Packit Service |
b439df |
exit(EXIT_FAILURE);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
/* size_to_smaller_unit() only works with positive values */
|
|
Packit Service |
b439df |
if (adjust_str[0] == '-')
|
|
Packit Service |
b439df |
adjust = -adjust;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
switch (*iter) {
|
|
Packit Service |
b439df |
case 'G':
|
|
Packit Service |
b439df |
case 'g':
|
|
Packit Service |
b439df |
adjust = size_to_smaller_unit(adjust);
|
|
Packit Service |
b439df |
case 'M':
|
|
Packit Service |
b439df |
case 'm':
|
|
Packit Service |
b439df |
adjust = size_to_smaller_unit(adjust);
|
|
Packit Service |
b439df |
case 'K':
|
|
Packit Service |
b439df |
case 'k':
|
|
Packit Service |
b439df |
adjust = size_to_smaller_unit(adjust);
|
|
Packit Service |
b439df |
adjust = adjust / page_size;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
/* if previously negative, make negative again */
|
|
Packit Service |
b439df |
if (adjust_str[0] == '-')
|
|
Packit Service |
b439df |
adjust = -adjust;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (adjust_str[0] != '+' && adjust_str[0] != '-')
|
|
Packit Service |
b439df |
base = 0;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
/* Ensure we neither go negative nor exceed LONG_MAX. */
|
|
Packit Service |
b439df |
if (adjust < 0 && -adjust > base) {
|
|
Packit Service |
b439df |
adjust = -base;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
if (adjust > 0 && (base + adjust) < base) {
|
|
Packit Service |
b439df |
adjust = LONG_MAX - base;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
base += adjust;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
DEBUG("Returning page count of %ld\n", base);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
return base;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
void pool_adjust(char *cmd, unsigned int counter)
|
|
Packit Service |
b439df |
{
|
|
Packit Service |
b439df |
struct hpage_pool pools[MAX_POOLS];
|
|
Packit Service |
b439df |
int pos;
|
|
Packit Service |
b439df |
int cnt;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
char *iter = NULL;
|
|
Packit Service |
b439df |
char *page_size_str = NULL;
|
|
Packit Service |
b439df |
char *adjust_str = NULL;
|
|
Packit Service |
b439df |
long page_size;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
unsigned long min;
|
|
Packit Service |
b439df |
unsigned long min_orig;
|
|
Packit Service |
b439df |
unsigned long max;
|
|
Packit Service |
b439df |
unsigned long last_pool_value;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
/* Extract the pagesize and adjustment. */
|
|
Packit Service |
b439df |
page_size_str = strtok_r(cmd, ":", &iter);
|
|
Packit Service |
b439df |
if (page_size_str)
|
|
Packit Service |
b439df |
adjust_str = strtok_r(NULL, ":", &iter);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (!page_size_str || !adjust_str) {
|
|
Packit Service |
b439df |
ERROR("%s: invalid resize specification\n", cmd);
|
|
Packit Service |
b439df |
exit(EXIT_FAILURE);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
INFO("page_size<%s> adjust<%s> counter<%d>\n",
|
|
Packit Service |
b439df |
page_size_str, adjust_str, counter);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
/* Convert and validate the page_size. */
|
|
Packit Service |
b439df |
if (strcmp(page_size_str, "DEFAULT") == 0)
|
|
Packit Service |
b439df |
page_size = kernel_default_hugepage_size();
|
|
Packit Service |
b439df |
else
|
|
Packit Service |
b439df |
page_size = parse_page_size(page_size_str);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
DEBUG("Working with page_size of %ld\n", page_size);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
cnt = hpool_sizes(pools, MAX_POOLS);
|
|
Packit Service |
b439df |
if (cnt < 0) {
|
|
Packit Service |
b439df |
ERROR("unable to obtain pools list");
|
|
Packit Service |
b439df |
exit(EXIT_FAILURE);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
for (pos = 0; cnt--; pos++) {
|
|
Packit Service |
b439df |
if (pools[pos].pagesize == page_size)
|
|
Packit Service |
b439df |
break;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
if (cnt < 0) {
|
|
Packit Service |
b439df |
ERROR("%s: unknown page size\n", page_size_str);
|
|
Packit Service |
b439df |
exit(EXIT_FAILURE);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
min_orig = min = pools[pos].minimum;
|
|
Packit Service |
b439df |
max = pools[pos].maximum;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (counter == POOL_BOTH) {
|
|
Packit Service |
b439df |
min = value_adjust(adjust_str, min, page_size);
|
|
Packit Service |
b439df |
max = min;
|
|
Packit Service |
b439df |
} else if (counter == POOL_MIN) {
|
|
Packit Service |
b439df |
min = value_adjust(adjust_str, min, page_size);
|
|
Packit Service |
b439df |
if (min > max)
|
|
Packit Service |
b439df |
max = min;
|
|
Packit Service |
b439df |
} else {
|
|
Packit Service |
b439df |
max = value_adjust(adjust_str, max, page_size);
|
|
Packit Service |
b439df |
if (max < min)
|
|
Packit Service |
b439df |
min = max;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
INFO("%ld, %ld -> %ld, %ld\n", pools[pos].minimum, pools[pos].maximum,
|
|
Packit Service |
b439df |
min, max);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if ((pools[pos].maximum - pools[pos].minimum) < (max - min)) {
|
|
Packit Service |
b439df |
INFO("setting HUGEPAGES_OC to %ld\n", (max - min));
|
|
Packit Service |
b439df |
set_huge_page_counter(page_size, HUGEPAGES_OC, (max - min));
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (opt_hard)
|
|
Packit Service |
b439df |
cnt = 5;
|
|
Packit Service |
b439df |
else
|
|
Packit Service |
b439df |
cnt = -1;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (min > min_orig) {
|
|
Packit Service |
b439df |
if (opt_temp_swap)
|
|
Packit Service |
b439df |
add_temp_swap(page_size);
|
|
Packit Service |
b439df |
if (opt_ramdisk_swap)
|
|
Packit Service |
b439df |
add_ramdisk_swap(page_size);
|
|
Packit Service |
b439df |
check_swap();
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (opt_obey_mempolicy && get_huge_page_counter(page_size,
|
|
Packit Service |
b439df |
HUGEPAGES_TOTAL_MEMPOL) < 0) {
|
|
Packit Service |
b439df |
opt_obey_mempolicy = 0;
|
|
Packit Service |
b439df |
WARNING("Counter for NUMA huge page allocations is not found, continuing with normal pool adjustment\n");
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
INFO("setting HUGEPAGES_TOTAL%s to %ld\n",
|
|
Packit Service |
b439df |
opt_obey_mempolicy ? "_MEMPOL" : "", min);
|
|
Packit Service |
b439df |
set_huge_page_counter(page_size,
|
|
Packit Service |
b439df |
opt_obey_mempolicy ? HUGEPAGES_TOTAL_MEMPOL : HUGEPAGES_TOTAL,
|
|
Packit Service |
b439df |
min);
|
|
Packit Service |
b439df |
get_pool_size(page_size, &pools[pos]);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
/* If we fail to make an allocation, retry if user requests */
|
|
Packit Service |
b439df |
last_pool_value = pools[pos].minimum;
|
|
Packit Service |
b439df |
while ((pools[pos].minimum != min) && (cnt > 0)) {
|
|
Packit Service |
b439df |
/* Make note if progress is being made and sleep for IO */
|
|
Packit Service |
b439df |
if (last_pool_value == pools[pos].minimum)
|
|
Packit Service |
b439df |
cnt--;
|
|
Packit Service |
b439df |
else
|
|
Packit Service |
b439df |
cnt = 5;
|
|
Packit Service |
b439df |
sleep(6);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
last_pool_value = pools[pos].minimum;
|
|
Packit Service |
b439df |
INFO("Retrying allocation HUGEPAGES_TOTAL%s to %ld current %ld\n", opt_obey_mempolicy ? "_MEMPOL" : "", min, pools[pos].minimum);
|
|
Packit Service |
b439df |
set_huge_page_counter(page_size,
|
|
Packit Service |
b439df |
opt_obey_mempolicy ?
|
|
Packit Service |
b439df |
HUGEPAGES_TOTAL_MEMPOL :
|
|
Packit Service |
b439df |
HUGEPAGES_TOTAL,
|
|
Packit Service |
b439df |
min);
|
|
Packit Service |
b439df |
get_pool_size(page_size, &pools[pos]);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (min > min_orig && !opt_swap_persist) {
|
|
Packit Service |
b439df |
if (opt_temp_swap)
|
|
Packit Service |
b439df |
rem_temp_swap();
|
|
Packit Service |
b439df |
else if (opt_ramdisk_swap)
|
|
Packit Service |
b439df |
rem_ramdisk_swap();
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
/*
|
|
Packit Service |
b439df |
* HUGEPAGES_TOTAL is not guarenteed to check to exactly the figure
|
|
Packit Service |
b439df |
* requested should there be insufficient pages. Check the new
|
|
Packit Service |
b439df |
* value and adjust HUGEPAGES_OC accordingly.
|
|
Packit Service |
b439df |
*/
|
|
Packit Service |
b439df |
if (pools[pos].minimum != min) {
|
|
Packit Service |
b439df |
WARNING("failed to set pool minimum to %ld became %ld\n",
|
|
Packit Service |
b439df |
min, pools[pos].minimum);
|
|
Packit Service |
b439df |
min = pools[pos].minimum;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
if (pools[pos].maximum != max) {
|
|
Packit Service |
b439df |
INFO("setting HUGEPAGES_OC to %ld\n", (max - min));
|
|
Packit Service |
b439df |
set_huge_page_counter(page_size, HUGEPAGES_OC, (max - min));
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
void page_sizes(int all)
|
|
Packit Service |
b439df |
{
|
|
Packit Service |
b439df |
struct hpage_pool pools[MAX_POOLS];
|
|
Packit Service |
b439df |
int pos;
|
|
Packit Service |
b439df |
int cnt;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
cnt = hpool_sizes(pools, MAX_POOLS);
|
|
Packit Service |
b439df |
if (cnt < 0) {
|
|
Packit Service |
b439df |
ERROR("unable to obtain pools list");
|
|
Packit Service |
b439df |
exit(EXIT_FAILURE);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
qsort(pools, cnt, sizeof(pools[0]), cmpsizes);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
for (pos = 0; cnt--; pos++) {
|
|
Packit Service |
b439df |
if (all || (pools[pos].maximum &&
|
|
Packit Service |
b439df |
hugetlbfs_find_path_for_size(pools[pos].pagesize)))
|
|
Packit Service |
b439df |
printf("%ld\n", pools[pos].pagesize);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
void explain()
|
|
Packit Service |
b439df |
{
|
|
Packit Service |
b439df |
show_mem();
|
|
Packit Service |
b439df |
mounts_list_all();
|
|
Packit Service |
b439df |
printf("\nHuge page pools:\n");
|
|
Packit Service |
b439df |
pool_list();
|
|
Packit Service |
b439df |
printf("\nHuge page sizes with configured pools:\n");
|
|
Packit Service |
b439df |
page_sizes(0);
|
|
Packit Service |
b439df |
check_minfreekbytes();
|
|
Packit Service |
b439df |
check_shmmax();
|
|
Packit Service |
b439df |
check_swap();
|
|
Packit Service |
b439df |
check_user();
|
|
Packit Service |
b439df |
printf("\nNote: Permanent swap space should be preferred when dynamic "
|
|
Packit Service |
b439df |
"huge page pools are used.\n");
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
int main(int argc, char** argv)
|
|
Packit Service |
b439df |
{
|
|
Packit Service |
b439df |
int ops;
|
|
Packit Service |
b439df |
int has_hugepages = kernel_has_hugepages();
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
char opts[] = "+hdv";
|
|
Packit Service |
b439df |
char base[PATH_MAX];
|
|
Packit Service |
b439df |
char *opt_min_adj[MAX_POOLS], *opt_max_adj[MAX_POOLS];
|
|
Packit Service |
b439df |
char *opt_user_mounts = NULL, *opt_group_mounts = NULL;
|
|
Packit Service |
b439df |
int opt_list_mounts = 0, opt_pool_list = 0, opt_create_mounts = 0;
|
|
Packit Service |
b439df |
int opt_global_mounts = 0, opt_pgsizes = 0, opt_pgsizes_all = 0;
|
|
Packit Service |
b439df |
int opt_explain = 0, minadj_count = 0, maxadj_count = 0;
|
|
Packit Service |
b439df |
int opt_trans_always = 0, opt_trans_never = 0, opt_trans_madvise = 0;
|
|
Packit Service |
b439df |
int opt_khuge_pages = 0, opt_khuge_scan = 0, opt_khuge_alloc = 0;
|
|
Packit Service |
b439df |
int ret = 0, index = 0;
|
|
Packit Service |
b439df |
char *khuge_pages = NULL, *khuge_alloc = NULL, *khuge_scan = NULL;
|
|
Packit Service |
b439df |
gid_t opt_gid = 0;
|
|
Packit Service |
b439df |
struct group *opt_grp = NULL;
|
|
Packit Service |
b439df |
int group_invalid = 0;
|
|
Packit Service |
b439df |
struct option long_opts[] = {
|
|
Packit Service |
b439df |
{"help", no_argument, NULL, 'h'},
|
|
Packit Service |
b439df |
{"verbose", required_argument, NULL, 'v' },
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
{"list-all-mounts", no_argument, NULL, LONG_LIST_ALL_MOUNTS},
|
|
Packit Service |
b439df |
{"pool-list", no_argument, NULL, LONG_POOL_LIST},
|
|
Packit Service |
b439df |
{"pool-pages-min", required_argument, NULL, LONG_POOL_MIN_ADJ},
|
|
Packit Service |
b439df |
{"pool-pages-max", required_argument, NULL, LONG_POOL_MAX_ADJ},
|
|
Packit Service |
b439df |
{"obey-mempolicy", no_argument, NULL, LONG_POOL_MEMPOL},
|
|
Packit Service |
b439df |
{"thp-always", no_argument, NULL, LONG_TRANS_ALWAYS},
|
|
Packit Service |
b439df |
{"thp-madvise", no_argument, NULL, LONG_TRANS_MADVISE},
|
|
Packit Service |
b439df |
{"thp-never", no_argument, NULL, LONG_TRANS_NEVER},
|
|
Packit Service |
b439df |
{"thp-khugepaged-pages", required_argument, NULL, LONG_KHUGE_PAGES},
|
|
Packit Service |
b439df |
{"thp-khugepaged-scan-sleep", required_argument, NULL, LONG_KHUGE_SCAN},
|
|
Packit Service |
b439df |
{"thp-khugepaged-alloc-sleep", required_argument, NULL, LONG_KHUGE_ALLOC},
|
|
Packit Service |
b439df |
{"set-recommended-min_free_kbytes", no_argument, NULL, LONG_SET_RECOMMENDED_MINFREEKBYTES},
|
|
Packit Service |
b439df |
{"set-recommended-shmmax", no_argument, NULL, LONG_SET_RECOMMENDED_SHMMAX},
|
|
Packit Service |
b439df |
{"set-shm-group", required_argument, NULL, LONG_SET_HUGETLB_SHM_GROUP},
|
|
Packit Service |
b439df |
{"enable-zone-movable", no_argument, NULL, LONG_MOVABLE_ENABLE},
|
|
Packit Service |
b439df |
{"disable-zone-movable", no_argument, NULL, LONG_MOVABLE_DISABLE},
|
|
Packit Service |
b439df |
{"hard", no_argument, NULL, LONG_HARD},
|
|
Packit Service |
b439df |
{"add-temp-swap", optional_argument, NULL, LONG_SWAP_DISK},
|
|
Packit Service |
b439df |
{"add-ramdisk-swap", no_argument, NULL, LONG_SWAP_RAMDISK},
|
|
Packit Service |
b439df |
{"persist", no_argument, NULL, LONG_SWAP_PERSIST},
|
|
Packit Service |
b439df |
{"create-mounts", no_argument, NULL, LONG_CREATE_MOUNTS},
|
|
Packit Service |
b439df |
{"create-user-mounts", required_argument, NULL, LONG_CREATE_USER_MOUNTS},
|
|
Packit Service |
b439df |
{"create-group-mounts", required_argument, NULL, LONG_CREATE_GROUP_MOUNTS},
|
|
Packit Service |
b439df |
{"create-global-mounts", no_argument, NULL, LONG_CREATE_GLOBAL_MOUNTS},
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
{"max-size", required_argument, NULL, LONG_LIMIT_SIZE},
|
|
Packit Service |
b439df |
{"max-inodes", required_argument, NULL, LONG_LIMIT_INODES},
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
{"page-sizes", no_argument, NULL, LONG_PAGE_SIZES},
|
|
Packit Service |
b439df |
{"page-sizes-all", no_argument, NULL, LONG_PAGE_AVAIL},
|
|
Packit Service |
b439df |
{"dry-run", no_argument, NULL, 'd'},
|
|
Packit Service |
b439df |
{"explain", no_argument, NULL, LONG_EXPLAIN},
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
{0},
|
|
Packit Service |
b439df |
};
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
hugetlbfs_setup_debug();
|
|
Packit Service |
b439df |
setup_mounts();
|
|
Packit Service |
b439df |
verbose_init();
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
ops = 0;
|
|
Packit Service |
b439df |
while (ret != -1) {
|
|
Packit Service |
b439df |
ret = getopt_long(argc, argv, opts, long_opts, &index);
|
|
Packit Service |
b439df |
switch (ret) {
|
|
Packit Service |
b439df |
case -1:
|
|
Packit Service |
b439df |
break;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
case '?':
|
|
Packit Service |
b439df |
print_usage();
|
|
Packit Service |
b439df |
exit(EXIT_FAILURE);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
case 'h':
|
|
Packit Service |
b439df |
print_usage();
|
|
Packit Service |
b439df |
exit(EXIT_SUCCESS);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
case 'v':
|
|
Packit Service |
b439df |
verbose(optarg);
|
|
Packit Service |
b439df |
continue;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
case 'd':
|
|
Packit Service |
b439df |
opt_dry_run = 1;
|
|
Packit Service |
b439df |
continue;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
default:
|
|
Packit Service |
b439df |
/* All other commands require hugepage support. */
|
|
Packit Service |
b439df |
if (! has_hugepages) {
|
|
Packit Service |
b439df |
ERROR("kernel does not support huge pages\n");
|
|
Packit Service |
b439df |
exit(EXIT_FAILURE);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
switch (ret) {
|
|
Packit Service |
b439df |
case -1:
|
|
Packit Service |
b439df |
break;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
case LONG_HARD:
|
|
Packit Service |
b439df |
opt_hard = 1;
|
|
Packit Service |
b439df |
continue;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
case LONG_SWAP_DISK:
|
|
Packit Service |
b439df |
if (optarg)
|
|
Packit Service |
b439df |
opt_temp_swap = atoi(optarg);
|
|
Packit Service |
b439df |
else
|
|
Packit Service |
b439df |
opt_temp_swap = -1;
|
|
Packit Service |
b439df |
break;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
case LONG_SWAP_RAMDISK:
|
|
Packit Service |
b439df |
opt_ramdisk_swap = 1;
|
|
Packit Service |
b439df |
break;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
case LONG_SWAP_PERSIST:
|
|
Packit Service |
b439df |
opt_swap_persist = 1;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
case LONG_LIST_ALL_MOUNTS:
|
|
Packit Service |
b439df |
opt_list_mounts = 1;
|
|
Packit Service |
b439df |
break;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
case LONG_POOL_LIST:
|
|
Packit Service |
b439df |
opt_pool_list = 1;
|
|
Packit Service |
b439df |
break;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
case LONG_POOL_MIN_ADJ:
|
|
Packit Service |
b439df |
if (minadj_count == MAX_POOLS) {
|
|
Packit Service |
b439df |
WARNING("Attempting to adjust an invalid "
|
|
Packit Service |
b439df |
"pool or a pool multiple times, "
|
|
Packit Service |
b439df |
"ignoring request: '%s'\n", optarg);
|
|
Packit Service |
b439df |
} else {
|
|
Packit Service |
b439df |
opt_min_adj[minadj_count++] = optarg;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
break;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
case LONG_POOL_MEMPOL:
|
|
Packit Service |
b439df |
opt_obey_mempolicy = 1;
|
|
Packit Service |
b439df |
break;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
case LONG_TRANS_ALWAYS:
|
|
Packit Service |
b439df |
opt_trans_always = 1;
|
|
Packit Service |
b439df |
break;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
case LONG_TRANS_MADVISE:
|
|
Packit Service |
b439df |
opt_trans_madvise = 1;
|
|
Packit Service |
b439df |
break;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
case LONG_TRANS_NEVER:
|
|
Packit Service |
b439df |
opt_trans_never = 1;
|
|
Packit Service |
b439df |
break;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
case LONG_KHUGE_PAGES:
|
|
Packit Service |
b439df |
opt_khuge_pages = 1;
|
|
Packit Service |
b439df |
khuge_pages = optarg;
|
|
Packit Service |
b439df |
break;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
case LONG_KHUGE_SCAN:
|
|
Packit Service |
b439df |
opt_khuge_scan = 1;
|
|
Packit Service |
b439df |
khuge_scan = optarg;
|
|
Packit Service |
b439df |
break;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
case LONG_KHUGE_ALLOC:
|
|
Packit Service |
b439df |
opt_khuge_alloc = 1;
|
|
Packit Service |
b439df |
khuge_alloc = optarg;
|
|
Packit Service |
b439df |
break;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
case LONG_POOL_MAX_ADJ:
|
|
Packit Service |
b439df |
if (! kernel_has_overcommit()) {
|
|
Packit Service |
b439df |
ERROR("kernel does not support overcommit, "
|
|
Packit Service |
b439df |
"max cannot be adjusted\n");
|
|
Packit Service |
b439df |
exit(EXIT_FAILURE);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (maxadj_count == MAX_POOLS) {
|
|
Packit Service |
b439df |
WARNING("Attempting to adjust an invalid "
|
|
Packit Service |
b439df |
"pool or a pool multiple times, "
|
|
Packit Service |
b439df |
"ignoring request: '%s'\n", optarg);
|
|
Packit Service |
b439df |
} else {
|
|
Packit Service |
b439df |
opt_max_adj[maxadj_count++] = optarg;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
break;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
case LONG_MOVABLE_ENABLE:
|
|
Packit Service |
b439df |
opt_movable = 1;
|
|
Packit Service |
b439df |
break;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
case LONG_SET_RECOMMENDED_MINFREEKBYTES:
|
|
Packit Service |
b439df |
opt_set_recommended_minfreekbytes = 1;
|
|
Packit Service |
b439df |
break;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
case LONG_SET_RECOMMENDED_SHMMAX:
|
|
Packit Service |
b439df |
opt_set_recommended_shmmax = 1;
|
|
Packit Service |
b439df |
break;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
case LONG_SET_HUGETLB_SHM_GROUP:
|
|
Packit Service |
b439df |
opt_grp = getgrnam(optarg);
|
|
Packit Service |
b439df |
if (!opt_grp) {
|
|
Packit Service |
b439df |
opt_gid = atoi(optarg);
|
|
Packit Service |
b439df |
if (opt_gid == 0 && strcmp(optarg, "0"))
|
|
Packit Service |
b439df |
group_invalid = 1;
|
|
Packit Service |
b439df |
opt_grp = getgrgid(opt_gid);
|
|
Packit Service |
b439df |
if (!opt_grp)
|
|
Packit Service |
b439df |
group_invalid = 1;
|
|
Packit Service |
b439df |
} else {
|
|
Packit Service |
b439df |
opt_gid = opt_grp->gr_gid;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
if (group_invalid) {
|
|
Packit Service |
b439df |
ERROR("Invalid group specification (%s)\n", optarg);
|
|
Packit Service |
b439df |
exit(EXIT_FAILURE);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
opt_set_hugetlb_shm_group = 1;
|
|
Packit Service |
b439df |
break;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
case LONG_MOVABLE_DISABLE:
|
|
Packit Service |
b439df |
opt_movable = 0;
|
|
Packit Service |
b439df |
break;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
case LONG_CREATE_MOUNTS:
|
|
Packit Service |
b439df |
opt_create_mounts = 1;
|
|
Packit Service |
b439df |
break;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
case LONG_CREATE_USER_MOUNTS:
|
|
Packit Service |
b439df |
opt_user_mounts = optarg;
|
|
Packit Service |
b439df |
break;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
case LONG_CREATE_GROUP_MOUNTS:
|
|
Packit Service |
b439df |
opt_group_mounts = optarg;
|
|
Packit Service |
b439df |
break;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
case LONG_CREATE_GLOBAL_MOUNTS:
|
|
Packit Service |
b439df |
opt_global_mounts = 1;
|
|
Packit Service |
b439df |
break;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
case LONG_LIMIT_SIZE:
|
|
Packit Service |
b439df |
/* Not a pagesize, but the conversions the same */
|
|
Packit Service |
b439df |
opt_limit_mount_size = parse_page_size(optarg);
|
|
Packit Service |
b439df |
if (!opt_limit_mount_size)
|
|
Packit Service |
b439df |
WARNING("Mount max size specification 0, invalid or overflowed\n");
|
|
Packit Service |
b439df |
break;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
case LONG_LIMIT_INODES:
|
|
Packit Service |
b439df |
opt_limit_mount_inodes = atoi(optarg);
|
|
Packit Service |
b439df |
break;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
case LONG_PAGE_SIZES:
|
|
Packit Service |
b439df |
opt_pgsizes = 1;
|
|
Packit Service |
b439df |
break;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
case LONG_PAGE_AVAIL:
|
|
Packit Service |
b439df |
opt_pgsizes_all = 1;
|
|
Packit Service |
b439df |
break;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
case LONG_EXPLAIN:
|
|
Packit Service |
b439df |
opt_explain = 1;
|
|
Packit Service |
b439df |
break;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
default:
|
|
Packit Service |
b439df |
WARNING("unparsed option %08x\n", ret);
|
|
Packit Service |
b439df |
ret = -1;
|
|
Packit Service |
b439df |
break;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
if (ret != -1)
|
|
Packit Service |
b439df |
ops++;
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
verbose_expose();
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (opt_list_mounts)
|
|
Packit Service |
b439df |
mounts_list_all();
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (opt_pool_list)
|
|
Packit Service |
b439df |
pool_list();
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (opt_movable != -1)
|
|
Packit Service |
b439df |
setup_zone_movable(opt_movable);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (opt_trans_always)
|
|
Packit Service |
b439df |
set_trans_opt(TRANS_ENABLE, ALWAYS);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (opt_trans_madvise)
|
|
Packit Service |
b439df |
set_trans_opt(TRANS_ENABLE, MADVISE);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (opt_trans_never)
|
|
Packit Service |
b439df |
set_trans_opt(TRANS_ENABLE, NEVER);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (opt_khuge_pages)
|
|
Packit Service |
b439df |
set_trans_opt(KHUGE_SCAN_PAGES, khuge_pages);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (opt_khuge_alloc)
|
|
Packit Service |
b439df |
set_trans_opt(KHUGE_ALLOC_SLEEP, khuge_alloc);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (opt_khuge_scan)
|
|
Packit Service |
b439df |
set_trans_opt(KHUGE_SCAN_SLEEP, khuge_scan);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (opt_set_recommended_minfreekbytes)
|
|
Packit Service |
b439df |
set_recommended_minfreekbytes();
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (opt_set_recommended_shmmax)
|
|
Packit Service |
b439df |
set_recommended_shmmax();
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (opt_set_hugetlb_shm_group)
|
|
Packit Service |
b439df |
set_hugetlb_shm_group(opt_gid, opt_grp->gr_name);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
while (--minadj_count >= 0) {
|
|
Packit Service |
b439df |
if (! kernel_has_overcommit())
|
|
Packit Service |
b439df |
pool_adjust(opt_min_adj[minadj_count], POOL_BOTH);
|
|
Packit Service |
b439df |
else
|
|
Packit Service |
b439df |
pool_adjust(opt_min_adj[minadj_count], POOL_MIN);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
while (--maxadj_count >=0)
|
|
Packit Service |
b439df |
pool_adjust(opt_max_adj[maxadj_count], POOL_MAX);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (opt_create_mounts) {
|
|
Packit Service |
b439df |
snprintf(base, PATH_MAX, "%s", MOUNT_DIR);
|
|
Packit Service |
b439df |
create_mounts(NULL, NULL, base, S_IRWXU | S_IRWXG);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (opt_user_mounts != NULL) {
|
|
Packit Service |
b439df |
snprintf(base, PATH_MAX, "%s/user", MOUNT_DIR);
|
|
Packit Service |
b439df |
create_mounts(opt_user_mounts, NULL, base, S_IRWXU);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (opt_group_mounts) {
|
|
Packit Service |
b439df |
snprintf(base, PATH_MAX, "%s/group", MOUNT_DIR);
|
|
Packit Service |
b439df |
create_mounts(NULL, opt_group_mounts, base, S_IRWXG);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (opt_global_mounts) {
|
|
Packit Service |
b439df |
snprintf(base, PATH_MAX, "%s/global", MOUNT_DIR);
|
|
Packit Service |
b439df |
create_mounts(NULL, NULL, base, S_IRWXU | S_IRWXG | S_IRWXO | S_ISVTX );
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (opt_pgsizes)
|
|
Packit Service |
b439df |
page_sizes(0);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (opt_pgsizes_all)
|
|
Packit Service |
b439df |
page_sizes(1);
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if (opt_explain)
|
|
Packit Service |
b439df |
explain();
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
index = optind;
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
if ((argc - index) != 0 || ops == 0) {
|
|
Packit Service |
b439df |
print_usage();
|
|
Packit Service |
b439df |
exit(EXIT_FAILURE);
|
|
Packit Service |
b439df |
}
|
|
Packit Service |
b439df |
|
|
Packit Service |
b439df |
exit(EXIT_SUCCESS);
|
|
Packit Service |
b439df |
}
|