A recent kernel bug report [1], highlighted the need to test page structure mappings and direct-i/o for device dax. Repurpose the existing filesystem-dax test for this case.
[1]: https://lists.01.org/pipermail/linux-nvdimm/2016-August/006704.html Cc: Toshi Kani <[email protected]> Signed-off-by: Dan Williams <[email protected]> --- test/Makefile.am | 1 test/dax-pmd.c | 147 +++++++++++++++++++++++++++++------------------------ test/device-dax.c | 10 ++++ 3 files changed, 92 insertions(+), 66 deletions(-) diff --git a/test.h b/test.h index 331d4131e2c7..2940ac0f7396 100644 --- a/test.h +++ b/test.h @@ -16,7 +16,7 @@ void builtin_xaction_namespace_reset(void); struct ndctl_ctx; int test_parent_uuid(int loglevel, struct ndctl_test *test, struct ndctl_ctx *ctx); -int test_direct_io(int loglevel, struct ndctl_test *test, struct ndctl_ctx *ctx); +int test_dax_directio(int dax_fd, void *dax_addr, off_t offset); int test_dpa_alloc(int loglevel, struct ndctl_test *test, struct ndctl_ctx *ctx); int test_libndctl(int loglevel, struct ndctl_test *test, struct ndctl_ctx *ctx); int test_blk_namespaces(int loglevel, struct ndctl_test *test, struct ndctl_ctx *ctx); diff --git a/test/Makefile.am b/test/Makefile.am index d13c138bb28a..f0240fe5883a 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -60,6 +60,7 @@ dax_errors_SOURCES = dax-errors.c device_dax_SOURCES = \ device-dax.c \ dax-dev.c \ + dax-pmd.c \ core.c \ ../ndctl/builtin-xaction-namespace.c \ ../ndctl/util/json.c diff --git a/test/dax-pmd.c b/test/dax-pmd.c index ff0c70e9ea47..47f254e398b2 100644 --- a/test/dax-pmd.c +++ b/test/dax-pmd.c @@ -10,84 +10,35 @@ #include <sys/ioctl.h> #include <stdlib.h> #include <linux/fs.h> +#include <test.h> #include <linux/fiemap.h> #define NUM_EXTENTS 5 #define HPAGE_SIZE (2 << 20) #define ALIGN(x, a) ((((unsigned long long) x) + (a - 1)) & ~(a - 1)) #define fail() fprintf(stderr, "%s: failed at: %d\n", __func__, __LINE__) -#define faili(i) fprintf(stderr, "%s: failed at: %d: %ld\n", __func__, __LINE__, i) +#define faili(i) fprintf(stderr, "%s: failed at: %d: %d\n", __func__, __LINE__, i) #define TEST_FILE "test_dax_data" -/* test_pmd assumes that fd references a pre-allocated + dax-capable file */ -static int test_pmd(int fd) +int test_dax_directio(int dax_fd, void *dax_addr, off_t offset) { - unsigned long long m_align, p_align; - int fd2 = -1, rc = -ENXIO; - struct fiemap_extent *ext; - void *base, *addr, *buf; - struct fiemap *map; - unsigned long i; - - if (fd < 0) { - fail(); - return -ENXIO; - } - - map = calloc(1, sizeof(struct fiemap) - + sizeof(struct fiemap_extent) * NUM_EXTENTS); - if (!map) { - fail(); - return -ENXIO; - } + int i, rc = -ENXIO; + void *buf; if (posix_memalign(&buf, 4096, 4096) != 0) - goto err_memalign; - - base = mmap(NULL, 4*HPAGE_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); - if (base == MAP_FAILED) { - fail(); - goto err_mmap; - } - munmap(base, 4*HPAGE_SIZE); - - map->fm_start = 0; - map->fm_length = -1; - map->fm_extent_count = NUM_EXTENTS; - rc = ioctl(fd, FS_IOC_FIEMAP, map); - if (rc < 0) { - fail(); - goto err_extent; - } - - for (i = 0; i < map->fm_mapped_extents; i++) { - ext = &map->fm_extents[i]; - fprintf(stderr, "[%ld]: l: %llx p: %llx len: %llx flags: %x\n", - i, ext->fe_logical, ext->fe_physical, - ext->fe_length, ext->fe_flags); - if (ext->fe_length > 2 * HPAGE_SIZE) { - fprintf(stderr, "found potential huge extent\n"); - break; - } - } - - if (i >= map->fm_mapped_extents) { - fail(); - goto err_extent; - } - - m_align = ALIGN(base, HPAGE_SIZE) - ((unsigned long) base); - p_align = ALIGN(ext->fe_physical, HPAGE_SIZE) - ext->fe_physical; + return -ENOMEM; for (i = 0; i < 3; i++) { - rc = -ENXIO; - addr = mmap((char *) base + m_align, 2*HPAGE_SIZE, - PROT_READ|PROT_WRITE, MAP_SHARED, fd, - ext->fe_logical + p_align); + void *addr = mmap(dax_addr, 2*HPAGE_SIZE, + PROT_READ|PROT_WRITE, MAP_SHARED, dax_fd, + offset); + int fd2; + if (addr == MAP_FAILED) { faili(i); break; } + rc = -ENXIO; fd2 = open(TEST_FILE, O_CREAT|O_TRUNC|O_DIRECT|O_RDWR, DEFFILEMODE); @@ -97,7 +48,7 @@ static int test_pmd(int fd) break; } - fprintf(stderr, "%s: test: %ld\n", __func__, i); + fprintf(stderr, "%s: test: %d\n", __func__, i); rc = 0; switch (i) { case 0: /* test O_DIRECT of unfaulted address */ @@ -131,8 +82,10 @@ static int test_pmd(int fd) } else if (rc > 0) { /* parent */ wait(&rc); - if (rc != EXIT_SUCCESS) + rc = WEXITSTATUS(rc); + if (rc != EXIT_SUCCESS) { faili(i); + } } else faili(i); break; @@ -151,15 +104,77 @@ static int test_pmd(int fd) break; } + 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; + struct fiemap_extent *ext; + struct fiemap *map; + int rc = -ENXIO; + unsigned long i; + void *base; + + if (fd < 0) { + fail(); + return -ENXIO; + } + + map = calloc(1, sizeof(struct fiemap) + + sizeof(struct fiemap_extent) * NUM_EXTENTS); + if (!map) { + fail(); + return -ENXIO; + } + + base = mmap(NULL, 4*HPAGE_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if (base == MAP_FAILED) { + fail(); + goto err_mmap; + } + munmap(base, 4*HPAGE_SIZE); + + map->fm_start = 0; + map->fm_length = -1; + map->fm_extent_count = NUM_EXTENTS; + rc = ioctl(fd, FS_IOC_FIEMAP, map); + if (rc < 0) { + fail(); + goto err_extent; + } + + for (i = 0; i < map->fm_mapped_extents; i++) { + ext = &map->fm_extents[i]; + fprintf(stderr, "[%ld]: l: %llx p: %llx len: %llx flags: %x\n", + i, ext->fe_logical, ext->fe_physical, + ext->fe_length, ext->fe_flags); + if (ext->fe_length > 2 * HPAGE_SIZE) { + fprintf(stderr, "found potential huge extent\n"); + break; + } + } + + if (i >= map->fm_mapped_extents) { + fail(); + goto err_extent; + } + + 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, (char *) base + m_align, ext->fe_logical + + p_align); + err_extent: err_mmap: - free(buf); - err_memalign: free(map); return rc; } -int main(int argc, char *argv[]) +int __attribute__((weak)) main(int argc, char *argv[]) { int fd, rc; diff --git a/test/device-dax.c b/test/device-dax.c index fdd138884522..34ca284f2ef5 100644 --- a/test/device-dax.c +++ b/test/device-dax.c @@ -117,6 +117,16 @@ static int test_device_dax(int loglevel, struct ndctl_test *test, p = (int *) (buf + (1UL << 20)); *p = 0; + if (ndctl_test_attempt(test, KERNEL_VERSION(4, 9, 0))) { + /* prior to 4.8-final this crashes */ + rc = test_dax_directio(fd, NULL, 0); + if (rc) { + fprintf(stderr, "%s: failed dax direct-i/o\n", + ndctl_namespace_get_devname(ndns)); + return rc; + } + } + rc = reset_device_dax(ndns); if (rc < 0) { fprintf(stderr, "%s: failed to reset device-dax instance\n", _______________________________________________ Linux-nvdimm mailing list [email protected] https://lists.01.org/mailman/listinfo/linux-nvdimm
