The definition of BUS_MCEERR_AR is not available by default on older
glibc releases. Auto-detect this capability and de-feature the
MADV_HWPOISON injection tests if the definition is not found.

Signed-off-by: Dan Williams <[email protected]>
---
This depends on "test: Add device-dax MADV_HWPOISON test"
https://patchwork.kernel.org/patch/10451131/

 configure.ac      |    5 ++
 test.h            |    8 +++
 test/Makefile.am  |    8 +++
 test/dax-pmd.c    |  130 ----------------------------------------------
 test/dax-poison.c |  149 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 170 insertions(+), 130 deletions(-)
 create mode 100644 test/dax-poison.c

diff --git a/configure.ac b/configure.ac
index 02e8679ab707..17b5a657149c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -102,6 +102,11 @@ AS_IF([test "x$enable_test" = "xyes"],
        [AC_DEFINE([ENABLE_TEST], [1], [ndctl test support])])
 AM_CONDITIONAL([ENABLE_TEST], [test "x$enable_test" = "xyes"])
 
+AC_CHECK_DECLS([BUS_MCEERR_AR], [enable_poison=yes], [], [[#include 
<signal.h>]])
+AS_IF([test "x$enable_poison" = "xyes"],
+       [AC_DEFINE([ENABLE_POISON], [1], [ndctl test poison support])])
+AM_CONDITIONAL([ENABLE_POISON], [test "x$enable_poison" = "xyes"])
+
 PKG_CHECK_MODULES([KMOD], [libkmod])
 PKG_CHECK_MODULES([UDEV], [libudev])
 PKG_CHECK_MODULES([UUID], [uuid])
diff --git a/test.h b/test.h
index ce873f51f7aa..e627785a5334 100644
--- a/test.h
+++ b/test.h
@@ -38,8 +38,16 @@ struct ndctl_ctx;
 int test_parent_uuid(int loglevel, struct ndctl_test *test, struct ndctl_ctx 
*ctx);
 int test_multi_pmem(int loglevel, struct ndctl_test *test, struct ndctl_ctx 
*ctx);
 int test_dax_directio(int dax_fd, unsigned long align, void *dax_addr, off_t 
offset);
+#ifdef ENABLE_POISON
 int test_dax_poison(int dax_fd, unsigned long align, void *dax_addr,
                off_t offset, bool fsdax);
+#else
+static inline int test_dax_poison(int dax_fd, unsigned long align,
+               void *dax_addr, off_t offset, bool fsdax)
+{
+       return 0;
+}
+#endif
 int test_dpa_alloc(int loglevel, struct ndctl_test *test, struct ndctl_ctx 
*ctx);
 int test_dsm_fail(int loglevel, struct ndctl_test *test, struct ndctl_ctx 
*ctx);
 int test_libndctl(int loglevel, struct ndctl_test *test, struct ndctl_ctx 
*ctx);
diff --git a/test/Makefile.am b/test/Makefile.am
index 496a663351c1..a9b8b3eccbbf 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -97,6 +97,7 @@ dax_dev_LDADD = $(LIBNDCTL_LIB) $(KMOD_LIBS)
 dax_pmd_SOURCES = dax-pmd.c
 hugetlb_SOURCES = hugetlb.c \
                  dax-pmd.c
+
 mmap_SOURCES = mmap.c
 dax_errors_SOURCES = dax-errors.c
 daxdev_errors_SOURCES = daxdev-errors.c \
@@ -111,6 +112,13 @@ device_dax_SOURCES = \
                ../ndctl/namespace.c \
                ../ndctl/check.c \
                ../util/json.c
+
+if ENABLE_POISON
+dax_pmd_SOURCES += dax-poison.c
+hugetlb_SOURCES += dax-poison.c
+device_dax_SOURCES += dax-poison.c
+endif
+
 device_dax_LDADD = \
                $(LIBNDCTL_LIB) \
                $(KMOD_LIBS) \
diff --git a/test/dax-pmd.c b/test/dax-pmd.c
index 65110b7c6a4c..0b4bd98edce4 100644
--- a/test/dax-pmd.c
+++ b/test/dax-pmd.c
@@ -27,7 +27,6 @@
 #include <test.h>
 #include <util/size.h>
 #include <linux/fiemap.h>
-#include <stdbool.h>
 
 #define NUM_EXTENTS 5
 #define fail() fprintf(stderr, "%s: failed at: %d (%s)\n", \
