From patchwork Tue Dec 15 02:19:37 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Williams X-Patchwork-Id: 7850961 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 46A4D9F32E for ; Tue, 15 Dec 2015 02:20:09 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 9FD4C20381 for ; Tue, 15 Dec 2015 02:20:07 +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 E01C4201CD for ; Tue, 15 Dec 2015 02:20:05 +0000 (UTC) Received: from ml01.vlan14.01.org (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id D5DE81A2098; Mon, 14 Dec 2015 18:20:05 -0800 (PST) X-Original-To: linux-nvdimm@lists.01.org Delivered-To: linux-nvdimm@lists.01.org Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by ml01.01.org (Postfix) with ESMTP id 03E981A20BA for ; Mon, 14 Dec 2015 18:20:03 -0800 (PST) Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga102.jf.intel.com with ESMTP; 14 Dec 2015 18:20:03 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.20,429,1444719600"; d="scan'208";a="871548925" Received: from dwillia2-desk3.jf.intel.com ([10.54.39.136]) by orsmga002.jf.intel.com with ESMTP; 14 Dec 2015 18:20:03 -0800 Subject: [ndctl PATCH 2/3] ndctl: unit test updates 'pfn' devices From: Dan Williams To: linux-nvdimm@lists.01.org Date: Mon, 14 Dec 2015 18:19:37 -0800 Message-ID: <20151215021936.37242.56898.stgit@dwillia2-desk3.jf.intel.com> In-Reply-To: <20151215021746.37242.59572.stgit@dwillia2-desk3.jf.intel.com> References: <20151215021746.37242.59572.stgit@dwillia2-desk3.jf.intel.com> User-Agent: StGit/0.17.1-9-g687f MIME-Version: 1.0 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=-2.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_LOW, T_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 Follow the template established by the btt tests to check the creation and autodetection of pfn configurations. Signed-off-by: Dan Williams --- lib/test-libndctl.c | 440 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 394 insertions(+), 46 deletions(-) diff --git a/lib/test-libndctl.c b/lib/test-libndctl.c index c406685f1c4d..5acf971a1fb7 100644 --- a/lib/test-libndctl.c +++ b/lib/test-libndctl.c @@ -97,8 +97,10 @@ static const char *NFIT_TEST_MODULE = "nfit_test"; static const char *NFIT_PROVIDER0 = "nfit_test.0"; static const char *NFIT_PROVIDER1 = "nfit_test.1"; +#define SZ_4K 0x00001000 #define SZ_128K 0x00020000 #define SZ_7M 0x00700000 +#define SZ_2M 0x00200000 #define SZ_8M 0x00800000 #define SZ_11M 0x00b00000 #define SZ_12M 0x00c00000 @@ -109,6 +111,7 @@ static const char *NFIT_PROVIDER1 = "nfit_test.1"; #define SZ_28M 0x01c00000 #define SZ_32M 0x02000000 #define SZ_64M 0x04000000 +#define SZ_1G 0x40000000 struct dimm { unsigned int handle; @@ -148,11 +151,32 @@ static struct dimm dimms1[] = { } }; -struct btt { +static struct btt { int enabled; uuid_t uuid; int num_sector_sizes; unsigned int sector_sizes[7]; +} default_btt = { + 0, { 0, }, 7, { 512, 520, 528, 4096, 4104, 4160, 4224, }, +}; + +struct pfn { + int enabled; + uuid_t uuid; + enum ndctl_pfn_loc locs[2]; + unsigned long aligns[4]; +}; + +static struct pfn_default { + int enabled; + uuid_t uuid; + enum ndctl_pfn_loc loc; + unsigned long align; +} default_pfn = { + .enabled = 0, + .uuid = { 0, }, + .loc = NDCTL_PFN_LOC_NONE, + .align = SZ_2M, }; struct region { @@ -169,6 +193,7 @@ struct region { int active; } iset; struct btt *btts[2]; + struct pfn_default *pfns[2]; struct namespace *namespaces[4]; }; @@ -181,10 +206,21 @@ static struct btt btt_settings = { .sector_sizes = { 512, 520, 528, 4096, 4104, 4160, 4224, }, }; +static struct pfn pfn_settings = { + .enabled = 1, + .uuid = { 1, 2, 3, 4, 5, 6, 7, 0, + 8, 9, 10, 11, 12, 13, 14, 15 + }, + .locs = { NDCTL_PFN_LOC_RAM, NDCTL_PFN_LOC_PMEM }, + /* order matters, successful aligns at the end */ + .aligns = { 1, SZ_1G, SZ_4K, SZ_2M, }, +}; + struct namespace { unsigned int id; char *type; struct btt *btt_settings; + struct pfn *pfn_settings; unsigned long long size; uuid_t uuid; int do_configure; @@ -199,7 +235,7 @@ static unsigned long blk_sector_sizes[7] = { 512, 520, 528, 4096, 4104, 4160, 42 static unsigned long pmem_sector_sizes[1] = { 0 }; static struct namespace namespace0_pmem0 = { - 0, "namespace_pmem", &btt_settings, SZ_18M, + 0, "namespace_pmem", &btt_settings, &pfn_settings, SZ_18M, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -207,7 +243,7 @@ static struct namespace namespace0_pmem0 = { }; static struct namespace namespace1_pmem0 = { - 0, "namespace_pmem", &btt_settings, SZ_20M, + 0, "namespace_pmem", &btt_settings, &pfn_settings, SZ_20M, { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -215,7 +251,7 @@ static struct namespace namespace1_pmem0 = { }; static struct namespace namespace2_blk0 = { - 0, "namespace_blk", NULL, SZ_7M, + 0, "namespace_blk", NULL, NULL, SZ_7M, { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, @@ -223,7 +259,7 @@ static struct namespace namespace2_blk0 = { }; static struct namespace namespace2_blk1 = { - 1, "namespace_blk", NULL, SZ_11M, + 1, "namespace_blk", NULL, NULL, SZ_11M, { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, @@ -231,7 +267,7 @@ static struct namespace namespace2_blk1 = { }; static struct namespace namespace3_blk0 = { - 0, "namespace_blk", NULL, SZ_7M, + 0, "namespace_blk", NULL, NULL, SZ_7M, { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, @@ -239,7 +275,7 @@ static struct namespace namespace3_blk0 = { }; static struct namespace namespace3_blk1 = { - 1, "namespace_blk", NULL, SZ_11M, + 1, "namespace_blk", NULL, NULL, SZ_11M, { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, @@ -247,7 +283,7 @@ static struct namespace namespace3_blk1 = { }; static struct namespace namespace4_blk0 = { - 0, "namespace_blk", &btt_settings, SZ_27M, + 0, "namespace_blk", &btt_settings, NULL, SZ_27M, { 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, @@ -255,17 +291,13 @@ static struct namespace namespace4_blk0 = { }; static struct namespace namespace5_blk0 = { - 0, "namespace_blk", &btt_settings, SZ_27M, + 0, "namespace_blk", &btt_settings, NULL, SZ_27M, { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, }, 1, 1, 7, 0, blk_sector_sizes, }; -static struct btt default_btt = { - 0, { 0, }, 7, { 512, 520, 528, 4096, 4104, 4160, 4224, }, -}; - static struct region regions0[] = { { { 1 }, 2, 1, "pmem", SZ_32M, SZ_32M, { 1 }, .namespaces = { @@ -274,6 +306,9 @@ static struct region regions0[] = { .btts = { [0] = &default_btt, }, + .pfns = { + [0] = &default_pfn, + }, }, { { 2 }, 4, 1, "pmem", SZ_64M, SZ_64M, { 1 }, .namespaces = { @@ -282,6 +317,9 @@ static struct region regions0[] = { .btts = { [0] = &default_btt, }, + .pfns = { + [0] = &default_pfn, + }, }, { { DIMM_HANDLE(0, 0, 0, 0, 0) }, 1, 1, "blk", SZ_18M, SZ_32M, .namespaces = { @@ -320,11 +358,11 @@ static struct region regions0[] = { }; static struct namespace namespace1 = { - 0, "namespace_io", &btt_settings, SZ_32M, + 0, "namespace_io", &btt_settings, &pfn_settings, SZ_32M, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, }, 0, 0, 1, 1, pmem_sector_sizes, + 0, 0, 0, 0, }, -1, 0, 1, 1, pmem_sector_sizes, }; static struct region regions1[] = { @@ -365,6 +403,17 @@ static struct ndctl_btt *get_idle_btt(struct ndctl_region *region) return NULL; } +static struct ndctl_pfn *get_idle_pfn(struct ndctl_region *region) +{ + struct ndctl_pfn *pfn; + + ndctl_pfn_foreach(region, pfn) + if (!ndctl_pfn_is_enabled(pfn) && !ndctl_pfn_is_configured(pfn)) + return pfn; + + return NULL; +} + static struct ndctl_namespace *get_namespace_by_id(struct ndctl_region *region, struct namespace *namespace) { @@ -423,11 +472,15 @@ static struct ndctl_region *get_blk_region_by_dimm_handle(struct ndctl_bus *bus, return NULL; } +enum ns_mode { + BTT, PFN, +}; static int check_namespaces(struct ndctl_region *region, - struct namespace **namespaces); + struct namespace **namespaces, enum ns_mode mode); static int check_btts(struct ndctl_region *region, struct btt **btts); -static int check_regions(struct ndctl_bus *bus, struct region *regions, int n) +static int check_regions(struct ndctl_bus *bus, struct region *regions, int n, + enum ns_mode mode) { int i, rc = 0; @@ -507,7 +560,8 @@ static int check_regions(struct ndctl_bus *bus, struct region *regions, int n) return rc; if (regions[i].namespaces[0]) - rc = check_namespaces(region, regions[i].namespaces); + rc = check_namespaces(region, regions[i].namespaces, + mode); if (rc) break; } @@ -515,6 +569,135 @@ static int check_regions(struct ndctl_bus *bus, struct region *regions, int n) return rc; } +static int __check_pfn_create(struct ndctl_region *region, + struct ndctl_namespace *ndns, struct namespace *namespace, + void *buf, enum ndctl_pfn_loc loc, unsigned long align, + uuid_t uuid) +{ + struct ndctl_pfn *pfn_seed = ndctl_region_get_pfn_seed(region); + struct ndctl_pfn *pfn; + const char *devname; + int fd, retry = 10; + char bdevpath[50]; + ssize_t rc; + + pfn = get_idle_pfn(region); + if (!pfn) + return -ENXIO; + + devname = ndctl_pfn_get_devname(pfn); + ndctl_pfn_set_uuid(pfn, uuid); + ndctl_pfn_set_location(pfn, loc); + ndctl_pfn_set_align(pfn, align); + ndctl_pfn_set_namespace(pfn, ndns); + rc = ndctl_pfn_enable(pfn); + if (align == SZ_1G) { + if (rc == 0) { + fprintf(stderr, "%s: expected pfn enable failure with align: %lx\n", + devname, align); + return rc; + } + ndctl_pfn_delete(pfn); + return 0; + } + if (namespace->ro == (rc == 0)) { + fprintf(stderr, "%s: expected pfn enable %s, %s read-%s\n", + devname, + namespace->ro ? "failure" : "success", + ndctl_region_get_devname(region), + namespace->ro ? "only" : "write"); + return -ENXIO; + } + + if (pfn_seed == ndctl_region_get_pfn_seed(region) + && pfn == pfn_seed) { + fprintf(stderr, "%s: failed to advance pfn seed\n", + ndctl_region_get_devname(region)); + return -ENXIO; + } + + if (namespace->ro) { + ndctl_region_set_ro(region, 0); + rc = ndctl_pfn_enable(pfn); + fprintf(stderr, "%s: failed to enable after setting rw\n", + devname); + ndctl_region_set_ro(region, 1); + return -ENXIO; + } + + sprintf(bdevpath, "/dev/%s", ndctl_pfn_get_block_device(pfn)); + rc = -ENXIO; + fd = open(bdevpath, O_RDWR|O_DIRECT); + if (fd < 0) + fprintf(stderr, "%s: failed to open %s\n", + devname, bdevpath); + + while (fd >= 0) { + rc = pread(fd, buf, 4096, 0); + if (rc < 4096) { + /* TODO: track down how this happens! */ + if (errno == ENOENT && retry--) { + usleep(5000); + continue; + } + fprintf(stderr, "%s: failed to read %s: %d %zd (%s)\n", + devname, bdevpath, -errno, rc, + strerror(errno)); + rc = -ENXIO; + break; + } + if (write(fd, buf, 4096) < 4096) { + fprintf(stderr, "%s: failed to write %s\n", + devname, bdevpath); + rc = -ENXIO; + break; + } + rc = 0; + break; + } + if (namespace->ro) + ndctl_region_set_ro(region, 1); + if (fd >= 0) + close(fd); + + if (rc) + return rc; + + rc = ndctl_pfn_delete(pfn); + if (rc) + fprintf(stderr, "%s: failed to delete pfn (%zd)\n", devname, rc); + return rc; +} + +static int check_pfn_create(struct ndctl_region *region, + struct ndctl_namespace *ndns, struct namespace *namespace) +{ + struct pfn *pfn_s = namespace->pfn_settings; + unsigned int i, j; + void *buf = NULL; + int rc = 0; + + if (!pfn_s) + return 0; + + if (posix_memalign(&buf, 4096, 4096) != 0) + return -ENXIO; + + for (i = 0; i < ARRAY_SIZE(pfn_s->locs); i++) { + for (j = 0; j < ARRAY_SIZE(pfn_s->aligns); j++) { + rc = __check_pfn_create(region, ndns, namespace, buf, + pfn_s->locs[i], pfn_s->aligns[j], + pfn_s->uuid); + if (rc) + break; + } + if (rc) + break; + } + free(buf); + return rc; +} + static int check_btt_create(struct ndctl_region *region, struct ndctl_namespace *ndns, struct namespace *namespace) { @@ -631,12 +814,12 @@ static int check_btt_create(struct ndctl_region *region, struct ndctl_namespace static int configure_namespace(struct ndctl_region *region, struct ndctl_namespace *ndns, struct namespace *namespace, - unsigned long lbasize) + unsigned long lbasize, enum ns_mode mode) { char devname[50]; int rc; - if (!namespace->do_configure) + if (namespace->do_configure <= 0) return 0; snprintf(devname, sizeof(devname), "namespace%d.%d", @@ -665,10 +848,20 @@ static int configure_namespace(struct ndctl_region *region, if (rc < 1) fprintf(stderr, "%s: is_configured: %d\n", devname, rc); - rc = check_btt_create(region, ndns, namespace); - if (rc < 0) { - fprintf(stderr, "%s: failed to create btt\n", devname); - return rc; + if (mode == BTT) { + rc = check_btt_create(region, ndns, namespace); + if (rc < 0) { + fprintf(stderr, "%s: failed to create btt\n", devname); + return rc; + } + } + + if (mode == PFN) { + rc = check_pfn_create(region, ndns, namespace); + if (rc < 0) { + fprintf(stderr, "%s: failed to create pfn\n", devname); + return rc; + } } rc = ndctl_namespace_enable(ndns); @@ -678,6 +871,93 @@ static int configure_namespace(struct ndctl_region *region, return rc; } +static int check_pfn_autodetect(struct ndctl_bus *bus, + struct ndctl_namespace *ndns, void *buf, + struct namespace *namespace) +{ + struct ndctl_region *region = ndctl_namespace_get_region(ndns); + const char *devname = ndctl_namespace_get_devname(ndns); + struct pfn *auto_pfn = namespace->pfn_settings; + struct ndctl_pfn *pfn, *found = NULL; + ssize_t rc = -ENXIO; + char bdev[50]; + int fd, ro; + + ndctl_pfn_foreach(region, pfn) { + struct ndctl_namespace *pfn_ndns; + uuid_t uu; + + ndctl_pfn_get_uuid(pfn, uu); + if (uuid_compare(uu, auto_pfn->uuid) != 0) + continue; + if (!ndctl_pfn_is_enabled(pfn)) + continue; + pfn_ndns = ndctl_pfn_get_namespace(pfn); + if (strcmp(ndctl_namespace_get_devname(pfn_ndns), devname) != 0) + continue; + fprintf(stderr, "%s: pfn_ndns: %p ndns: %p\n", __func__, + pfn_ndns, ndns); + found = pfn; + break; + } + + if (!found) + return -ENXIO; + + sprintf(bdev, "/dev/%s", ndctl_pfn_get_block_device(pfn)); + fd = open(bdev, O_RDONLY); + if (fd < 0) + return -ENXIO; + rc = ioctl(fd, BLKROGET, &ro); + if (rc < 0) { + fprintf(stderr, "%s: failed to open %s\n", __func__, bdev); + rc = -ENXIO; + goto out; + } + close(fd); + fd = -1; + + rc = -ENXIO; + if (ro != namespace->ro) { + fprintf(stderr, "%s: read-%s expected read-%s by default\n", + bdev, ro ? "only" : "write", + namespace->ro ? "only" : "write"); + goto out; + } + + /* destroy pfn device */ + ndctl_pfn_delete(found); + + /* clear read-write, and enable raw mode */ + ndctl_region_set_ro(region, 0); + ndctl_namespace_set_raw_mode(ndns, 1); + ndctl_namespace_enable(ndns); + + /* destroy pfn metadata */ + sprintf(bdev, "/dev/%s", ndctl_namespace_get_block_device(ndns)); + fd = open(bdev, O_RDWR|O_DIRECT|O_EXCL); + if (fd < 0) { + fprintf(stderr, "%s: failed to open %s to destroy pfn\n", + devname, bdev); + goto out; + } + + memset(buf, 0, 4096); + rc = pwrite(fd, buf, 4096, 4096); + if (rc < 4096) { + rc = -ENXIO; + fprintf(stderr, "%s: failed to overwrite pfn on %s\n", + devname, bdev); + } + out: + ndctl_region_set_ro(region, namespace->ro); + ndctl_namespace_set_raw_mode(ndns, 0); + if (fd >= 0) + close(fd); + + return rc; +} + static int check_btt_autodetect(struct ndctl_bus *bus, struct ndctl_namespace *ndns, void *buf, struct namespace *namespace) @@ -766,7 +1046,7 @@ static int check_btt_autodetect(struct ndctl_bus *bus, } static int check_namespaces(struct ndctl_region *region, - struct namespace **namespaces) + struct namespace **namespaces, enum ns_mode mode) { struct ndctl_bus *bus = ndctl_region_get_bus(region); struct ndctl_namespace **ndns_save; @@ -778,6 +1058,10 @@ static int check_namespaces(struct ndctl_region *region, if (posix_memalign(&buf, 4096, 4096) != 0) return -ENOMEM; + for (i = 0; (namespace = namespaces[i]); i++) + if (namespace->do_configure >= 0) + namespace->do_configure = 1; + retry: ndns_save = NULL; for (i = 0; (namespace = namespaces[i]); i++) { @@ -796,11 +1080,13 @@ static int check_namespaces(struct ndctl_region *region, } for (j = 0; j < namespace->num_sector_sizes; j++) { - struct btt *btt_s; - struct ndctl_btt *btt; + struct btt *btt_s = NULL; + struct pfn *pfn_s = NULL; + struct ndctl_btt *btt = NULL; + struct ndctl_pfn *pfn = NULL; rc = configure_namespace(region, ndns, namespace, - namespace->sector_sizes[j]); + namespace->sector_sizes[j], mode); if (rc < 0) { fprintf(stderr, "%s: failed to configure namespace\n", devname); @@ -819,22 +1105,37 @@ static int check_namespaces(struct ndctl_region *region, /* * On the second time through this loop we skip - * establishing btt since check_btt_autodetect() - * destroyed the inital instance. + * establishing btt|pfn since + * check_{btt|pfn}_autodetect() destroyed the + * inital instance. */ - btt_s = namespace->do_configure - ? namespace->btt_settings : NULL; - - btt = ndctl_namespace_get_btt(ndns); - if (!!btt_s != !!btt) { - fprintf(stderr, "%s expected btt %s by default\n", - devname, namespace->btt_settings - ? "enabled" : "disabled"); - rc = -ENXIO; - break; + if (mode == BTT) { + btt_s = namespace->do_configure > 0 + ? namespace->btt_settings : NULL; + btt = ndctl_namespace_get_btt(ndns); + if (!!btt_s != !!btt) { + fprintf(stderr, "%s expected btt %s by default\n", + devname, namespace->btt_settings + ? "enabled" : "disabled"); + rc = -ENXIO; + break; + } + } + + if (mode == PFN) { + pfn_s = namespace->do_configure > 0 + ? namespace->pfn_settings : NULL; + pfn = ndctl_namespace_get_pfn(ndns); + if (!!pfn_s != !!pfn) { + fprintf(stderr, "%s expected pfn %s by default\n", + devname, namespace->pfn_settings + ? "enabled" : "disabled"); + rc = -ENXIO; + break; + } } - if (!btt_s && !ndctl_namespace_is_enabled(ndns)) { + if (!btt_s && !pfn_s && !ndctl_namespace_is_enabled(ndns)) { fprintf(stderr, "%s: expected enabled by default\n", devname); rc = -ENXIO; @@ -871,8 +1172,16 @@ static int check_namespaces(struct ndctl_region *region, break; } - sprintf(bdevpath, "/dev/%s", btt ? ndctl_btt_get_block_device(btt) - : ndctl_namespace_get_block_device(ndns)); + if (btt) + sprintf(bdevpath, "/dev/%s", + ndctl_btt_get_block_device(btt)); + else if (pfn) + sprintf(bdevpath, "/dev/%s", + ndctl_pfn_get_block_device(pfn)); + else + sprintf(bdevpath, "/dev/%s", + ndctl_namespace_get_block_device(ndns)); + fd = open(bdevpath, O_RDONLY); if (fd < 0) { fprintf(stderr, "%s: failed to open(%s, O_RDONLY)\n", @@ -948,11 +1257,19 @@ static int check_namespaces(struct ndctl_region *region, break; } + if (pfn_s && check_pfn_autodetect(bus, ndns, buf, + namespace) < 0) { + fprintf(stderr, "%s, failed pfn autodetect\n", devname); + rc = -ENXIO; + break; + } + + /* * if the namespace is being tested with a btt, there is no * point testing different sector sizes for the namespace itself */ - if (btt_s) + if (btt_s || pfn_s) break; /* @@ -1532,10 +1849,28 @@ static int check_dimms(struct ndctl_bus *bus, struct dimm *dimms, int n, return 0; } +static void reset_bus(struct ndctl_bus *bus) +{ + struct ndctl_region *region; + struct ndctl_dimm *dimm; + + /* disable all regions so that set_config_data commands are permitted */ + ndctl_region_foreach(bus, region) + ndctl_region_disable_invalidate(region); + + ndctl_dimm_foreach(bus, dimm) + ndctl_dimm_zero_labels(dimm); + + /* set regions back to their default state */ + ndctl_region_foreach(bus, region) + ndctl_region_enable(region); +} + static int do_test0(struct ndctl_ctx *ctx, struct ndctl_test *test) { struct ndctl_bus *bus = ndctl_bus_get_by_provider(ctx, NFIT_PROVIDER0); struct ndctl_region *region; + struct ndctl_dimm *dimm; int rc; if (!bus) @@ -1550,11 +1885,24 @@ static int do_test0(struct ndctl_ctx *ctx, struct ndctl_test *test) if (rc) return rc; + ndctl_dimm_foreach(bus, dimm) { + rc = ndctl_dimm_zero_labels(dimm); + if (rc < 0) { + fprintf(stderr, "failed to zero %s\n", + ndctl_dimm_get_devname(dimm)); + return rc; + } + } + /* set regions back to their default state */ ndctl_region_foreach(bus, region) ndctl_region_enable(region); - return check_regions(bus, regions0, ARRAY_SIZE(regions0)); + rc = check_regions(bus, regions0, ARRAY_SIZE(regions0), BTT); + if (rc) + return rc; + reset_bus(bus); + return check_regions(bus, regions0, ARRAY_SIZE(regions0), PFN); } static int do_test1(struct ndctl_ctx *ctx, struct ndctl_test *test) @@ -1569,7 +1917,7 @@ static int do_test1(struct ndctl_ctx *ctx, struct ndctl_test *test) if (rc) return rc; - return check_regions(bus, regions1, ARRAY_SIZE(regions1)); + return check_regions(bus, regions1, ARRAY_SIZE(regions1), BTT); } typedef int (*do_test_fn)(struct ndctl_ctx *ctx, struct ndctl_test *test);