mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-01-16 02:56:36 +07:00
29750f71a9
The tests use both shared and private mapped hugetlb memory, and monitors the hugetlb usage counter as well as the hugetlb reservation counter. They test different configurations such as hugetlb memory usage via hugetlbfs, or MAP_HUGETLB, or shmget/shmat, and with and without MAP_POPULATE. Also add test for hugetlb reservation reparenting, since this is a subtle issue. Signed-off-by: Mina Almasry <almasrymina@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Tested-by: Sandipan Das <sandipan@linux.ibm.com> [powerpc64] Acked-by: Mike Kravetz <mike.kravetz@oracle.com> Cc: Sandipan Das <sandipan@linux.ibm.com> Cc: David Rientjes <rientjes@google.com> Cc: Greg Thelen <gthelen@google.com> Cc: Shakeel Butt <shakeelb@google.com> Cc: Shuah Khan <shuah@kernel.org> Link: http://lkml.kernel.org/r/20200211213128.73302-8-almasrymina@google.com Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
243 lines
4.6 KiB
C
243 lines
4.6 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* This program reserves and uses hugetlb memory, supporting a bunch of
|
|
* scenarios needed by the charged_reserved_hugetlb.sh test.
|
|
*/
|
|
|
|
#include <err.h>
|
|
#include <errno.h>
|
|
#include <signal.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <sys/types.h>
|
|
#include <sys/shm.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/mman.h>
|
|
|
|
/* Global definitions. */
|
|
enum method {
|
|
HUGETLBFS,
|
|
MMAP_MAP_HUGETLB,
|
|
SHM,
|
|
MAX_METHOD
|
|
};
|
|
|
|
|
|
/* Global variables. */
|
|
static const char *self;
|
|
static char *shmaddr;
|
|
static int shmid;
|
|
|
|
/*
|
|
* Show usage and exit.
|
|
*/
|
|
static void exit_usage(void)
|
|
{
|
|
printf("Usage: %s -p <path to hugetlbfs file> -s <size to map> "
|
|
"[-m <0=hugetlbfs | 1=mmap(MAP_HUGETLB)>] [-l] [-r] "
|
|
"[-o] [-w] [-n]\n",
|
|
self);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
void sig_handler(int signo)
|
|
{
|
|
printf("Received %d.\n", signo);
|
|
if (signo == SIGINT) {
|
|
printf("Deleting the memory\n");
|
|
if (shmdt((const void *)shmaddr) != 0) {
|
|
perror("Detach failure");
|
|
shmctl(shmid, IPC_RMID, NULL);
|
|
exit(4);
|
|
}
|
|
|
|
shmctl(shmid, IPC_RMID, NULL);
|
|
printf("Done deleting the memory\n");
|
|
}
|
|
exit(2);
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
int fd = 0;
|
|
int key = 0;
|
|
int *ptr = NULL;
|
|
int c = 0;
|
|
int size = 0;
|
|
char path[256] = "";
|
|
enum method method = MAX_METHOD;
|
|
int want_sleep = 0, private = 0;
|
|
int populate = 0;
|
|
int write = 0;
|
|
int reserve = 1;
|
|
|
|
unsigned long i;
|
|
|
|
if (signal(SIGINT, sig_handler) == SIG_ERR)
|
|
err(1, "\ncan't catch SIGINT\n");
|
|
|
|
/* Parse command-line arguments. */
|
|
setvbuf(stdout, NULL, _IONBF, 0);
|
|
self = argv[0];
|
|
|
|
while ((c = getopt(argc, argv, "s:p:m:owlrn")) != -1) {
|
|
switch (c) {
|
|
case 's':
|
|
size = atoi(optarg);
|
|
break;
|
|
case 'p':
|
|
strncpy(path, optarg, sizeof(path));
|
|
break;
|
|
case 'm':
|
|
if (atoi(optarg) >= MAX_METHOD) {
|
|
errno = EINVAL;
|
|
perror("Invalid -m.");
|
|
exit_usage();
|
|
}
|
|
method = atoi(optarg);
|
|
break;
|
|
case 'o':
|
|
populate = 1;
|
|
break;
|
|
case 'w':
|
|
write = 1;
|
|
break;
|
|
case 'l':
|
|
want_sleep = 1;
|
|
break;
|
|
case 'r':
|
|
private
|
|
= 1;
|
|
break;
|
|
case 'n':
|
|
reserve = 0;
|
|
break;
|
|
default:
|
|
errno = EINVAL;
|
|
perror("Invalid arg");
|
|
exit_usage();
|
|
}
|
|
}
|
|
|
|
if (strncmp(path, "", sizeof(path)) != 0) {
|
|
printf("Writing to this path: %s\n", path);
|
|
} else {
|
|
errno = EINVAL;
|
|
perror("path not found");
|
|
exit_usage();
|
|
}
|
|
|
|
if (size != 0) {
|
|
printf("Writing this size: %d\n", size);
|
|
} else {
|
|
errno = EINVAL;
|
|
perror("size not found");
|
|
exit_usage();
|
|
}
|
|
|
|
if (!populate)
|
|
printf("Not populating.\n");
|
|
else
|
|
printf("Populating.\n");
|
|
|
|
if (!write)
|
|
printf("Not writing to memory.\n");
|
|
|
|
if (method == MAX_METHOD) {
|
|
errno = EINVAL;
|
|
perror("-m Invalid");
|
|
exit_usage();
|
|
} else
|
|
printf("Using method=%d\n", method);
|
|
|
|
if (!private)
|
|
printf("Shared mapping.\n");
|
|
else
|
|
printf("Private mapping.\n");
|
|
|
|
if (!reserve)
|
|
printf("NO_RESERVE mapping.\n");
|
|
else
|
|
printf("RESERVE mapping.\n");
|
|
|
|
switch (method) {
|
|
case HUGETLBFS:
|
|
printf("Allocating using HUGETLBFS.\n");
|
|
fd = open(path, O_CREAT | O_RDWR, 0777);
|
|
if (fd == -1)
|
|
err(1, "Failed to open file.");
|
|
|
|
ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
|
|
(private ? MAP_PRIVATE : MAP_SHARED) |
|
|
(populate ? MAP_POPULATE : 0) |
|
|
(reserve ? 0 : MAP_NORESERVE),
|
|
fd, 0);
|
|
|
|
if (ptr == MAP_FAILED) {
|
|
close(fd);
|
|
err(1, "Error mapping the file");
|
|
}
|
|
break;
|
|
case MMAP_MAP_HUGETLB:
|
|
printf("Allocating using MAP_HUGETLB.\n");
|
|
ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
|
|
(private ? (MAP_PRIVATE | MAP_ANONYMOUS) :
|
|
MAP_SHARED) |
|
|
MAP_HUGETLB | (populate ? MAP_POPULATE : 0) |
|
|
(reserve ? 0 : MAP_NORESERVE),
|
|
-1, 0);
|
|
|
|
if (ptr == MAP_FAILED)
|
|
err(1, "mmap");
|
|
|
|
printf("Returned address is %p\n", ptr);
|
|
break;
|
|
case SHM:
|
|
printf("Allocating using SHM.\n");
|
|
shmid = shmget(key, size,
|
|
SHM_HUGETLB | IPC_CREAT | SHM_R | SHM_W);
|
|
if (shmid < 0) {
|
|
shmid = shmget(++key, size,
|
|
SHM_HUGETLB | IPC_CREAT | SHM_R | SHM_W);
|
|
if (shmid < 0)
|
|
err(1, "shmget");
|
|
}
|
|
printf("shmid: 0x%x, shmget key:%d\n", shmid, key);
|
|
|
|
ptr = shmat(shmid, NULL, 0);
|
|
if (ptr == (int *)-1) {
|
|
perror("Shared memory attach failure");
|
|
shmctl(shmid, IPC_RMID, NULL);
|
|
exit(2);
|
|
}
|
|
printf("shmaddr: %p\n", ptr);
|
|
|
|
break;
|
|
default:
|
|
errno = EINVAL;
|
|
err(1, "Invalid method.");
|
|
}
|
|
|
|
if (write) {
|
|
printf("Writing to memory.\n");
|
|
memset(ptr, 1, size);
|
|
}
|
|
|
|
if (want_sleep) {
|
|
/* Signal to caller that we're done. */
|
|
printf("DONE\n");
|
|
|
|
/* Hold memory until external kill signal is delivered. */
|
|
while (1)
|
|
sleep(100);
|
|
}
|
|
|
|
if (method == HUGETLBFS)
|
|
close(fd);
|
|
|
|
return 0;
|
|
}
|