@@ -194,135 +193,6 @@ int test_dax_directio(int dax_fd, unsigned long align, 
void *dax_addr, off_t off
        return rc;
 }
 
-static sigjmp_buf sj_env;
-static int sig_mcerr_ao, sig_mcerr_ar, sig_count;
-
-static void sigbus_hdl(int sig, siginfo_t *si, void *ptr)
-{
-       switch (si->si_code) {
-       case BUS_MCEERR_AO:
-               fprintf(stderr, "%s: BUS_MCEERR_AO addr: %p len: %d\n",
-                       __func__, si->si_addr, 1 << si->si_addr_lsb);
-               sig_mcerr_ao++;
-               break;
-       case BUS_MCEERR_AR:
-               fprintf(stderr, "%s: BUS_MCEERR_AR addr: %p len: %d\n",
-                       __func__, si->si_addr, 1 << si->si_addr_lsb);
-               sig_mcerr_ar++;
-               break;
-       default:
-               sig_count++;
-               break;
-       }
-
-       siglongjmp(sj_env, 1);
-}
-
-int test_dax_poison(int dax_fd, unsigned long align, void *dax_addr,
-               off_t offset, bool fsdax)
-{
-       unsigned char *addr = MAP_FAILED;
-       struct sigaction act;
-       unsigned x = x;
-       void *buf;
-       int rc;
-
-       /*
-        * MADV_HWPOISON must be page aligned, and this routine assumes
-        * align is >= 8K
-        */
-       if (align < SZ_2M)
-               return 0;
-
-       if (posix_memalign(&buf, 4096, 4096) != 0)
-               return -ENOMEM;
-
-       memset(&act, 0, sizeof(act));
-       act.sa_sigaction = sigbus_hdl;
-       act.sa_flags = SA_SIGINFO;
-
-       if (sigaction(SIGBUS, &act, 0)) {
-               fail();
-               rc = -errno;
-               goto out;
-       }
-
-       /* dirty the block on disk to bypass the default zero page */
-       if (fsdax) {
-               rc = pwrite(dax_fd, buf, 4096, offset + align / 2);
-               if (rc < 4096) {
-                       fail();
-                       rc = -ENXIO;
-                       goto out;
-               }
-               fsync(dax_fd);
-       }
-
-       addr = mmap(dax_addr, 2*align, PROT_READ|PROT_WRITE,
-                       MAP_SHARED_VALIDATE|MAP_POPULATE|MAP_SYNC, dax_fd, 
offset);
-       if (addr == MAP_FAILED) {
-               fail();
-               rc = -errno;
-               goto out;
-       }
-
-       if (sigsetjmp(sj_env, 1)) {
-               if (sig_mcerr_ar) {
-                       fprintf(stderr, "madvise triggered 'action required' 
sigbus\n");
-                       goto clear_error;
-               } else if (sig_count) {
-                       fail();
-                       return -ENXIO;
-               }
-       }
-
-       rc = madvise(addr + align / 2, 4096, MADV_HWPOISON);
-       if (rc) {
-               fail();
-               rc = -errno;
-               goto out;
-       }
-
-       /* clear the error */
-clear_error:
-       if (!sig_mcerr_ar) {
-               fail();
-               rc = -ENXIO;
-               goto out;
-       }
-
-       if (!fsdax) {
-               rc = 0;
-               goto out;
-       }
-
-       rc = fallocate(dax_fd, FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE,
-                       offset + align / 2, 4096);
-       if (rc) {
-               fail();
-               rc = -errno;
-               goto out;
-       }
-
-       rc = pwrite(dax_fd, buf, 4096, offset + align / 2);
-       if (rc < 4096) {
-               fail();
-               rc = -ENXIO;
-               goto out;
-       }
-       fsync(dax_fd);
-
-       /* check that we can fault in the poison page */
-       x = *(volatile unsigned *) addr + align / 2;
-       rc = 0;
-
-out:
-       if (addr != MAP_FAILED)
-               munmap(addr, 2 * align);
-       free(buf);
-       return rc;
-}
-
 /* test_pmd assumes that fd references a pre-allocated + dax-capable file */
 static int test_pmd(int fd)
 {
diff --git a/test/dax-poison.c b/test/dax-poison.c
new file mode 100644
index 000000000000..7faa402e623c
--- /dev/null
+++ b/test/dax-poison.c
@@ -0,0 +1,149 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2018 Intel Corporation. All rights reserved. */
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <sys/mman.h>
+#include <linux/mman.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <stdlib.h>
+#include <linux/fs.h>
+#include <test.h>
+#include <util/size.h>
+#include <stdbool.h>
+
+#define fail() fprintf(stderr, "%s: failed at: %d (%s)\n", \
+       __func__, __LINE__, strerror(errno))
+
+static sigjmp_buf sj_env;
+static int sig_mcerr_ao, sig_mcerr_ar, sig_count;
+
+static void sigbus_hdl(int sig, siginfo_t *si, void *ptr)
+{
+       switch (si->si_code) {
+       case BUS_MCEERR_AO:
+               fprintf(stderr, "%s: BUS_MCEERR_AO addr: %p len: %d\n",
+                       __func__, si->si_addr, 1 << si->si_addr_lsb);
+               sig_mcerr_ao++;
+               break;
+       case BUS_MCEERR_AR:
+               fprintf(stderr, "%s: BUS_MCEERR_AR addr: %p len: %d\n",
+                       __func__, si->si_addr, 1 << si->si_addr_lsb);
+               sig_mcerr_ar++;
+               break;
+       default:
+               sig_count++;
+               break;
+       }
+
+       siglongjmp(sj_env, 1);
+}
+
+int test_dax_poison(int dax_fd, unsigned long align, void *dax_addr,
+               off_t offset, bool fsdax)
+{
+       unsigned char *addr = MAP_FAILED;
+       struct sigaction act;
+       unsigned x = x;
+       void *buf;
+       int rc;
+
+       /*
+        * MADV_HWPOISON must be page aligned, and this routine assumes
+        * align is >= 8K
+        */
+       if (align < SZ_2M)
+               return 0;
+
+       if (posix_memalign(&buf, 4096, 4096) != 0)
+               return -ENOMEM;
+
+       memset(&act, 0, sizeof(act));
+       act.sa_sigaction = sigbus_hdl;
+       act.sa_flags = SA_SIGINFO;
+
+       if (sigaction(SIGBUS, &act, 0)) {
+               fail();
+               rc = -errno;
+               goto out;
+       }
+
+       /* dirty the block on disk to bypass the default zero page */
+       if (fsdax) {
+               rc = pwrite(dax_fd, buf, 4096, offset + align / 2);
+               if (rc < 4096) {
+                       fail();
+                       rc = -ENXIO;
+                       goto out;
+               }
+               fsync(dax_fd);
+       }
+
+       addr = mmap(dax_addr, 2*align, PROT_READ|PROT_WRITE,
+                       MAP_SHARED_VALIDATE|MAP_POPULATE|MAP_SYNC, dax_fd, 
offset);
+       if (addr == MAP_FAILED) {
+               fail();
+               rc = -errno;
+               goto out;
+       }
+
+       if (sigsetjmp(sj_env, 1)) {
+               if (sig_mcerr_ar) {
+                       fprintf(stderr, "madvise triggered 'action required' 
sigbus\n");
+                       goto clear_error;
+               } else if (sig_count) {
+                       fail();
+                       return -ENXIO;
+               }
+       }
+
+       rc = madvise(addr + align / 2, 4096, MADV_HWPOISON);
+       if (rc) {
+               fail();
+               rc = -errno;
+               goto out;
+       }
+
+       /* clear the error */
+clear_error:
+       if (!sig_mcerr_ar) {
+               fail();
+               rc = -ENXIO;
+               goto out;
+       }
+
+       if (!fsdax) {
+               rc = 0;
+               goto out;
+       }
+
+       rc = fallocate(dax_fd, FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE,
+                       offset + align / 2, 4096);
+       if (rc) {
+               fail();
+               rc = -errno;
+               goto out;
+       }
+
+       rc = pwrite(dax_fd, buf, 4096, offset + align / 2);
+       if (rc < 4096) {
+               fail();
+               rc = -ENXIO;
+               goto out;
+       }
+       fsync(dax_fd);
+
+       /* check that we can fault in the poison page */
+       x = *(volatile unsigned *) addr + align / 2;
+       rc = 0;
+
+out:
+       if (addr != MAP_FAILED)
+               munmap(addr, 2 * align);
+       free(buf);
+       return rc;
+}

_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimm

Reply via email to