diff options
Diffstat (limited to 'tools/testing/selftests/mm/compaction_test.c')
| -rw-r--r-- | tools/testing/selftests/mm/compaction_test.c | 158 |
1 files changed, 42 insertions, 116 deletions
diff --git a/tools/testing/selftests/mm/compaction_test.c b/tools/testing/selftests/mm/compaction_test.c index 30209c40b697..30d4ace7155a 100644 --- a/tools/testing/selftests/mm/compaction_test.c +++ b/tools/testing/selftests/mm/compaction_test.c @@ -17,6 +17,7 @@ #include <string.h> #include "kselftest.h" +#include "hugepage_settings.h" #define MAP_SIZE_MB 100 #define MAP_SIZE (MAP_SIZE_MB * 1024 * 1024) @@ -28,30 +29,34 @@ struct map_list { int read_memory_info(unsigned long *memfree, unsigned long *hugepagesize) { - char buffer[256] = {0}; - char *cmd = "cat /proc/meminfo | grep -i memfree | grep -o '[0-9]*'"; - FILE *cmdfile = popen(cmd, "r"); - - if (!(fgets(buffer, sizeof(buffer), cmdfile))) { - ksft_print_msg("Failed to read meminfo: %s\n", strerror(errno)); + char buffer[256]; + int found = 0; + FILE *file; + int ret = -1; + + file = fopen("/proc/meminfo", "r"); + if (!file) { + ksft_print_msg("Failed to open /proc/meminfo: %s\n", + strerror(errno)); return -1; } - pclose(cmdfile); - - *memfree = atoll(buffer); - cmd = "cat /proc/meminfo | grep -i hugepagesize | grep -o '[0-9]*'"; - cmdfile = popen(cmd, "r"); - - if (!(fgets(buffer, sizeof(buffer), cmdfile))) { - ksft_print_msg("Failed to read meminfo: %s\n", strerror(errno)); - return -1; + while (fgets(buffer, sizeof(buffer), file) && found != 2) { + if (sscanf(buffer, "MemFree: %lu kB", memfree) == 1 || + sscanf(buffer, "Hugepagesize: %lu kB", hugepagesize) == 1) + found++; } - pclose(cmdfile); - *hugepagesize = atoll(buffer); + if (ferror(file)) + ksft_print_msg("Failed to read /proc/meminfo: %s\n", + strerror(errno)); + else if (found != 2) + ksft_print_msg("Failed to parse /proc/meminfo\n"); + else + ret = 0; - return 0; + fclose(file); + return ret; } int prereq(void) @@ -82,124 +87,44 @@ int prereq(void) return -1; } -int check_compaction(unsigned long mem_free, unsigned long hugepage_size, - unsigned long initial_nr_hugepages) +int check_compaction(unsigned long mem_free, unsigned long hugepage_size) { - unsigned long nr_hugepages_ul; - int fd, ret = -1; + unsigned long nr_hugepages; int compaction_index = 0; - char nr_hugepages[20] = {0}; - char init_nr_hugepages[24] = {0}; - char target_nr_hugepages[24] = {0}; - int slen; - - snprintf(init_nr_hugepages, sizeof(init_nr_hugepages), - "%lu", initial_nr_hugepages); + int ret = -1; /* We want to test with 80% of available memory. Else, OOM killer comes in to play */ mem_free = mem_free * 0.8; - fd = open("/proc/sys/vm/nr_hugepages", O_RDWR | O_NONBLOCK); - if (fd < 0) { - ksft_print_msg("Failed to open /proc/sys/vm/nr_hugepages: %s\n", - strerror(errno)); - ret = -1; - goto out; - } - /* * Request huge pages for about half of the free memory. The Kernel * will allocate as much as it can, and we expect it will get at least 1/3 */ - nr_hugepages_ul = mem_free / hugepage_size / 2; - snprintf(target_nr_hugepages, sizeof(target_nr_hugepages), - "%lu", nr_hugepages_ul); - - slen = strlen(target_nr_hugepages); - if (write(fd, target_nr_hugepages, slen) != slen) { - ksft_print_msg("Failed to write %lu to /proc/sys/vm/nr_hugepages: %s\n", - nr_hugepages_ul, strerror(errno)); - goto close_fd; - } - - lseek(fd, 0, SEEK_SET); - - if (read(fd, nr_hugepages, sizeof(nr_hugepages)) <= 0) { - ksft_print_msg("Failed to re-read from /proc/sys/vm/nr_hugepages: %s\n", - strerror(errno)); - goto close_fd; - } + nr_hugepages = mem_free / hugepage_size / 2; + hugetlb_set_nr_default_pages(nr_hugepages); /* We should have been able to request at least 1/3 rd of the memory in huge pages */ - nr_hugepages_ul = strtoul(nr_hugepages, NULL, 10); - if (!nr_hugepages_ul) { + nr_hugepages = hugetlb_nr_default_pages(); + if (!nr_hugepages) { ksft_print_msg("ERROR: No memory is available as huge pages\n"); - goto close_fd; - } - compaction_index = mem_free/(nr_hugepages_ul * hugepage_size); - - lseek(fd, 0, SEEK_SET); - - if (write(fd, init_nr_hugepages, strlen(init_nr_hugepages)) - != strlen(init_nr_hugepages)) { - ksft_print_msg("Failed to write value to /proc/sys/vm/nr_hugepages: %s\n", - strerror(errno)); - goto close_fd; + goto out; } + compaction_index = mem_free/(nr_hugepages * hugepage_size); - ksft_print_msg("Number of huge pages allocated = %lu\n", - nr_hugepages_ul); + ksft_print_msg("Number of huge pages allocated = %lu\n", nr_hugepages); if (compaction_index > 3) { ksft_print_msg("ERROR: Less than 1/%d of memory is available\n" "as huge pages\n", compaction_index); - goto close_fd; - } - - ret = 0; - - close_fd: - close(fd); - out: - ksft_test_result(ret == 0, "check_compaction\n"); - return ret; -} - -int set_zero_hugepages(unsigned long *initial_nr_hugepages) -{ - int fd, ret = -1; - char nr_hugepages[20] = {0}; - - fd = open("/proc/sys/vm/nr_hugepages", O_RDWR | O_NONBLOCK); - if (fd < 0) { - ksft_print_msg("Failed to open /proc/sys/vm/nr_hugepages: %s\n", - strerror(errno)); goto out; } - if (read(fd, nr_hugepages, sizeof(nr_hugepages)) <= 0) { - ksft_print_msg("Failed to read from /proc/sys/vm/nr_hugepages: %s\n", - strerror(errno)); - goto close_fd; - } - lseek(fd, 0, SEEK_SET); - - /* Start with the initial condition of 0 huge pages */ - if (write(fd, "0", sizeof(char)) != sizeof(char)) { - ksft_print_msg("Failed to write 0 to /proc/sys/vm/nr_hugepages: %s\n", - strerror(errno)); - goto close_fd; - } - - *initial_nr_hugepages = strtoul(nr_hugepages, NULL, 10); ret = 0; - close_fd: - close(fd); - out: + ksft_test_result(ret == 0, "check_compaction\n"); return ret; } @@ -212,18 +137,17 @@ int main(int argc, char **argv) unsigned long mem_free = 0; unsigned long hugepage_size = 0; long mem_fragmentable_MB = 0; - unsigned long initial_nr_hugepages; ksft_print_header(); if (prereq() || geteuid()) ksft_exit_skip("Prerequisites unsatisfied\n"); - ksft_set_plan(1); - /* Start the test without hugepages reducing mem_free */ - if (set_zero_hugepages(&initial_nr_hugepages)) - ksft_exit_fail(); + if (!hugetlb_setup_default_exact(0)) + ksft_exit_skip("Could not reset nr_hugepages\n"); + + ksft_set_plan(1); lim.rlim_cur = RLIM_INFINITY; lim.rlim_max = RLIM_INFINITY; @@ -261,6 +185,9 @@ int main(int argc, char **argv) mem_fragmentable_MB -= MAP_SIZE_MB; } + /* Unmap every other entry in the list to create fragmentation with + * locked pages before invoking check_compaction(). + */ for (entry = list; entry != NULL; entry = entry->next) { munmap(entry->map, MAP_SIZE); if (!entry->next) @@ -268,8 +195,7 @@ int main(int argc, char **argv) entry = entry->next; } - if (check_compaction(mem_free, hugepage_size, - initial_nr_hugepages) == 0) + if (check_compaction(mem_free, hugepage_size) == 0) ksft_exit_pass(); ksft_exit_fail(); |
