linux-nvdimm.lists.01.org archive mirror
 help / color / mirror / Atom feed
* [ndctl PATCH] test: add a MADV_HWPOISON test
@ 2018-05-22 16:19 Dan Williams
  2018-05-23 17:45 ` Verma, Vishal L
  0 siblings, 1 reply; 3+ messages in thread
From: Dan Williams @ 2018-05-22 16:19 UTC (permalink / raw)
  To: linux-nvdimm

Check that injecting soft-poison to a dax mapping results in SIGBUS with
the expected BUS_MCEERR_AR siginfo data.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 test/dax-pmd.c |  130 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 126 insertions(+), 4 deletions(-)

diff --git a/test/dax-pmd.c b/test/dax-pmd.c
index 65bee6ffe907..abff4f9fd199 100644
--- a/test/dax-pmd.c
+++ b/test/dax-pmd.c
@@ -12,6 +12,7 @@
  */
 #include <stdio.h>
 #include <unistd.h>
+#include <setjmp.h>
 #include <sys/mman.h>
 #include <linux/mman.h>
 #include <sys/types.h>
@@ -192,15 +193,130 @@ 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);
+}
+
+static int test_dax_poison(int dax_fd, unsigned long align, void *dax_addr,
+		off_t offset)
+{
+	unsigned char *addr = MAP_FAILED;
+	struct sigaction act;
+	unsigned x = x;
+	void *buf;
+	int rc;
+
+	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 */
+	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;
+	}
+
+	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)
 {
-	unsigned long long m_align, p_align;
+	unsigned long long m_align, p_align, pmd_off;
 	struct fiemap_extent *ext;
+	void *base, *pmd_addr;
 	struct fiemap *map;
 	int rc = -ENXIO;
 	unsigned long i;
-	void *base;
 
 	if (fd < 0) {
 		fail();
@@ -249,9 +365,15 @@ static int test_pmd(int fd)
 	m_align = ALIGN(base, HPAGE_SIZE) - ((unsigned long) base);
 	p_align = ALIGN(ext->fe_physical, HPAGE_SIZE) - ext->fe_physical;
 
-	rc = test_dax_directio(fd, HPAGE_SIZE, (char *) base + m_align,
-			ext->fe_logical + p_align);
+	pmd_addr = (char *) base + m_align;
+	pmd_off =  ext->fe_logical + p_align;
+	rc = test_dax_directio(fd, HPAGE_SIZE, pmd_addr, pmd_off);
+	if (rc)
+		goto err_directio;
+
+	rc = test_dax_poison(fd, HPAGE_SIZE, pmd_addr, pmd_off);
 
+ err_directio:
  err_extent:
  err_mmap:
 	free(map);

_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2018-05-23 17:50 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-05-22 16:19 [ndctl PATCH] test: add a MADV_HWPOISON test Dan Williams
2018-05-23 17:45 ` Verma, Vishal L
2018-05-23 17:50   ` Dan Williams

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).