pfnmap currently checks the target file in FIXTURE_SETUP(pfnmap),
meaning once for every test, and skips the test if any check fails.

The target file is the same for every test so this is a little
overkill. More importantly, this approach means that the whole suite
will report PASS even if all the tests are skipped because kernel
configuration (e.g. CONFIG_STRICT_DEVMEM=y) prevented /dev/mem from
being mapped, for instance.

Let's ensure that KSFT_SKIP is returned as exit code if any check
fails by performing the checks in pfnmap_init(), run once. That
function also takes care of finding the offset of the pages to be
mapped and saves it in a global. The file is still mapped/unmapped
for every test, as some of them modify the mapping.

Signed-off-by: Kevin Brodsky <[email protected]>
---
 tools/testing/selftests/mm/pfnmap.c | 81 ++++++++++++++++++++---------
 1 file changed, 55 insertions(+), 26 deletions(-)

diff --git a/tools/testing/selftests/mm/pfnmap.c 
b/tools/testing/selftests/mm/pfnmap.c
index 35b0e3ed54cd..e41d5464130b 100644
--- a/tools/testing/selftests/mm/pfnmap.c
+++ b/tools/testing/selftests/mm/pfnmap.c
@@ -25,8 +25,11 @@
 #include "kselftest_harness.h"
 #include "vm_util.h"
 
+#define DEV_MEM_NPAGES 2
+
 static sigjmp_buf sigjmp_buf_env;
 static char *file = "/dev/mem";
+static off_t file_offset;
 
 static void signal_handler(int sig)
 {
@@ -88,7 +91,7 @@ static int find_ram_target(off_t *offset,
                        break;
 
                /* We need two pages. */
-               if (end > start + 2 * pagesize) {
+               if (end > start + DEV_MEM_NPAGES * pagesize) {
                        fclose(file);
                        *offset = start;
                        return 0;
@@ -97,9 +100,49 @@ static int find_ram_target(off_t *offset,
        return -ENOENT;
 }
 
+static void pfnmap_init(void)
+{
+       size_t pagesize = getpagesize();
+       size_t size = DEV_MEM_NPAGES * pagesize;
+       int fd;
+       void *addr;
+
+       if (strncmp(file, "/dev/mem", strlen("/dev/mem")) == 0) {
+               int err = find_ram_target(&file_offset, pagesize);
+
+               if (err)
+                       ksft_exit_skip("Cannot find ram target in 
'/proc/iomem': %s\n",
+                                      strerror(-err));
+       } else {
+               file_offset = 0;
+       }
+
+       /*
+        * Make sure we can open and map the file, and perform some basic
+        * checks; skip the whole suite if anything goes wrong.
+        * A fresh mapping is then created for every test case by
+        * FIXTURE_SETUP(pfnmap).
+        */
+       fd = open(file, O_RDONLY);
+       if (fd < 0)
+               ksft_exit_skip("Cannot open '%s': %s\n", file, strerror(errno));
+
+       addr = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, file_offset);
+       if (addr == MAP_FAILED)
+               ksft_exit_skip("Cannot mmap '%s': %s\n", file, strerror(errno));
+
+       if (!check_vmflag_pfnmap(addr))
+               ksft_exit_skip("Invalid file: '%s'. Not pfnmap'ed\n", file);
+
+       if (test_read_access(addr, size))
+               ksft_exit_skip("Cannot read-access mmap'ed '%s'\n", file);
+
+       munmap(addr, size);
+       close(fd);
+}
+
 FIXTURE(pfnmap)
 {
-       off_t offset;
        size_t pagesize;
        int dev_mem_fd;
        char *addr1;
@@ -112,31 +155,13 @@ FIXTURE_SETUP(pfnmap)
 {
        self->pagesize = getpagesize();
 
-       if (strncmp(file, "/dev/mem", strlen("/dev/mem")) == 0) {
-               /* We'll require two physical pages throughout our tests ... */
-               if (find_ram_target(&self->offset, self->pagesize))
-                       SKIP(return,
-                                  "Cannot find ram target in '/proc/iomem'\n");
-       } else {
-               self->offset = 0;
-       }
-
        self->dev_mem_fd = open(file, O_RDONLY);
-       if (self->dev_mem_fd < 0)
-               SKIP(return, "Cannot open '%s'\n", file);
+       ASSERT_GE(self->dev_mem_fd, 0);
 
-       self->size1 = self->pagesize * 2;
+       self->size1 = DEV_MEM_NPAGES * self->pagesize;
        self->addr1 = mmap(NULL, self->size1, PROT_READ, MAP_SHARED,
-                          self->dev_mem_fd, self->offset);
-       if (self->addr1 == MAP_FAILED)
-               SKIP(return, "Cannot mmap '%s'\n", file);
-
-       if (!check_vmflag_pfnmap(self->addr1))
-               SKIP(return, "Invalid file: '%s'. Not pfnmap'ed\n", file);
-
-       /* ... and want to be able to read from them. */
-       if (test_read_access(self->addr1, self->size1))
-               SKIP(return, "Cannot read-access mmap'ed '%s'\n", file);
+                          self->dev_mem_fd, file_offset);
+       ASSERT_NE(self->addr1, MAP_FAILED);
 
        self->size2 = 0;
        self->addr2 = MAP_FAILED;
@@ -189,7 +214,7 @@ TEST_F(pfnmap, munmap_split)
         */
        self->size2 = self->pagesize;
        self->addr2 = mmap(NULL, self->pagesize, PROT_READ, MAP_SHARED,
-                          self->dev_mem_fd, self->offset);
+                          self->dev_mem_fd, file_offset);
        ASSERT_NE(self->addr2, MAP_FAILED);
 }
 
@@ -258,8 +283,12 @@ int main(int argc, char **argv)
                if (strcmp(argv[i], "--") == 0) {
                        if (i + 1 < argc && strlen(argv[i + 1]) > 0)
                                file = argv[i + 1];
-                       return test_harness_run(i, argv);
+                       argc = i;
+                       break;
                }
        }
+
+       pfnmap_init();
+
        return test_harness_run(argc, argv);
 }
-- 
2.51.2


Reply via email to