diff options
Diffstat (limited to 'tools/testing/selftests/mm/gup_test.c')
| -rw-r--r-- | tools/testing/selftests/mm/gup_test.c | 96 |
1 files changed, 43 insertions, 53 deletions
diff --git a/tools/testing/selftests/mm/gup_test.c b/tools/testing/selftests/mm/gup_test.c index ec2229136384..fb8f9ae49efa 100644 --- a/tools/testing/selftests/mm/gup_test.c +++ b/tools/testing/selftests/mm/gup_test.c @@ -1,3 +1,4 @@ +#define __SANE_USERSPACE_TYPES__ // Use ll64 #include <fcntl.h> #include <errno.h> #include <stdio.h> @@ -11,14 +12,13 @@ #include <pthread.h> #include <assert.h> #include <mm/gup_test.h> -#include "../kselftest.h" +#include "kselftest.h" #include "vm_util.h" #define MB (1UL << 20) -/* Just the flags we need, copied from mm.h: */ +/* Just the flags we need, copied from the kernel internals. */ #define FOLL_WRITE 0x01 /* check pte is writable */ -#define FOLL_TOUCH 0x02 /* mark page accessed */ #define GUP_TEST_FILE "/sys/kernel/debug/gup_test" @@ -50,39 +50,41 @@ static char *cmd_to_str(unsigned long cmd) void *gup_thread(void *data) { struct gup_test gup = *(struct gup_test *)data; - int i; + int i, status; /* Only report timing information on the *_BENCHMARK commands: */ if ((cmd == PIN_FAST_BENCHMARK) || (cmd == GUP_FAST_BENCHMARK) || (cmd == PIN_LONGTERM_BENCHMARK)) { for (i = 0; i < repeats; i++) { gup.size = size; - if (ioctl(gup_fd, cmd, &gup)) - perror("ioctl"), exit(1); + status = ioctl(gup_fd, cmd, &gup); + if (status) + break; pthread_mutex_lock(&print_mutex); - printf("%s: Time: get:%lld put:%lld us", - cmd_to_str(cmd), gup.get_delta_usec, - gup.put_delta_usec); + ksft_print_msg("%s: Time: get:%lld put:%lld us", + cmd_to_str(cmd), gup.get_delta_usec, + gup.put_delta_usec); if (gup.size != size) - printf(", truncated (size: %lld)", gup.size); - printf("\n"); + ksft_print_msg(", truncated (size: %lld)", gup.size); + ksft_print_msg("\n"); pthread_mutex_unlock(&print_mutex); } } else { gup.size = size; - if (ioctl(gup_fd, cmd, &gup)) { - perror("ioctl"); - exit(1); - } + status = ioctl(gup_fd, cmd, &gup); + if (status) + goto return_; pthread_mutex_lock(&print_mutex); - printf("%s: done\n", cmd_to_str(cmd)); + ksft_print_msg("%s: done\n", cmd_to_str(cmd)); if (gup.size != size) - printf("Truncated (size: %lld)\n", gup.size); + ksft_print_msg("Truncated (size: %lld)\n", gup.size); pthread_mutex_unlock(&print_mutex); } +return_: + ksft_test_result(!status, "ioctl status %d\n", status); return NULL; } @@ -90,7 +92,7 @@ int main(int argc, char **argv) { struct gup_test gup = { 0 }; int filed, i, opt, nr_pages = 1, thp = -1, write = 1, nthreads = 1, ret; - int flags = MAP_PRIVATE, touch = 0; + int flags = MAP_PRIVATE; char *file = "/dev/zero"; pthread_t *tid; char *p; @@ -136,6 +138,8 @@ int main(int argc, char **argv) break; case 'n': nr_pages = atoi(optarg); + if (nr_pages < 0) + nr_pages = size / psize(); break; case 't': thp = 1; @@ -165,12 +169,8 @@ int main(int argc, char **argv) case 'H': flags |= (MAP_HUGETLB | MAP_ANONYMOUS); break; - case 'z': - /* fault pages in gup, do not fault in userland */ - touch = 1; - break; default: - return -1; + ksft_exit_fail_msg("Wrong argument\n"); } } @@ -198,11 +198,12 @@ int main(int argc, char **argv) } } - filed = open(file, O_RDWR|O_CREAT); - if (filed < 0) { - perror("open"); - exit(filed); - } + ksft_print_header(); + ksft_set_plan(nthreads); + + filed = open(file, O_RDWR|O_CREAT, 0664); + if (filed < 0) + ksft_exit_fail_msg("Unable to open %s: %s\n", file, strerror(errno)); gup.nr_pages_per_call = nr_pages; if (write) @@ -213,27 +214,24 @@ int main(int argc, char **argv) switch (errno) { case EACCES: if (getuid()) - printf("Please run this test as root\n"); + ksft_print_msg("Please run this test as root\n"); break; case ENOENT: - if (opendir("/sys/kernel/debug") == NULL) { - printf("mount debugfs at /sys/kernel/debug\n"); - break; - } - printf("check if CONFIG_GUP_TEST is enabled in kernel config\n"); + if (opendir("/sys/kernel/debug") == NULL) + ksft_print_msg("mount debugfs at /sys/kernel/debug\n"); + ksft_print_msg("check if CONFIG_GUP_TEST is enabled in kernel config\n"); break; default: - perror("failed to open " GUP_TEST_FILE); + ksft_print_msg("failed to open %s: %s\n", GUP_TEST_FILE, strerror(errno)); break; } - exit(KSFT_SKIP); + ksft_test_result_skip("Please run this test as root\n"); + ksft_exit_pass(); } p = mmap(NULL, size, PROT_READ | PROT_WRITE, flags, filed, 0); - if (p == MAP_FAILED) { - perror("mmap"); - exit(1); - } + if (p == MAP_FAILED) + ksft_exit_fail_msg("mmap: %s\n", strerror(errno)); gup.addr = (unsigned long)p; if (thp == 1) @@ -241,18 +239,9 @@ int main(int argc, char **argv) else if (thp == 0) madvise(p, size, MADV_NOHUGEPAGE); - /* - * FOLL_TOUCH, in gup_test, is used as an either/or case: either - * fault pages in from the kernel via FOLL_TOUCH, or fault them - * in here, from user space. This allows comparison of performance - * between those two cases. - */ - if (touch) { - gup.gup_flags |= FOLL_TOUCH; - } else { - for (; (unsigned long)p < gup.addr + size; p += psize()) - p[0] = 0; - } + /* Fault them in here, from user space. */ + for (; (unsigned long)p < gup.addr + size; p += psize()) + p[0] = 0; tid = malloc(sizeof(pthread_t) * nthreads); assert(tid); @@ -264,7 +253,8 @@ int main(int argc, char **argv) ret = pthread_join(tid[i], NULL); assert(ret == 0); } + free(tid); - return 0; + ksft_exit_pass(); } |
