mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 12:42:02 +00:00
selftests/mm: thuge-gen: conform to TAP format output
Conform the layout, informational and status messages to TAP. No functional change is intended other than the layout of output messages. Also remove unneeded logging which isn't enabled. Skip a hugepage size if it has less free pages to avoid unnecessary failures. For examples, some systems may not have 1GB hugepage free. So skip 1GB for testing in this test instead of failing the entire test. Link: https://lkml.kernel.org/r/20240202113119.2047740-11-usama.anjum@collabora.com Signed-off-by: Muhammad Usama Anjum <usama.anjum@collabora.com> Cc: Shuah Khan <shuah@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
parent
735887041a
commit
b38bd9b2c4
@ -4,7 +4,7 @@
|
||||
Before running this huge pages for each huge page size must have been
|
||||
reserved.
|
||||
For large pages beyond MAX_PAGE_ORDER (like 1GB on x86) boot options must
|
||||
be used.
|
||||
be used. 1GB wouldn't be tested if it isn't available.
|
||||
Also shmmax must be increased.
|
||||
And you need to run as root to work around some weird permissions in shm.
|
||||
And nothing using huge pages should run in parallel.
|
||||
@ -26,8 +26,7 @@
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include "vm_util.h"
|
||||
|
||||
#define err(x) perror(x), exit(1)
|
||||
#include "../kselftest.h"
|
||||
|
||||
#define MAP_HUGE_2MB (21 << MAP_HUGE_SHIFT)
|
||||
#define MAP_HUGE_1GB (30 << MAP_HUGE_SHIFT)
|
||||
@ -44,11 +43,8 @@
|
||||
#define SHM_HUGE_1GB (30 << SHM_HUGE_SHIFT)
|
||||
|
||||
#define NUM_PAGESIZES 5
|
||||
|
||||
#define NUM_PAGES 4
|
||||
|
||||
#define Dprintf(fmt...) // printf(fmt)
|
||||
|
||||
unsigned long page_sizes[NUM_PAGESIZES];
|
||||
int num_page_sizes;
|
||||
|
||||
@ -60,28 +56,15 @@ int ilog2(unsigned long v)
|
||||
return l;
|
||||
}
|
||||
|
||||
void find_pagesizes(void)
|
||||
{
|
||||
glob_t g;
|
||||
int i;
|
||||
glob("/sys/kernel/mm/hugepages/hugepages-*kB", 0, NULL, &g);
|
||||
assert(g.gl_pathc <= NUM_PAGESIZES);
|
||||
for (i = 0; i < g.gl_pathc; i++) {
|
||||
sscanf(g.gl_pathv[i], "/sys/kernel/mm/hugepages/hugepages-%lukB",
|
||||
&page_sizes[i]);
|
||||
page_sizes[i] <<= 10;
|
||||
printf("Found %luMB\n", page_sizes[i] >> 20);
|
||||
}
|
||||
num_page_sizes = g.gl_pathc;
|
||||
globfree(&g);
|
||||
}
|
||||
|
||||
void show(unsigned long ps)
|
||||
{
|
||||
char buf[100];
|
||||
|
||||
if (ps == getpagesize())
|
||||
return;
|
||||
printf("%luMB: ", ps >> 20);
|
||||
|
||||
ksft_print_msg("%luMB: ", ps >> 20);
|
||||
|
||||
fflush(stdout);
|
||||
snprintf(buf, sizeof buf,
|
||||
"cat /sys/kernel/mm/hugepages/hugepages-%lukB/free_hugepages",
|
||||
@ -105,7 +88,7 @@ unsigned long read_sysfs(int warn, char *fmt, ...)
|
||||
f = fopen(buf, "r");
|
||||
if (!f) {
|
||||
if (warn)
|
||||
printf("missing %s\n", buf);
|
||||
ksft_print_msg("missing %s\n", buf);
|
||||
return 0;
|
||||
}
|
||||
if (getline(&line, &linelen, f) > 0) {
|
||||
@ -127,115 +110,135 @@ void test_mmap(unsigned long size, unsigned flags)
|
||||
{
|
||||
char *map;
|
||||
unsigned long before, after;
|
||||
int err;
|
||||
|
||||
before = read_free(size);
|
||||
map = mmap(NULL, size*NUM_PAGES, PROT_READ|PROT_WRITE,
|
||||
MAP_PRIVATE|MAP_ANONYMOUS|MAP_HUGETLB|flags, -1, 0);
|
||||
if (map == MAP_FAILED)
|
||||
ksft_exit_fail_msg("mmap: %s\n", strerror(errno));
|
||||
|
||||
if (map == (char *)-1) err("mmap");
|
||||
memset(map, 0xff, size*NUM_PAGES);
|
||||
after = read_free(size);
|
||||
Dprintf("before %lu after %lu diff %ld size %lu\n",
|
||||
before, after, before - after, size);
|
||||
assert(size == getpagesize() || (before - after) == NUM_PAGES);
|
||||
|
||||
show(size);
|
||||
err = munmap(map, size * NUM_PAGES);
|
||||
assert(!err);
|
||||
ksft_test_result(size == getpagesize() || (before - after) == NUM_PAGES,
|
||||
"%s mmap\n", __func__);
|
||||
|
||||
if (munmap(map, size * NUM_PAGES))
|
||||
ksft_exit_fail_msg("%s: unmap %s\n", __func__, strerror(errno));
|
||||
}
|
||||
|
||||
void test_shmget(unsigned long size, unsigned flags)
|
||||
{
|
||||
int id;
|
||||
unsigned long before, after;
|
||||
int err;
|
||||
struct shm_info i;
|
||||
char *map;
|
||||
|
||||
before = read_free(size);
|
||||
id = shmget(IPC_PRIVATE, size * NUM_PAGES, IPC_CREAT|0600|flags);
|
||||
if (id < 0) err("shmget");
|
||||
if (id < 0) {
|
||||
if (errno == EPERM) {
|
||||
ksft_test_result_skip("shmget requires root privileges: %s\n",
|
||||
strerror(errno));
|
||||
return;
|
||||
}
|
||||
ksft_exit_fail_msg("shmget: %s\n", strerror(errno));
|
||||
}
|
||||
|
||||
struct shm_info i;
|
||||
if (shmctl(id, SHM_INFO, (void *)&i) < 0) err("shmctl");
|
||||
Dprintf("alloc %lu res %lu\n", i.shm_tot, i.shm_rss);
|
||||
if (shmctl(id, SHM_INFO, (void *)&i) < 0)
|
||||
ksft_exit_fail_msg("shmctl: %s\n", strerror(errno));
|
||||
|
||||
|
||||
Dprintf("id %d\n", id);
|
||||
char *map = shmat(id, NULL, 0600);
|
||||
if (map == (char*)-1) err("shmat");
|
||||
map = shmat(id, NULL, 0600);
|
||||
if (map == MAP_FAILED)
|
||||
ksft_exit_fail_msg("shmat: %s\n", strerror(errno));
|
||||
|
||||
shmctl(id, IPC_RMID, NULL);
|
||||
|
||||
memset(map, 0xff, size*NUM_PAGES);
|
||||
after = read_free(size);
|
||||
|
||||
Dprintf("before %lu after %lu diff %ld size %lu\n",
|
||||
before, after, before - after, size);
|
||||
assert(size == getpagesize() || (before - after) == NUM_PAGES);
|
||||
show(size);
|
||||
err = shmdt(map);
|
||||
assert(!err);
|
||||
ksft_test_result(size == getpagesize() || (before - after) == NUM_PAGES,
|
||||
"%s: mmap\n", __func__);
|
||||
if (shmdt(map))
|
||||
ksft_exit_fail_msg("%s: shmdt: %s\n", __func__, strerror(errno));
|
||||
}
|
||||
|
||||
void sanity_checks(void)
|
||||
void find_pagesizes(void)
|
||||
{
|
||||
int i;
|
||||
unsigned long largest = getpagesize();
|
||||
int i;
|
||||
glob_t g;
|
||||
|
||||
for (i = 0; i < num_page_sizes; i++) {
|
||||
if (page_sizes[i] > largest)
|
||||
glob("/sys/kernel/mm/hugepages/hugepages-*kB", 0, NULL, &g);
|
||||
assert(g.gl_pathc <= NUM_PAGESIZES);
|
||||
for (i = 0; (i < g.gl_pathc) && (num_page_sizes < NUM_PAGESIZES); i++) {
|
||||
sscanf(g.gl_pathv[i], "/sys/kernel/mm/hugepages/hugepages-%lukB",
|
||||
&page_sizes[num_page_sizes]);
|
||||
page_sizes[num_page_sizes] <<= 10;
|
||||
ksft_print_msg("Found %luMB\n", page_sizes[i] >> 20);
|
||||
|
||||
if (page_sizes[num_page_sizes] > largest)
|
||||
largest = page_sizes[i];
|
||||
|
||||
if (read_free(page_sizes[i]) < NUM_PAGES) {
|
||||
printf("Not enough huge pages for page size %lu MB, need %u\n",
|
||||
page_sizes[i] >> 20,
|
||||
NUM_PAGES);
|
||||
exit(0);
|
||||
}
|
||||
if (read_free(page_sizes[num_page_sizes]) >= NUM_PAGES)
|
||||
num_page_sizes++;
|
||||
else
|
||||
ksft_print_msg("SKIP for size %lu MB as not enough huge pages, need %u\n",
|
||||
page_sizes[num_page_sizes] >> 20, NUM_PAGES);
|
||||
}
|
||||
globfree(&g);
|
||||
|
||||
if (read_sysfs(0, "/proc/sys/kernel/shmmax") < NUM_PAGES * largest) {
|
||||
printf("Please do echo %lu > /proc/sys/kernel/shmmax", largest * NUM_PAGES);
|
||||
exit(0);
|
||||
}
|
||||
if (read_sysfs(0, "/proc/sys/kernel/shmmax") < NUM_PAGES * largest)
|
||||
ksft_exit_fail_msg("Please do echo %lu > /proc/sys/kernel/shmmax",
|
||||
largest * NUM_PAGES);
|
||||
|
||||
#if defined(__x86_64__)
|
||||
if (largest != 1U<<30) {
|
||||
printf("No GB pages available on x86-64\n"
|
||||
ksft_exit_fail_msg("No GB pages available on x86-64\n"
|
||||
"Please boot with hugepagesz=1G hugepages=%d\n", NUM_PAGES);
|
||||
exit(0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int i;
|
||||
unsigned default_hps = default_huge_page_size();
|
||||
int i;
|
||||
|
||||
ksft_print_header();
|
||||
|
||||
find_pagesizes();
|
||||
|
||||
sanity_checks();
|
||||
if (!num_page_sizes)
|
||||
ksft_finished();
|
||||
|
||||
ksft_set_plan(2 * num_page_sizes + 3);
|
||||
|
||||
for (i = 0; i < num_page_sizes; i++) {
|
||||
unsigned long ps = page_sizes[i];
|
||||
int arg = ilog2(ps) << MAP_HUGE_SHIFT;
|
||||
printf("Testing %luMB mmap with shift %x\n", ps >> 20, arg);
|
||||
|
||||
ksft_print_msg("Testing %luMB mmap with shift %x\n", ps >> 20, arg);
|
||||
test_mmap(ps, MAP_HUGETLB | arg);
|
||||
}
|
||||
printf("Testing default huge mmap\n");
|
||||
|
||||
ksft_print_msg("Testing default huge mmap\n");
|
||||
test_mmap(default_hps, MAP_HUGETLB);
|
||||
|
||||
puts("Testing non-huge shmget");
|
||||
ksft_print_msg("Testing non-huge shmget\n");
|
||||
test_shmget(getpagesize(), 0);
|
||||
|
||||
for (i = 0; i < num_page_sizes; i++) {
|
||||
unsigned long ps = page_sizes[i];
|
||||
int arg = ilog2(ps) << SHM_HUGE_SHIFT;
|
||||
printf("Testing %luMB shmget with shift %x\n", ps >> 20, arg);
|
||||
ksft_print_msg("Testing %luMB shmget with shift %x\n", ps >> 20, arg);
|
||||
test_shmget(ps, SHM_HUGETLB | arg);
|
||||
}
|
||||
puts("default huge shmget");
|
||||
|
||||
ksft_print_msg("default huge shmget\n");
|
||||
test_shmget(default_hps, SHM_HUGETLB);
|
||||
|
||||
return 0;
|
||||
ksft_finished();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user