Commit b38bd9b2 authored by Muhammad Usama Anjum's avatar Muhammad Usama Anjum Committed by Andrew Morton

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.comSigned-off-by: default avatarMuhammad Usama Anjum <usama.anjum@collabora.com>
Cc: Shuah Khan <shuah@kernel.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent 73588704
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
Before running this huge pages for each huge page size must have been Before running this huge pages for each huge page size must have been
reserved. reserved.
For large pages beyond MAX_PAGE_ORDER (like 1GB on x86) boot options must 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. Also shmmax must be increased.
And you need to run as root to work around some weird permissions in shm. And you need to run as root to work around some weird permissions in shm.
And nothing using huge pages should run in parallel. And nothing using huge pages should run in parallel.
...@@ -26,8 +26,7 @@ ...@@ -26,8 +26,7 @@
#include <stdarg.h> #include <stdarg.h>
#include <string.h> #include <string.h>
#include "vm_util.h" #include "vm_util.h"
#include "../kselftest.h"
#define err(x) perror(x), exit(1)
#define MAP_HUGE_2MB (21 << MAP_HUGE_SHIFT) #define MAP_HUGE_2MB (21 << MAP_HUGE_SHIFT)
#define MAP_HUGE_1GB (30 << MAP_HUGE_SHIFT) #define MAP_HUGE_1GB (30 << MAP_HUGE_SHIFT)
...@@ -44,11 +43,8 @@ ...@@ -44,11 +43,8 @@
#define SHM_HUGE_1GB (30 << SHM_HUGE_SHIFT) #define SHM_HUGE_1GB (30 << SHM_HUGE_SHIFT)
#define NUM_PAGESIZES 5 #define NUM_PAGESIZES 5
#define NUM_PAGES 4 #define NUM_PAGES 4
#define Dprintf(fmt...) // printf(fmt)
unsigned long page_sizes[NUM_PAGESIZES]; unsigned long page_sizes[NUM_PAGESIZES];
int num_page_sizes; int num_page_sizes;
...@@ -60,28 +56,15 @@ int ilog2(unsigned long v) ...@@ -60,28 +56,15 @@ int ilog2(unsigned long v)
return l; 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) void show(unsigned long ps)
{ {
char buf[100]; char buf[100];
if (ps == getpagesize()) if (ps == getpagesize())
return; return;
printf("%luMB: ", ps >> 20);
ksft_print_msg("%luMB: ", ps >> 20);
fflush(stdout); fflush(stdout);
snprintf(buf, sizeof buf, snprintf(buf, sizeof buf,
"cat /sys/kernel/mm/hugepages/hugepages-%lukB/free_hugepages", "cat /sys/kernel/mm/hugepages/hugepages-%lukB/free_hugepages",
...@@ -105,7 +88,7 @@ unsigned long read_sysfs(int warn, char *fmt, ...) ...@@ -105,7 +88,7 @@ unsigned long read_sysfs(int warn, char *fmt, ...)
f = fopen(buf, "r"); f = fopen(buf, "r");
if (!f) { if (!f) {
if (warn) if (warn)
printf("missing %s\n", buf); ksft_print_msg("missing %s\n", buf);
return 0; return 0;
} }
if (getline(&line, &linelen, f) > 0) { if (getline(&line, &linelen, f) > 0) {
...@@ -127,115 +110,135 @@ void test_mmap(unsigned long size, unsigned flags) ...@@ -127,115 +110,135 @@ void test_mmap(unsigned long size, unsigned flags)
{ {
char *map; char *map;
unsigned long before, after; unsigned long before, after;
int err;
before = read_free(size); before = read_free(size);
map = mmap(NULL, size*NUM_PAGES, PROT_READ|PROT_WRITE, map = mmap(NULL, size*NUM_PAGES, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS|MAP_HUGETLB|flags, -1, 0); 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); memset(map, 0xff, size*NUM_PAGES);
after = read_free(size); 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); show(size);
err = munmap(map, size * NUM_PAGES); ksft_test_result(size == getpagesize() || (before - after) == NUM_PAGES,
assert(!err); "%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) void test_shmget(unsigned long size, unsigned flags)
{ {
int id; int id;
unsigned long before, after; unsigned long before, after;
int err; struct shm_info i;
char *map;
before = read_free(size); before = read_free(size);
id = shmget(IPC_PRIVATE, size * NUM_PAGES, IPC_CREAT|0600|flags); id = shmget(IPC_PRIVATE, size * NUM_PAGES, IPC_CREAT|0600|flags);
if (id < 0) err("shmget"); if (id < 0) {
if (errno == EPERM) {
struct shm_info i; ksft_test_result_skip("shmget requires root privileges: %s\n",
if (shmctl(id, SHM_INFO, (void *)&i) < 0) err("shmctl"); strerror(errno));
Dprintf("alloc %lu res %lu\n", i.shm_tot, i.shm_rss); return;
}
ksft_exit_fail_msg("shmget: %s\n", strerror(errno));
}
if (shmctl(id, SHM_INFO, (void *)&i) < 0)
ksft_exit_fail_msg("shmctl: %s\n", strerror(errno));
Dprintf("id %d\n", id); map = shmat(id, NULL, 0600);
char *map = shmat(id, NULL, 0600); if (map == MAP_FAILED)
if (map == (char*)-1) err("shmat"); ksft_exit_fail_msg("shmat: %s\n", strerror(errno));
shmctl(id, IPC_RMID, NULL); shmctl(id, IPC_RMID, NULL);
memset(map, 0xff, size*NUM_PAGES); memset(map, 0xff, size*NUM_PAGES);
after = read_free(size); 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); show(size);
err = shmdt(map); ksft_test_result(size == getpagesize() || (before - after) == NUM_PAGES,
assert(!err); "%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(); unsigned long largest = getpagesize();
int i;
glob_t g;
for (i = 0; i < num_page_sizes; i++) { glob("/sys/kernel/mm/hugepages/hugepages-*kB", 0, NULL, &g);
if (page_sizes[i] > largest) 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]; largest = page_sizes[i];
if (read_free(page_sizes[i]) < NUM_PAGES) { if (read_free(page_sizes[num_page_sizes]) >= NUM_PAGES)
printf("Not enough huge pages for page size %lu MB, need %u\n", num_page_sizes++;
page_sizes[i] >> 20, else
NUM_PAGES); ksft_print_msg("SKIP for size %lu MB as not enough huge pages, need %u\n",
exit(0); page_sizes[num_page_sizes] >> 20, NUM_PAGES);
}
} }
globfree(&g);
if (read_sysfs(0, "/proc/sys/kernel/shmmax") < NUM_PAGES * largest) { if (read_sysfs(0, "/proc/sys/kernel/shmmax") < NUM_PAGES * largest)
printf("Please do echo %lu > /proc/sys/kernel/shmmax", largest * NUM_PAGES); ksft_exit_fail_msg("Please do echo %lu > /proc/sys/kernel/shmmax",
exit(0); largest * NUM_PAGES);
}
#if defined(__x86_64__) #if defined(__x86_64__)
if (largest != 1U<<30) { 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); "Please boot with hugepagesz=1G hugepages=%d\n", NUM_PAGES);
exit(0);
} }
#endif #endif
} }
int main(void) int main(void)
{ {
int i;
unsigned default_hps = default_huge_page_size(); unsigned default_hps = default_huge_page_size();
int i;
ksft_print_header();
find_pagesizes(); 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++) { for (i = 0; i < num_page_sizes; i++) {
unsigned long ps = page_sizes[i]; unsigned long ps = page_sizes[i];
int arg = ilog2(ps) << MAP_HUGE_SHIFT; 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); 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); test_mmap(default_hps, MAP_HUGETLB);
puts("Testing non-huge shmget"); ksft_print_msg("Testing non-huge shmget\n");
test_shmget(getpagesize(), 0); test_shmget(getpagesize(), 0);
for (i = 0; i < num_page_sizes; i++) { for (i = 0; i < num_page_sizes; i++) {
unsigned long ps = page_sizes[i]; unsigned long ps = page_sizes[i];
int arg = ilog2(ps) << SHM_HUGE_SHIFT; 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); test_shmget(ps, SHM_HUGETLB | arg);
} }
puts("default huge shmget");
ksft_print_msg("default huge shmget\n");
test_shmget(default_hps, SHM_HUGETLB); test_shmget(default_hps, SHM_HUGETLB);
return 0; ksft_finished();
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment