@@ -22,7 +22,7 @@ int nfit_test_init(struct kmod_ctx **ctx, struct kmod_module **mod,
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, void *dax_addr, off_t offset);
+int test_dax_directio(int dax_fd, unsigned long align, void *dax_addr, off_t offset);
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);
@@ -19,7 +19,7 @@
#define faili(i) fprintf(stderr, "%s: failed at: %d: %d\n", __func__, __LINE__, i)
#define TEST_FILE "test_dax_data"
-int test_dax_directio(int dax_fd, void *dax_addr, off_t offset)
+int test_dax_directio(int dax_fd, unsigned long align, void *dax_addr, off_t offset)
{
int i, rc = -ENXIO;
void *buf;
@@ -28,7 +28,7 @@ int test_dax_directio(int dax_fd, void *dax_addr, off_t offset)
return -ENOMEM;
for (i = 0; i < 3; i++) {
- void *addr = mmap(dax_addr, 2*HPAGE_SIZE,
+ void *addr = mmap(dax_addr, 2*align,
PROT_READ|PROT_WRITE, MAP_SHARED, dax_fd,
offset);
int fd2;
@@ -43,7 +43,7 @@ int test_dax_directio(int dax_fd, void *dax_addr, off_t offset)
DEFFILEMODE);
if (fd2 < 0) {
faili(i);
- munmap(addr, 2*HPAGE_SIZE);
+ munmap(addr, 2*align);
break;
}
@@ -94,7 +94,7 @@ int test_dax_directio(int dax_fd, void *dax_addr, off_t offset)
break;
}
- munmap(addr, 2*HPAGE_SIZE);
+ munmap(addr, 2*align);
addr = MAP_FAILED;
unlink(TEST_FILE);
close(fd2);
@@ -164,8 +164,8 @@ 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, (char *) base + m_align, ext->fe_logical
- + p_align);
+ rc = test_dax_directio(fd, HPAGE_SIZE, (char *) base + m_align,
+ ext->fe_logical + p_align);
err_extent:
err_mmap:
@@ -41,27 +41,34 @@ static int reset_device_dax(struct ndctl_namespace *ndns)
return create_namespace(argc, argv, ctx);
}
-static int setup_device_dax(struct ndctl_namespace *ndns)
+static int setup_device_dax(struct ndctl_namespace *ndns, unsigned long __align)
{
struct ndctl_ctx *ctx = ndctl_namespace_get_ctx(ndns);
+ char align[32];
const char *argv[] = {
- "__func__", "-v", "-m", "dax", "-M", "dev", "-f", "-e", "",
+ "__func__", "-v", "-m", "dax", "-M", "dev", "-f", "-a", align,
+ "-e", "",
};
int argc = ARRAY_SIZE(argv);
argv[argc - 1] = ndctl_namespace_get_devname(ndns);
+ sprintf(align, "%ld", __align);
return create_namespace(argc, argv, ctx);
}
-static int setup_pmem_memory_mode(struct ndctl_namespace *ndns)
+static int setup_pmem_memory_mode(struct ndctl_namespace *ndns,
+ unsigned long __align)
{
struct ndctl_ctx *ctx = ndctl_namespace_get_ctx(ndns);
+ char align[32];
const char *argv[] = {
- "__func__", "-v", "-m", "memory", "-M", "dev", "-f", "-e", "",
+ "__func__", "-v", "-m", "memory", "-M", "dev", "-f", "-a",
+ align, "-e", "",
};
int argc = ARRAY_SIZE(argv);
argv[argc - 1] = ndctl_namespace_get_devname(ndns);
+ sprintf(align, "%ld", __align);
return create_namespace(argc, argv, ctx);
}
@@ -70,28 +77,35 @@ static void sigbus(int sig, siginfo_t *siginfo, void *d)
siglongjmp(sj_env, 1);
}
-#define VERIFY_SIZE SZ_4M
+#define VERIFY_SIZE(x) (x * 2)
#define VERIFY_BUF_SIZE 4096
-static int verify_data(struct daxctl_dev *dev, char *dax_buf, int salt,
- struct ndctl_test *test)
+/*
+ * This timeout value derived from an Intel(R) Xeon(R) CPU E5-2690 v2 @
+ * 3.00GHz where the loop, for the align == 2M case, completes in 7500us
+ * when cached and 200ms when uncached.
+ */
+#define VERIFY_TIME(x) (suseconds_t) ((ALIGN(x, SZ_2M) / SZ_4K) * 30)
+
+static int verify_data(struct daxctl_dev *dev, char *dax_buf,
+ unsigned long align, int salt, struct ndctl_test *test)
{
struct timeval tv1, tv2, tv_diff;
- int i;
+ unsigned long i;
if (!ndctl_test_attempt(test, KERNEL_VERSION(4, 9, 0)))
return 0;
/* verify data and cache mode */
gettimeofday(&tv1, NULL);
- for (i = 0; i < VERIFY_SIZE; i += VERIFY_BUF_SIZE) {
+ for (i = 0; i < VERIFY_SIZE(align); i += VERIFY_BUF_SIZE) {
unsigned int *verify = (unsigned int *) (dax_buf + i), j;
for (j = 0; j < VERIFY_BUF_SIZE / sizeof(int); j++)
if (verify[j] != salt + i + j)
break;
if (j < VERIFY_BUF_SIZE / sizeof(int)) {
- fprintf(stderr, "%s: @ %#x expected %#x got %#x\n",
+ fprintf(stderr, "%s: @ %#lx expected %#x got %#lx\n",
daxctl_dev_get_devname(dev), i,
verify[j], salt + i + j);
return -ENXIO;
@@ -100,13 +114,10 @@ static int verify_data(struct daxctl_dev *dev, char *dax_buf, int salt,
gettimeofday(&tv2, NULL);
timersub(&tv2, &tv1, &tv_diff);
tv_diff.tv_usec += tv_diff.tv_sec * 1000000;
- if (tv_diff.tv_usec > 15000) {
+ if (tv_diff.tv_usec > VERIFY_TIME(align)) {
/*
* Checks whether the kernel correctly mapped the
- * device-dax range as cacheable. The numbers were
- * derived from an Intel(R) Xeon(R) CPU E5-2690 v2 @
- * 3.00GHz where the loop completes in 7500us when
- * cached and 200ms when uncached.
+ * device-dax range as cacheable.
*/
fprintf(stderr, "%s: verify loop took too long usecs: %ld\n",
daxctl_dev_get_devname(dev), tv_diff.tv_usec);
@@ -115,14 +126,15 @@ static int verify_data(struct daxctl_dev *dev, char *dax_buf, int salt,
return 0;
}
-static int test_device_dax(int loglevel, struct ndctl_test *test,
- struct ndctl_ctx *ctx)
+static int __test_device_dax(unsigned long align, int loglevel,
+ struct ndctl_test *test, struct ndctl_ctx *ctx)
{
+ unsigned long i;
struct sigaction act;
struct ndctl_dax *dax;
struct ndctl_pfn *pfn;
struct daxctl_dev *dev;
- int i, fd, rc, *p, salt;
+ int fd, rc, *p, salt;
struct ndctl_namespace *ndns;
struct daxctl_region *dax_region;
char *buf, path[100], data[VERIFY_BUF_SIZE];
@@ -148,8 +160,11 @@ static int test_device_dax(int loglevel, struct ndctl_test *test,
if (!ndctl_test_attempt(test, KERNEL_VERSION(4, 7, 0)))
return 77;
+ if (align > SZ_2M && !ndctl_test_attempt(test, KERNEL_VERSION(4, 11, 0)))
+ return 77;
+
/* setup up memory mode pmem device and seed with verification data */
- rc = setup_pmem_memory_mode(ndns);
+ rc = setup_pmem_memory_mode(ndns, align);
if (rc < 0 || !(pfn = ndctl_namespace_get_pfn(ndns))) {
fprintf(stderr, "%s: failed device-dax setup\n",
ndctl_namespace_get_devname(ndns));
@@ -166,7 +181,7 @@ static int test_device_dax(int loglevel, struct ndctl_test *test,
srand(getpid());
salt = rand();
- for (i = 0; i < VERIFY_SIZE; i += VERIFY_BUF_SIZE) {
+ for (i = 0; i < VERIFY_SIZE(align); i += VERIFY_BUF_SIZE) {
unsigned int *verify = (unsigned int *) data, j;
for (j = 0; j < VERIFY_BUF_SIZE / sizeof(int); j++)
@@ -183,7 +198,7 @@ static int test_device_dax(int loglevel, struct ndctl_test *test,
close(fd);
/* switch the namespace to device-dax mode and verify data via mmap */
- rc = setup_device_dax(ndns);
+ rc = setup_device_dax(ndns, align);
if (rc < 0) {
fprintf(stderr, "%s: failed device-dax setup\n",
ndctl_namespace_get_devname(ndns));
@@ -209,26 +224,26 @@ static int test_device_dax(int loglevel, struct ndctl_test *test,
goto out;
}
- buf = mmap(NULL, VERIFY_SIZE, PROT_READ, MAP_PRIVATE, fd, 0);
+ buf = mmap(NULL, VERIFY_SIZE(align), PROT_READ, MAP_PRIVATE, fd, 0);
if (buf != MAP_FAILED) {
fprintf(stderr, "%s: expected MAP_PRIVATE failure\n", path);
rc = -ENXIO;
goto out;
}
- buf = mmap(NULL, VERIFY_SIZE, PROT_READ, MAP_SHARED, fd, 0);
+ buf = mmap(NULL, VERIFY_SIZE(align), PROT_READ, MAP_SHARED, fd, 0);
if (buf == MAP_FAILED) {
fprintf(stderr, "%s: expected MAP_SHARED success\n", path);
return -ENXIO;
}
- rc = verify_data(dev, buf, salt, test);
+ rc = verify_data(dev, buf, align, salt, test);
if (rc)
goto out;
/* upgrade to a writable mapping */
close(fd);
- munmap(buf, VERIFY_SIZE);
+ munmap(buf, VERIFY_SIZE(align));
fd = open(path, O_RDWR);
if (fd < 0) {
fprintf(stderr, "%s: failed to open(O_RDWR) device-dax instance\n",
@@ -237,7 +252,7 @@ static int test_device_dax(int loglevel, struct ndctl_test *test,
goto out;
}
- buf = mmap(NULL, VERIFY_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+ buf = mmap(NULL, VERIFY_SIZE(align), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if (buf == MAP_FAILED) {
fprintf(stderr, "%s: expected PROT_WRITE + MAP_SHARED success\n",
path);
@@ -251,7 +266,7 @@ static int test_device_dax(int loglevel, struct ndctl_test *test,
if (ndctl_test_attempt(test, KERNEL_VERSION(4, 9, 0))) {
int fd2;
- rc = test_dax_directio(fd, NULL, 0);
+ rc = test_dax_directio(fd, align, NULL, 0);
if (rc) {
fprintf(stderr, "%s: failed dax direct-i/o\n",
ndctl_namespace_get_devname(ndns));
@@ -294,7 +309,7 @@ static int test_device_dax(int loglevel, struct ndctl_test *test,
}
rc = EXIT_SUCCESS;
- p = (int *) (buf + (1UL << 20));
+ p = (int *) (buf + align);
*p = 0xff;
if (ndctl_test_attempt(test, KERNEL_VERSION(4, 9, 0))) {
/* after 4.9 this test will properly get sigbus above */
@@ -308,6 +323,21 @@ static int test_device_dax(int loglevel, struct ndctl_test *test,
return rc;
}
+static int test_device_dax(int loglevel, struct ndctl_test *test,
+ struct ndctl_ctx *ctx)
+{
+ unsigned long i, aligns[] = { SZ_4K, SZ_2M, SZ_1G };
+ int rc;
+
+ for (i = 0; i < ARRAY_SIZE(aligns); i++) {
+ rc = __test_device_dax(aligns[i], loglevel, test, ctx);
+ if (rc && rc != 77)
+ break;
+ }
+
+ return rc;
+}
+
int __attribute__((weak)) main(int argc, char *argv[])
{
struct ndctl_test *test = ndctl_test_new(0);
Add 4K and 1G alignment testing in addition to the default 2M. Signed-off-by: Dan Williams <dan.j.williams@intel.com> --- test.h | 2 + test/dax-pmd.c | 12 ++++--- test/device-dax.c | 86 ++++++++++++++++++++++++++++++++++++----------------- 3 files changed, 65 insertions(+), 35 deletions(-)