From patchwork Tue Nov 17 20:50:21 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Williams X-Patchwork-Id: 7642011 Return-Path: X-Original-To: patchwork-linux-nvdimm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id C293D9F1C2 for ; Tue, 17 Nov 2015 20:50:53 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 80008204D6 for ; Tue, 17 Nov 2015 20:50:52 +0000 (UTC) Received: from ml01.01.org (ml01.01.org [198.145.21.10]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 31392204D5 for ; Tue, 17 Nov 2015 20:50:51 +0000 (UTC) Received: from ml01.vlan14.01.org (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id EE38D1A1F1C; Tue, 17 Nov 2015 12:50:50 -0800 (PST) X-Original-To: linux-nvdimm@lists.01.org Delivered-To: linux-nvdimm@lists.01.org Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by ml01.01.org (Postfix) with ESMTP id 9C97E1A1F1C for ; Tue, 17 Nov 2015 12:50:49 -0800 (PST) Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga102.fm.intel.com with ESMTP; 17 Nov 2015 12:50:49 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.20,309,1444719600"; d="scan'208";a="687836266" Received: from dwillia2-desk3.jf.intel.com ([10.54.39.39]) by orsmga003.jf.intel.com with ESMTP; 17 Nov 2015 12:50:49 -0800 Subject: [PATCH] ndctl: dax pmd tests From: Dan Williams To: linux-nvdimm@lists.01.org Date: Tue, 17 Nov 2015 12:50:21 -0800 Message-ID: <20151117204650.25132.94694.stgit@dwillia2-desk3.jf.intel.com> User-Agent: StGit/0.17.1-9-g687f MIME-Version: 1.0 Cc: linux-fsdevel@vger.kernel.org, Dave Chinner , Jan Kara X-BeenThere: linux-nvdimm@lists.01.org X-Mailman-Version: 2.1.17 Precedence: list List-Id: "Linux-nvdimm developer list." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: linux-nvdimm-bounces@lists.01.org Sender: "Linux-nvdimm" X-Spam-Status: No, score=-3.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_LOW, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Check the following conditions: 1/ gup fault 2/ gup fast 3/ copying a huge mapping on fork() Cc: Jan Kara Cc: Dave Chinner Cc: Matthew Wilcox Cc: Ross Zwisler Signed-off-by: Dan Williams --- This is the test case used to generate the kernel crash signatures mentioned in "[PATCH 2/8] dax: disable pmd mappings": https://lists.01.org/pipermail/linux-nvdimm/2015-November/002875.html Makefile.am | 8 ++ lib/test-dax-dev.c | 96 +++++++++++++++++++++++++++++ lib/test-dax-pmd.c | 172 ++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/test-dax.sh | 34 ++++++++++ 4 files changed, 310 insertions(+) create mode 100755 lib/test-dax-dev.c create mode 100644 lib/test-dax-pmd.c create mode 100755 lib/test-dax.sh diff --git a/Makefile.am b/Makefile.am index e998c5766631..2989e076972d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -122,6 +122,9 @@ check_PROGRAMS = lib/test-libndctl lib/test-dpa-alloc lib/test-parent-uuid if ENABLE_DESTRUCTIVE TESTS += lib/test-blk-ns lib/test-pmem-ns lib/test-pcommit check_PROGRAMS += lib/test-blk-ns lib/test-pmem-ns lib/test-pcommit + +TESTS += lib/test-dax-dev lib/test-dax.sh +check_PROGRAMS += lib/test-dax-dev lib/test-dax-pmd endif lib_test_libndctl_SOURCES = lib/test-libndctl.c lib/test-core.c @@ -141,3 +144,8 @@ lib_test_dpa_alloc_LDADD = lib/libndctl.la $(UUID_LIBS) $(KMOD_LIBS) lib_test_parent_uuid_SOURCES = lib/test-parent-uuid.c lib/test-core.c lib_test_parent_uuid_LDADD = lib/libndctl.la $(UUID_LIBS) $(KMOD_LIBS) + +lib_test_dax_dev_SOURCES = lib/test-dax-dev.c lib/test-core.c +lib_test_dax_dev_LDADD = lib/libndctl.la + +lib_test_dax_pmd_SOURCES = lib/test-dax-pmd.c diff --git a/lib/test-dax-dev.c b/lib/test-dax-dev.c new file mode 100755 index 000000000000..3ca7cef0f71c --- /dev/null +++ b/lib/test-dax-dev.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2014-2015, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU Lesser General Public License, + * version 2.1, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for + * more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static int emit_e820_device(int loglevel, struct ndctl_test *test) +{ + int err, fd; + char path[256]; + const char *bdev; + struct ndctl_ctx *ctx; + struct ndctl_bus *bus; + struct ndctl_region *region; + struct ndctl_namespace *ndns; + + if (!ndctl_test_attempt(test, KERNEL_VERSION(4, 3, 0))) + return 77; + + err = ndctl_new(&ctx); + if (err < 0) + return err; + + ndctl_set_log_priority(ctx, loglevel); + err = -ENXIO; + bus = ndctl_bus_get_by_provider(ctx, "e820"); + if (!bus) + goto out; + + region = ndctl_region_get_first(bus); + if (!region) + goto out; + + ndns = ndctl_namespace_get_first(region); + if (!ndns) + goto out; + + bdev = ndctl_namespace_get_block_device(ndns); + if (!bdev) + goto out; + + if (snprintf(path, sizeof(path), "/dev/%s", bdev) >= (int) sizeof(path)) + goto out; + + /* + * Note, if the bdev goes active after this check we'll still + * clobber it in the following tests, see lib/test-dax.sh. + */ + fd = open(path, O_RDWR | O_EXCL); + if (fd < 0) + goto out; + err = 0; + fprintf(stdout, "%s\n", path); + + out: + if (err) + fprintf(stderr, "%s: failed to find usable victim device\n", + __func__); + ndctl_unref(ctx); + return err; +} + +int __attribute__((weak)) main(int argc, char *argv[]) +{ + struct ndctl_test *test = ndctl_test_new(0); + int rc; + + if (!test) { + fprintf(stderr, "failed to initialize test\n"); + return EXIT_FAILURE; + } + + rc = emit_e820_device(LOG_DEBUG, test); + return ndctl_test_result(test, rc); +} diff --git a/lib/test-dax-pmd.c b/lib/test-dax-pmd.c new file mode 100644 index 000000000000..fc64c7b82836 --- /dev/null +++ b/lib/test-dax-pmd.c @@ -0,0 +1,172 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 TEST_FILE "test_dax_data" + +/* 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; + int fd2 = -1, rc = -ENXIO; + struct fiemap_extent *ext; + struct fiemap *map; + void *addr, *buf; + 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; + } + + if (posix_memalign(&buf, 4096, 4096) != 0) + goto err_memalign; + + addr = mmap(NULL, 4*HPAGE_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if (addr == MAP_FAILED) { + fail(); + goto err_mmap; + } + munmap(addr, 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(addr, HPAGE_SIZE) - ((unsigned long) addr); + p_align = ALIGN(ext->fe_physical, HPAGE_SIZE) - ext->fe_physical; + + for (i = 0; i < 3; i++) { + rc = -ENXIO; + addr = mmap((char *) addr + m_align, 2*HPAGE_SIZE, + PROT_READ|PROT_WRITE, MAP_SHARED, fd, + ext->fe_logical + p_align); + if (addr == MAP_FAILED) { + faili(i); + break; + } + + fd2 = open(TEST_FILE, O_CREAT|O_TRUNC|O_DIRECT|O_RDWR); + if (fd2 < 0) { + faili(i); + munmap(addr, 2*HPAGE_SIZE); + break; + } + + rc = 0; + switch (i) { + case 0: /* test O_DIRECT of unfaulted address */ + if (write(fd2, addr, 4096) != 4096) { + faili(i); + rc = -ENXIO; + } + break; + case 1: /* test O_DIRECT of pre-faulted address */ + sprintf(addr, "odirect data"); + if (write(fd2, addr, 4096) != 4096) { + faili(i); + rc = -ENXIO; + } + ((char *) buf)[0] = 0; + read(fd2, buf, sizeof(buf)); + if (strcmp(buf, "test data") != 0) { + faili(i); + rc = -ENXIO; + } + break; + case 2: /* fork with pre-faulted pmd */ + sprintf(addr, "fork data"); + rc = fork(); + if (rc == 0) { + /* child */ + if (strcmp(addr, "fork data") == 0) + exit(EXIT_SUCCESS); + else + exit(EXIT_FAILURE); + } else if (rc > 0) { + /* parent */ + wait(&rc); + if (rc != EXIT_SUCCESS) + faili(i); + } else + faili(i); + break; + default: + faili(i); + rc = -ENXIO; + break; + } + + munmap(addr, 2*HPAGE_SIZE); + addr = MAP_FAILED; + unlink(TEST_FILE); + close(fd2); + fd2 = -1; + if (rc) + break; + } + + err_extent: + err_mmap: + free(buf); + err_memalign: + free(map); + return rc; +} + +int main(int argc, char *argv[]) +{ + int fd, rc; + + if (argc < 1) + return -EINVAL; + + fd = open(argv[1], O_RDWR); + rc = test_pmd(fd); + if (fd >= 0) + close(fd); + return rc; +} diff --git a/lib/test-dax.sh b/lib/test-dax.sh new file mode 100755 index 000000000000..048d82975d92 --- /dev/null +++ b/lib/test-dax.sh @@ -0,0 +1,34 @@ +#!/bin/bash +MNT=test_dax_mnt +FILE=image +DEV="" + +err() { + rc=1 + echo "test-dax: failed at line $1" + if [ -n "$DEV" ]; then + umount $DEV + else + rc=77 + fi + rmdir $MNT + exit $rc +} + +set -e +mkdir -p $MNT +trap 'err $LINENO' ERR + +DEV=$(lib/test-dax-dev) + +mkfs.ext4 $DEV +mount $DEV $MNT -o dax +fallocate -l 1GiB $MNT/$FILE +lib/test-dax-pmd $MNT/$FILE +umount $MNT + +mkfs.xfs -f $DEV +mount $DEV $MNT -o dax +fallocate -l 1GiB $MNT/$FILE +lib/test-dax-pmd $MNT/$FILE +umount $MNT