From patchwork Tue Jun 30 00:31:44 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Williams X-Patchwork-Id: 6692441 Return-Path: X-Original-To: patchwork-linux-nvdimm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 74B4BC05AC for ; Tue, 30 Jun 2015 00:37:36 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id BE6F520603 for ; Tue, 30 Jun 2015 00:37:33 +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 E613C20602 for ; Tue, 30 Jun 2015 00:37:30 +0000 (UTC) Received: from ml01.vlan14.01.org (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id D7F76182803; Mon, 29 Jun 2015 17:37:30 -0700 (PDT) X-Original-To: linux-nvdimm@lists.01.org Delivered-To: linux-nvdimm@lists.01.org Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by ml01.01.org (Postfix) with ESMTP id CD4B018268A for ; Mon, 29 Jun 2015 17:37:29 -0700 (PDT) Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga103.fm.intel.com with ESMTP; 29 Jun 2015 17:37:29 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.15,373,1432623600"; d="scan'208";a="755481725" Received: from dwillia2-desk3.jf.intel.com ([10.54.39.11]) by orsmga002.jf.intel.com with ESMTP; 29 Jun 2015 17:37:28 -0700 Subject: [ndctl PATCH 3/4] ndctl: rework btt instances to consume namespaces instead of block_devices From: Dan Williams To: linux-nvdimm@lists.01.org Date: Mon, 29 Jun 2015 20:31:44 -0400 Message-ID: <20150630003144.7510.85616.stgit@dwillia2-desk3.jf.intel.com> In-Reply-To: <20150630002707.7510.11816.stgit@dwillia2-desk3.jf.intel.com> References: <20150630002707.7510.11816.stgit@dwillia2-desk3.jf.intel.com> User-Agent: StGit/0.17.1-8-g92dd 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.5 required=5.0 tests=BAYES_00,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 The kernel has made the btt device a child of a region, a peer of the namespace devices in the region. It has also arranged for btt devices to be driven by the pmem driver or the nd_blk driver depending on which namespace type is hosting the btt. This has several implications: 1/ replace ndctl_btt_{get|set}_backing_dev() with ndctl_btt_{get|set}_namespace() 2/ add ndctl_namespace_get_btt() since there will now always be a 1:1 relationship between a btt and a namespace 3/ read-only-policy management is now centrally managed via a region's "read_only" attribute. Add ndctl_{get|set}_ro() apis. Update the unit test accordingly. 4/ The kernel has removed the 'delete' property in favor of auto-removing / resetting a btt instance when its associated namespace is removed. Previously a btt would be removed when its backing block device was removed. 5/ Enabling a namespace may instead trigger a btt device to get created and enabled (bound to the namespace driver). The return value from ndctl_namespace_enable() now encodes this possibility with a positive return code indicating that the namespace is not enabled, but a hosted btt instance in that namespace is enabled. 6/ The behavior of probing for a btt instance on a namespace can be suppressed by setting the 'raw_mode' flag for the namespace. The ndctl_namespace_{set,get}_raw_mode() apis are added for this purpose. 7/ BTT instances are now invalidated on region disable, so we need to track their 'generation' same as namesapces. Acked-by: Vishal Verma Signed-off-by: Dan Williams --- lib/libndctl.c | 377 ++++++++++++++++++++++++++++++++++---------------- lib/libndctl.sym | 13 +- lib/ndctl/libndctl.h | 23 ++- lib/test-libndctl.c | 256 +++++++++++++++++++--------------- ndctl.h | 2 5 files changed, 425 insertions(+), 246 deletions(-) diff --git a/lib/libndctl.c b/lib/libndctl.c index 366ea4a013a3..86a3a365f1d4 100644 --- a/lib/libndctl.c +++ b/lib/libndctl.c @@ -91,12 +91,10 @@ struct ndctl_bus { struct ndctl_ctx *ctx; unsigned int id, major, minor, revision; char *provider; - struct list_head btts; struct list_head dimms; struct list_head regions; struct list_node list; int dimms_init; - int btts_init; int regions_init; int has_nfit; char *bus_path; @@ -181,24 +179,27 @@ struct ndctl_mapping { * coordinating configuration with peer regions. * * When a region is disabled a client may have pending references to - * namespaces. After a disable event the client can + * namespaces and btts. After a disable event the client can * ndctl_region_cleanup() to clean up invalid objects, or it can * specify the cleanup flag to ndctl_region_disable(). */ struct ndctl_region { struct kmod_module *module; struct ndctl_bus *bus; - int id, num_mappings, nstype, range_index; + int id, num_mappings, nstype, range_index, ro; int mappings_init; int namespaces_init; + int btts_init; unsigned long long size; char *region_path; char *region_buf; int buf_len; int generation; + struct list_head btts; struct list_head mappings; struct list_head namespaces; struct list_head stale_namespaces; + struct list_head stale_btts; struct list_node list; /** * struct ndctl_interleave_set - extra info for interleave sets @@ -242,7 +243,7 @@ struct ndctl_namespace { char *ndns_path; char *ndns_buf; char *bdev; - int type, id, buf_len; + int type, id, buf_len, raw_mode; int generation; unsigned long long size; char *alt_name; @@ -254,8 +255,8 @@ struct ndctl_namespace { * struct ndctl_btt - stacked block device provided sector atomicity * @module: kernel module (nd_btt) * @lbasize: sector size info - * @bus: parent bus - * @backing_dev: backing block device name + * @ndns: host namespace for the btt instance + * @region: parent region * @btt_path: btt devpath * @uuid: unique identifier for a btt instance * @btt_buf: space to print paths for bind/unbind operations @@ -263,16 +264,16 @@ struct ndctl_namespace { */ struct ndctl_btt { struct kmod_module *module; - struct ndctl_bus *bus; + struct ndctl_region *region; + struct ndctl_namespace *ndns; struct list_node list; struct ndctl_lbasize lbasize; - char *backing_dev; char *btt_path; char *btt_buf; char *bdev; int buf_len; uuid_t uuid; - int id; + int id, generation; }; /** @@ -505,12 +506,47 @@ static void free_namespace(struct ndctl_namespace *ndns, struct list_head *head) free(ndns); } -static void free_namespaces(struct ndctl_region *region, struct list_head *head) +static void free_namespaces(struct ndctl_region *region) +{ + struct ndctl_namespace *ndns, *_n; + + list_for_each_safe(®ion->namespaces, ndns, _n, list) + free_namespace(ndns, ®ion->namespaces); +} + +static void free_stale_namespaces(struct ndctl_region *region) { struct ndctl_namespace *ndns, *_n; - list_for_each_safe(head, ndns, _n, list) - free_namespace(ndns, head); + list_for_each_safe(®ion->stale_namespaces, ndns, _n, list) + free_namespace(ndns, ®ion->stale_namespaces); +} + +static void free_btt(struct ndctl_btt *btt, struct list_head *head) +{ + if (head) + list_del_from(head, &btt->list); + kmod_module_unref(btt->module); + free(btt->lbasize.supported); + free(btt->btt_path); + free(btt->btt_buf); + free(btt); +} + +static void free_btts(struct ndctl_region *region) +{ + struct ndctl_btt *btt, *_b; + + list_for_each_safe(®ion->btts, btt, _b, list) + free_btt(btt, ®ion->btts); +} + +static void free_stale_btts(struct ndctl_region *region) +{ + struct ndctl_btt *btt, *_b; + + list_for_each_safe(®ion->stale_btts, btt, _b, list) + free_btt(btt, ®ion->stale_btts); } static void free_region(struct ndctl_region *region) @@ -522,8 +558,10 @@ static void free_region(struct ndctl_region *region) list_del_from(®ion->mappings, &mapping->list); free(mapping); } - free_namespaces(region, ®ion->namespaces); - free_namespaces(region, ®ion->stale_namespaces); + free_btts(region); + free_stale_btts(region); + free_namespaces(region); + free_stale_namespaces(region); list_del_from(&bus->regions, ®ion->list); kmod_module_unref(region->module); free(region->region_buf); @@ -531,25 +569,8 @@ static void free_region(struct ndctl_region *region) free(region); } -#define BTT_DELETE 1 -#define BTT_SKIP_DELETE 0 -static void free_btt(struct ndctl_btt *btt, int delete) -{ - struct ndctl_bus *bus = btt->bus; - - if (delete) - list_del_from(&bus->btts, &btt->list); - kmod_module_unref(btt->module); - free(btt->lbasize.supported); - free(btt->backing_dev); - free(btt->btt_path); - free(btt->btt_buf); - free(btt); -} - static void free_bus(struct ndctl_bus *bus) { - struct ndctl_btt *btt, *_b; struct ndctl_dimm *dimm, *_d; struct ndctl_region *region, *_r; @@ -557,8 +578,6 @@ static void free_bus(struct ndctl_bus *bus) list_del_from(&bus->dimms, &dimm->list); free(dimm); } - list_for_each_safe(&bus->btts, btt, _b, list) - free_btt(btt, BTT_DELETE); list_for_each_safe(&bus->regions, region, _r, list) free_region(region); list_del_from(&bus->ctx->busses, &bus->list); @@ -841,7 +860,6 @@ static int add_bus(void *parent, int id, const char *ctl_base) bus = calloc(1, sizeof(*bus)); if (!bus) goto err_bus; - list_head_init(&bus->btts); list_head_init(&bus->dimms); list_head_init(&bus->regions); bus->ctx = ctx; @@ -983,29 +1001,54 @@ NDCTL_EXPORT struct ndctl_bus *ndctl_bus_get_by_provider(struct ndctl_ctx *ctx, return NULL; } -NDCTL_EXPORT struct ndctl_btt *ndctl_bus_get_btt_seed(struct ndctl_bus *bus) +NDCTL_EXPORT struct ndctl_btt *ndctl_region_get_btt_seed(struct ndctl_region *region) { - struct ndctl_ctx *ctx = ndctl_bus_get_ctx(bus); - char *path = bus->bus_buf; - int len = bus->buf_len; + struct ndctl_ctx *ctx = ndctl_region_get_ctx(region); + char *path = region->region_buf; + int len = region->buf_len; struct ndctl_btt *btt; char buf[50]; - if (snprintf(path, len, "%s/btt_seed", bus->bus_path) >= len) { + if (snprintf(path, len, "%s/btt_seed", region->region_path) >= len) { err(ctx, "%s: buffer too small!\n", - ndctl_bus_get_devname(bus)); + ndctl_region_get_devname(region)); return NULL; } if (sysfs_read_attr(ctx, path, buf) < 0) return NULL; - ndctl_btt_foreach(bus, btt) + ndctl_btt_foreach(region, btt) if (strcmp(buf, ndctl_btt_get_devname(btt)) == 0) return btt; return NULL; } +NDCTL_EXPORT int ndctl_region_get_ro(struct ndctl_region *region) +{ + return region->ro; +} + +NDCTL_EXPORT int ndctl_region_set_ro(struct ndctl_region *region, int ro) +{ + struct ndctl_ctx *ctx = ndctl_region_get_ctx(region); + char *path = region->region_buf; + int len = region->buf_len; + + if (snprintf(path, len, "%s/read_only", region->region_path) >= len) { + err(ctx, "%s: buffer too small!\n", + ndctl_region_get_devname(region)); + return -ENXIO; + } + + ro = !!ro; + if (sysfs_write_attr(ctx, path, ro ? "1\n" : "0\n") < 0) + return -ENXIO; + + region->ro = ro; + return ro; +} + NDCTL_EXPORT const char *ndctl_bus_get_cmd_name(struct ndctl_bus *bus, int cmd) { return nvdimm_bus_cmd_name(cmd); @@ -1404,6 +1447,8 @@ static int add_region(void *parent, int id, const char *region_base) region = calloc(1, sizeof(*region)); if (!region) goto err_region; + list_head_init(®ion->btts); + list_head_init(®ion->stale_btts); list_head_init(®ion->mappings); list_head_init(®ion->namespaces); list_head_init(®ion->stale_namespaces); @@ -1443,6 +1488,11 @@ static int add_region(void *parent, int id, const char *region_base) region->iset.cookie); } + sprintf(path, "%s/read_only", region_base); + if (sysfs_read_attr(ctx, path, buf) < 0) + goto err_read; + region->ro = strtoul(buf, NULL, 0); + sprintf(path, "%s/modalias", region_base); if (sysfs_read_attr(ctx, path, buf) < 0) goto err_read; @@ -2189,7 +2239,8 @@ NDCTL_EXPORT int ndctl_region_enable(struct ndctl_region *region) NDCTL_EXPORT void ndctl_region_cleanup(struct ndctl_region *region) { - free_namespaces(region, ®ion->stale_namespaces); + free_stale_namespaces(region); + free_stale_btts(region); } static int ndctl_region_disable(struct ndctl_region *region, int cleanup) @@ -2207,7 +2258,9 @@ static int ndctl_region_disable(struct ndctl_region *region, int cleanup) return -EBUSY; } region->namespaces_init = 0; + region->btts_init = 0; list_append_list(®ion->stale_namespaces, ®ion->namespaces); + list_append_list(®ion->stale_btts, ®ion->btts); region->generation++; if (cleanup) ndctl_region_cleanup(region); @@ -2545,6 +2598,11 @@ static int add_namespace(void *parent, int id, const char *ndns_base) goto err_read; ndns->size = strtoull(buf, NULL, 0); + sprintf(path, "%s/force_raw", ndns_base); + if (sysfs_read_attr(ctx, path, buf) < 0) + goto err_read; + ndns->raw_mode = strtoul(buf, NULL, 0); + switch (ndns->type) { case ND_DEVICE_NAMESPACE_BLK: sprintf(path, "%s/sector_size", ndns_base); @@ -2670,6 +2728,30 @@ NDCTL_EXPORT const char *ndctl_namespace_get_devname(struct ndctl_namespace *ndn return devpath_to_devname(ndns->ndns_path); } +NDCTL_EXPORT struct ndctl_btt *ndctl_namespace_get_btt(struct ndctl_namespace *ndns) +{ + struct ndctl_region *region = ndctl_namespace_get_region(ndns); + struct ndctl_ctx *ctx = ndctl_namespace_get_ctx(ndns); + char *path = ndns->ndns_buf; + int len = ndns->buf_len; + struct ndctl_btt *btt; + char buf[50]; + + if (snprintf(path, len, "%s/holder", ndns->ndns_path) >= len) { + err(ctx, "%s: buffer too small!\n", + ndctl_namespace_get_devname(ndns)); + return NULL; + } + + if (sysfs_read_attr(ctx, path, buf) < 0) + return NULL; + + ndctl_btt_foreach(region, btt) + if (strcmp(buf, ndctl_btt_get_devname(btt)) == 0) + return btt; + return NULL; +} + NDCTL_EXPORT const char *ndctl_namespace_get_block_device(struct ndctl_namespace *ndns) { struct ndctl_ctx *ctx = ndctl_namespace_get_ctx(ndns); @@ -2698,6 +2780,32 @@ NDCTL_EXPORT int ndctl_namespace_is_valid(struct ndctl_namespace *ndns) return ndns->generation == region->generation; } +NDCTL_EXPORT int ndctl_namespace_get_raw_mode(struct ndctl_namespace *ndns) +{ + return ndns->raw_mode; +} + +NDCTL_EXPORT int ndctl_namespace_set_raw_mode(struct ndctl_namespace *ndns, + int raw_mode) +{ + struct ndctl_ctx *ctx = ndctl_namespace_get_ctx(ndns); + char *path = ndns->ndns_buf; + int len = ndns->buf_len; + + if (snprintf(path, len, "%s/force_raw", ndns->ndns_path) >= len) { + err(ctx, "%s: buffer too small!\n", + ndctl_namespace_get_devname(ndns)); + return -ENXIO; + } + + raw_mode = !!raw_mode; + if (sysfs_write_attr(ctx, path, raw_mode ? "1\n" : "0\n") < 0) + return -ENXIO; + + ndns->raw_mode = raw_mode; + return raw_mode; +} + NDCTL_EXPORT int ndctl_namespace_is_enabled(struct ndctl_namespace *ndns) { struct ndctl_ctx *ctx = ndctl_namespace_get_ctx(ndns); @@ -2788,13 +2896,30 @@ static int ndctl_unbind(struct ndctl_ctx *ctx, const char *devpath) return sysfs_write_attr(ctx, path, devname); } -static void btts_init(struct ndctl_bus *bus); +static int add_btt(void *parent, int id, const char *btt_base); + +static void btts_init(struct ndctl_region *region) +{ + struct ndctl_bus *bus = ndctl_region_get_bus(region); + char btt_fmt[20]; + + if (region->btts_init) + return; + region->btts_init = 1; + + sprintf(btt_fmt, "btt%d.", region->id); + device_parse(bus->ctx, bus, region->region_path, btt_fmt, region, add_btt); +} +/* + * Return 0 if enabled, < 0 if failed to enable, and > 0 if claimed by + * another device and that device is enabled. In the > 0 case a + * subsequent call to ndctl_namespace_is_enabled() will return 'false'. + */ NDCTL_EXPORT int ndctl_namespace_enable(struct ndctl_namespace *ndns) { const char *devname = ndctl_namespace_get_devname(ndns); struct ndctl_ctx *ctx = ndctl_namespace_get_ctx(ndns); - struct ndctl_bus *bus = ndctl_namespace_get_bus(ndns); struct ndctl_region *region = ndns->region; int rc; @@ -2804,22 +2929,31 @@ NDCTL_EXPORT int ndctl_namespace_enable(struct ndctl_namespace *ndns) rc = ndctl_bind(ctx, ndns->module, devname); if (!ndctl_namespace_is_enabled(ndns)) { + struct ndctl_btt *btt = ndctl_namespace_get_btt(ndns); + + if (btt && ndctl_btt_is_enabled(btt)) { + dbg(ctx, "%s: enabled via %s\n", devname, + ndctl_btt_get_devname(btt)); + rc = 1; + goto out; + } err(ctx, "%s: failed to enable\n", devname); return rc ? rc : -ENXIO; } + rc = 0; + dbg(ctx, "%s: enabled\n", devname); /* * Rescan now as successfully enabling a namespace device leads * to a new one being created, and potentially btts being attached */ + out: region->namespaces_init = 0; + region->btts_init = 0; namespaces_init(region); - bus->btts_init = 0; - btts_init(bus); + btts_init(region); - dbg(ctx, "%s: enabled\n", devname); - - return 0; + return rc; } NDCTL_EXPORT int ndctl_namespace_disable(struct ndctl_namespace *ndns) @@ -3133,10 +3267,10 @@ static int parse_lbasize_supported(struct ndctl_ctx *ctx, const char *devname, static int add_btt(void *parent, int id, const char *btt_base) { + struct ndctl_ctx *ctx = ndctl_region_get_ctx(parent); const char *devname = devpath_to_devname(btt_base); char *path = calloc(1, strlen(btt_base) + 100); - struct ndctl_bus *bus = parent; - struct ndctl_ctx *ctx = bus->ctx; + struct ndctl_region *region = parent; struct ndctl_btt *btt, *btt_dup; char buf[SYSFS_ATTR_SIZE]; int rc = -ENOMEM; @@ -3148,7 +3282,8 @@ static int add_btt(void *parent, int id, const char *btt_base) if (!btt) goto err_btt; btt->id = id; - btt->bus = bus; + btt->region = region; + btt->generation = region->generation; btt->btt_path = strdup(btt_base); if (!btt->btt_path) @@ -3178,21 +3313,14 @@ static int add_btt(void *parent, int id, const char *btt_base) if (parse_lbasize_supported(ctx, devname, buf, &btt->lbasize) < 0) goto err_read; - sprintf(path, "%s/backing_dev", btt_base); - if (sysfs_read_attr(ctx, path, buf) < 0) - goto err_read; - btt->backing_dev = strdup(buf); - if (!btt->backing_dev) - goto err_read; - free(path); - ndctl_btt_foreach(bus, btt_dup) + ndctl_btt_foreach(region, btt_dup) if (btt->id == btt_dup->id) { - free_btt(btt, BTT_SKIP_DELETE); + free_btt(btt, NULL); return 1; } - list_add(&bus->btts, &btt->list); + list_add(®ion->btts, &btt->list); return 0; err_read: @@ -3205,27 +3333,18 @@ static int add_btt(void *parent, int id, const char *btt_base) return rc; } -static void btts_init(struct ndctl_bus *bus) +NDCTL_EXPORT struct ndctl_btt *ndctl_btt_get_first(struct ndctl_region *region) { - if (bus->btts_init) - return; - bus->btts_init = 1; + btts_init(region); - device_parse(bus->ctx, bus, bus->bus_path, "btt", bus, add_btt); -} - -NDCTL_EXPORT struct ndctl_btt *ndctl_btt_get_first(struct ndctl_bus *bus) -{ - btts_init(bus); - - return list_top(&bus->btts, struct ndctl_btt, list); + return list_top(®ion->btts, struct ndctl_btt, list); } NDCTL_EXPORT struct ndctl_btt *ndctl_btt_get_next(struct ndctl_btt *btt) { - struct ndctl_bus *bus = btt->bus; + struct ndctl_region *region = btt->region; - return list_next(&bus->btts, btt, list); + return list_next(®ion->btts, btt, list); } NDCTL_EXPORT unsigned int ndctl_btt_get_id(struct ndctl_btt *btt) @@ -3252,9 +3371,32 @@ NDCTL_EXPORT int ndctl_btt_get_num_sector_sizes(struct ndctl_btt *btt) return btt->lbasize.num; } -NDCTL_EXPORT const char *ndctl_btt_get_backing_dev(struct ndctl_btt *btt) +NDCTL_EXPORT struct ndctl_namespace *ndctl_btt_get_namespace(struct ndctl_btt *btt) { - return btt->backing_dev; + struct ndctl_ctx *ctx = ndctl_btt_get_ctx(btt); + struct ndctl_namespace *ndns, *found = NULL; + struct ndctl_region *region = btt->region; + char *path = region->region_buf; + int len = region->buf_len; + char buf[50]; + + if (btt->ndns) + return btt->ndns; + + if (snprintf(path, len, "%s/namespace", btt->btt_path) >= len) { + err(ctx, "%s: buffer too small!\n", + ndctl_btt_get_devname(btt)); + return NULL; + } + + if (sysfs_read_attr(ctx, path, buf) < 0) + return NULL; + + ndctl_namespace_foreach(region, ndns) + if (strcmp(buf, ndctl_namespace_get_devname(ndns)) == 0) + found = ndns; + btt->ndns = found; + return found; } NDCTL_EXPORT void ndctl_btt_get_uuid(struct ndctl_btt *btt, uuid_t uu) @@ -3307,31 +3449,30 @@ NDCTL_EXPORT int ndctl_btt_set_sector_size(struct ndctl_btt *btt, return 0; } -NDCTL_EXPORT int ndctl_btt_set_backing_dev(struct ndctl_btt *btt, - const char *backing_dev) +NDCTL_EXPORT int ndctl_btt_set_namespace(struct ndctl_btt *btt, + struct ndctl_namespace *ndns) { struct ndctl_ctx *ctx = ndctl_btt_get_ctx(btt); char *path = btt->btt_buf; int len = btt->buf_len; - if (snprintf(path, len, "%s/backing_dev", btt->btt_path) >= len) { + if (snprintf(path, len, "%s/namespace", btt->btt_path) >= len) { err(ctx, "%s: buffer too small!\n", ndctl_btt_get_devname(btt)); return -ENXIO; } - if (sysfs_write_attr(ctx, path, backing_dev ? : "\n") != 0) + if (sysfs_write_attr(ctx, path, ndns + ? ndctl_namespace_get_devname(ndns) : "\n")) return -ENXIO; - free(btt->backing_dev); - btt->backing_dev = backing_dev ? strdup(backing_dev) : NULL; - + btt->ndns = ndns; return 0; } NDCTL_EXPORT struct ndctl_bus *ndctl_btt_get_bus(struct ndctl_btt *btt) { - return btt->bus; + return btt->region->bus; } NDCTL_EXPORT struct ndctl_ctx *ndctl_btt_get_ctx(struct ndctl_btt *btt) @@ -3365,6 +3506,13 @@ NDCTL_EXPORT const char *ndctl_btt_get_block_device(struct ndctl_btt *btt) return btt->bdev ? btt->bdev : ""; } +NDCTL_EXPORT int ndctl_btt_is_valid(struct ndctl_btt *btt) +{ + struct ndctl_region *region = ndctl_btt_get_region(btt); + + return btt->generation == region->generation; +} + NDCTL_EXPORT int ndctl_btt_is_enabled(struct ndctl_btt *btt) { struct ndctl_ctx *ctx = ndctl_btt_get_ctx(btt); @@ -3380,11 +3528,16 @@ NDCTL_EXPORT int ndctl_btt_is_enabled(struct ndctl_btt *btt) return is_enabled(ndctl_btt_get_bus(btt), path); } +NDCTL_EXPORT struct ndctl_region *ndctl_btt_get_region(struct ndctl_btt *btt) +{ + return btt->region; +} + NDCTL_EXPORT int ndctl_btt_enable(struct ndctl_btt *btt) { + struct ndctl_region *region = ndctl_btt_get_region(btt); const char *devname = ndctl_btt_get_devname(btt); struct ndctl_ctx *ctx = ndctl_btt_get_ctx(btt); - struct ndctl_bus *bus = ndctl_btt_get_bus(btt); char *path = btt->btt_buf; int len = btt->buf_len; @@ -3411,58 +3564,48 @@ NDCTL_EXPORT int ndctl_btt_enable(struct ndctl_btt *btt) * Rescan now as successfully enabling a btt device leads to a * new one being created */ - bus->btts_init = 0; - btts_init(bus); + region->btts_init = 0; + btts_init(region); return 0; } NDCTL_EXPORT int ndctl_btt_delete(struct ndctl_btt *btt) { + struct ndctl_region *region = ndctl_btt_get_region(btt); struct ndctl_ctx *ctx = ndctl_btt_get_ctx(btt); - int len = btt->buf_len, rc; - char *path = btt->btt_buf; + int rc; - /* - * Only permit deletion when we know a replacement seed device - * is present. - */ - if (!ndctl_btt_is_enabled(btt)) - return -EINVAL; + if (!ndctl_btt_is_valid(btt)) { + free_btt(btt, ®ion->stale_btts); + return 0; + } ndctl_unbind(ctx, btt->btt_path); - rc = ndctl_btt_set_backing_dev(btt, NULL); + rc = ndctl_btt_set_namespace(btt, NULL); if (rc) { - dbg(ctx, "%s: failed to clear backing dev: %d\n", + dbg(ctx, "%s: failed to clear namespace: %d\n", ndctl_btt_get_devname(btt), rc); return rc; } - if (snprintf(path, len, "%s/delete", btt->btt_path) >= len) { - err(ctx, "%s: buffer too small!\n", - ndctl_btt_get_devname(btt)); - return -EINVAL; - } - - rc = sysfs_write_attr(ctx, path, "1\n"); - if (rc < 0) - return -ENXIO; - free_btt(btt, BTT_DELETE); + free_btt(btt, ®ion->btts); + region->btts_init = 0; return 0; } NDCTL_EXPORT int ndctl_btt_is_configured(struct ndctl_btt *btt) { - if (ndctl_btt_get_sector_size(btt) == UINT_MAX) - return 0; + if (ndctl_btt_get_namespace(btt)) + return 1; - if (strcmp(ndctl_btt_get_backing_dev(btt), "") == 0) - return 0; + if (ndctl_btt_get_sector_size(btt) != UINT_MAX) + return 1; - if (memcmp(&btt->uuid, null_uuid, sizeof(null_uuid)) == 0) - return 0; + if (memcmp(&btt->uuid, null_uuid, sizeof(null_uuid)) != 0) + return 1; - return 1; + return 0; } diff --git a/lib/libndctl.sym b/lib/libndctl.sym index e21ffdd3a0a4..3391a095490c 100644 --- a/lib/libndctl.sym +++ b/lib/libndctl.sym @@ -24,7 +24,6 @@ global: ndctl_bus_get_minor; ndctl_bus_get_devname; ndctl_bus_get_by_provider; - ndctl_bus_get_btt_seed; ndctl_bus_get_cmd_name; ndctl_bus_is_cmd_supported; ndctl_bus_has_nfit; @@ -85,6 +84,7 @@ global: ndctl_region_get_available_size; ndctl_region_get_type; ndctl_region_get_namespace_seed; + ndctl_region_get_btt_seed; ndctl_region_get_type_name; ndctl_region_get_bus; ndctl_region_get_ctx; @@ -96,6 +96,8 @@ global: ndctl_region_disable_preserve; ndctl_region_cleanup; ndctl_region_get_interleave_set; + ndctl_region_get_ro; + ndctl_region_set_ro; ndctl_interleave_set_get_first; ndctl_interleave_set_get_next; ndctl_interleave_set_is_active; @@ -115,6 +117,7 @@ global: ndctl_namespace_get_next; ndctl_namespace_get_ctx; ndctl_namespace_get_bus; + ndctl_namespace_get_btt; ndctl_namespace_get_region; ndctl_namespace_get_id; ndctl_namespace_get_devname; @@ -138,22 +141,26 @@ global: ndctl_namespace_get_sector_size; ndctl_namespace_get_num_sector_sizes; ndctl_namespace_set_sector_size; + ndctl_namespace_get_raw_mode; + ndctl_namespace_set_raw_mode; ndctl_btt_get_first; ndctl_btt_get_next; ndctl_btt_get_ctx; ndctl_btt_get_bus; + ndctl_btt_get_region; ndctl_btt_get_id; ndctl_btt_get_supported_sector_size; ndctl_btt_get_sector_size; ndctl_btt_get_num_sector_sizes; - ndctl_btt_get_backing_dev; + ndctl_btt_get_namespace; ndctl_btt_get_uuid; ndctl_btt_is_enabled; + ndctl_btt_is_valid; ndctl_btt_get_devname; ndctl_btt_get_block_device; ndctl_btt_set_uuid; ndctl_btt_set_sector_size; - ndctl_btt_set_backing_dev; + ndctl_btt_set_namespace; ndctl_btt_enable; ndctl_btt_delete; ndctl_btt_is_configured; diff --git a/lib/ndctl/libndctl.h b/lib/ndctl/libndctl.h index 18c3cf303692..c92910db2015 100644 --- a/lib/ndctl/libndctl.h +++ b/lib/ndctl/libndctl.h @@ -103,7 +103,6 @@ unsigned int ndctl_bus_get_minor(struct ndctl_bus *bus); const char *ndctl_bus_get_devname(struct ndctl_bus *bus); struct ndctl_bus *ndctl_bus_get_by_provider(struct ndctl_ctx *ctx, const char *provider); -struct ndctl_btt *ndctl_bus_get_btt_seed(struct ndctl_bus *bus); const char *ndctl_bus_get_cmd_name(struct ndctl_bus *bus, int cmd); int ndctl_bus_is_cmd_supported(struct ndctl_bus *bus, int cmd); unsigned int ndctl_bus_get_revision(struct ndctl_bus *bus); @@ -194,6 +193,9 @@ unsigned int ndctl_region_get_range_index(struct ndctl_region *region); unsigned int ndctl_region_get_type(struct ndctl_region *region); struct ndctl_namespace *ndctl_region_get_namespace_seed( struct ndctl_region *region); +int ndctl_region_get_ro(struct ndctl_region *region); +int ndctl_region_set_ro(struct ndctl_region *region, int ro); +struct ndctl_btt *ndctl_region_get_btt_seed(struct ndctl_region *region); unsigned int ndctl_region_get_nstype(struct ndctl_region *region); const char *ndctl_region_get_type_name(struct ndctl_region *region); struct ndctl_bus *ndctl_region_get_bus(struct ndctl_region *region); @@ -266,6 +268,7 @@ struct ndctl_namespace *ndctl_namespace_get_next(struct ndctl_namespace *ndns); struct ndctl_ctx *ndctl_namespace_get_ctx(struct ndctl_namespace *ndns); struct ndctl_bus *ndctl_namespace_get_bus(struct ndctl_namespace *ndns); struct ndctl_region *ndctl_namespace_get_region(struct ndctl_namespace *ndns); +struct ndctl_btt *ndctl_namespace_get_btt(struct ndctl_namespace *ndns); unsigned int ndctl_namespace_get_id(struct ndctl_namespace *ndns); const char *ndctl_namespace_get_devname(struct ndctl_namespace *ndns); unsigned int ndctl_namespace_get_type(struct ndctl_namespace *ndns); @@ -291,34 +294,38 @@ unsigned int ndctl_namespace_get_sector_size(struct ndctl_namespace *ndns); int ndctl_namespace_get_num_sector_sizes(struct ndctl_namespace *ndns); int ndctl_namespace_set_sector_size(struct ndctl_namespace *ndns, unsigned int sector_size); +int ndctl_namespace_get_raw_mode(struct ndctl_namespace *ndns); +int ndctl_namespace_set_raw_mode(struct ndctl_namespace *ndns, int raw_mode); struct ndctl_btt; -struct ndctl_btt *ndctl_btt_get_first(struct ndctl_bus *bus); +struct ndctl_btt *ndctl_btt_get_first(struct ndctl_region *region); struct ndctl_btt *ndctl_btt_get_next(struct ndctl_btt *btt); -#define ndctl_btt_foreach(bus, btt) \ - for (btt = ndctl_btt_get_first(bus); \ +#define ndctl_btt_foreach(region, btt) \ + for (btt = ndctl_btt_get_first(region); \ btt != NULL; \ btt = ndctl_btt_get_next(btt)) -#define ndctl_btt_foreach_safe(bus, btt, _btt) \ - for (btt = ndctl_btt_get_first(bus), \ +#define ndctl_btt_foreach_safe(region, btt, _btt) \ + for (btt = ndctl_btt_get_first(region), \ _btt = ndctl_btt_get_next(btt); \ btt != NULL; \ btt = _btt, \ _btt = _btt ? ndctl_btt_get_next(_btt) : NULL) struct ndctl_ctx *ndctl_btt_get_ctx(struct ndctl_btt *btt); struct ndctl_bus *ndctl_btt_get_bus(struct ndctl_btt *btt); +struct ndctl_region *ndctl_btt_get_region(struct ndctl_btt *btt); unsigned int ndctl_btt_get_id(struct ndctl_btt *btt); unsigned int ndctl_btt_get_supported_sector_size(struct ndctl_btt *btt, int i); unsigned int ndctl_btt_get_sector_size(struct ndctl_btt *btt); int ndctl_btt_get_num_sector_sizes(struct ndctl_btt *btt); -const char *ndctl_btt_get_backing_dev(struct ndctl_btt *btt); +struct ndctl_namespace *ndctl_btt_get_namespace(struct ndctl_btt *btt); void ndctl_btt_get_uuid(struct ndctl_btt *btt, uuid_t uu); int ndctl_btt_is_enabled(struct ndctl_btt *btt); +int ndctl_btt_is_valid(struct ndctl_btt *btt); const char *ndctl_btt_get_devname(struct ndctl_btt *btt); const char *ndctl_btt_get_block_device(struct ndctl_btt *btt); int ndctl_btt_set_uuid(struct ndctl_btt *btt, uuid_t uu); int ndctl_btt_set_sector_size(struct ndctl_btt *btt, unsigned int sector_size); -int ndctl_btt_set_backing_dev(struct ndctl_btt *btt, const char *backing_dev); +int ndctl_btt_set_namespace(struct ndctl_btt *btt, struct ndctl_namespace *ndns); int ndctl_btt_enable(struct ndctl_btt *btt); int ndctl_btt_delete(struct ndctl_btt *btt); int ndctl_btt_is_configured(struct ndctl_btt *btt); diff --git a/lib/test-libndctl.c b/lib/test-libndctl.c index f8e9797d4483..8c1d6c992db6 100644 --- a/lib/test-libndctl.c +++ b/lib/test-libndctl.c @@ -150,6 +150,13 @@ static struct dimm dimms1[] = { } }; +struct btt { + int enabled; + uuid_t uuid; + int num_sector_sizes; + unsigned int sector_sizes[7]; +}; + struct region { union { unsigned int range_index; @@ -163,16 +170,10 @@ struct region { struct set { int active; } iset; + struct btt *btts[2]; struct namespace *namespaces[4]; }; -struct btt { - int enabled; - uuid_t uuid; - int num_sector_sizes; - unsigned int sector_sizes[7]; -}; - static struct btt btt_settings = { .enabled = 1, .uuid = { 0, 1, 2, 3, 4, 5, 6, 7, @@ -263,19 +264,61 @@ static struct namespace namespace5_blk0 = { 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 }, - { &namespace0_pmem0, NULL, }, }, + .namespaces = { + [0] = &namespace0_pmem0, + }, + .btts = { + [0] = &default_btt, + }, + }, { { 2 }, 4, 1, "pmem", SZ_64M, SZ_64M, { 1 }, - { &namespace1_pmem0, NULL, }, }, - { { DIMM_HANDLE(0, 0, 0, 0, 0) }, 1, 1, "blk", SZ_18M, SZ_32M, { }, - { &namespace2_blk0, &namespace2_blk1, NULL, }, }, - { { DIMM_HANDLE(0, 0, 0, 0, 1) }, 1, 1, "blk", SZ_18M, SZ_32M, { }, - { &namespace3_blk0, &namespace3_blk1, NULL, }, }, - { { DIMM_HANDLE(0, 0, 1, 0, 0) }, 1, 1, "blk", SZ_27M, SZ_32M, { }, - { &namespace4_blk0, NULL, }, }, - { { DIMM_HANDLE(0, 0, 1, 0, 1) }, 1, 1, "blk", SZ_27M, SZ_32M, { }, - { &namespace5_blk0, NULL, }, }, + .namespaces = { + [0] = &namespace1_pmem0, + }, + .btts = { + [0] = &default_btt, + }, + }, + { { DIMM_HANDLE(0, 0, 0, 0, 0) }, 1, 1, "blk", SZ_18M, SZ_32M, + .namespaces = { + [0] = &namespace2_blk0, + [1] = &namespace2_blk1, + }, + .btts = { + [0] = &default_btt, + }, + }, + { { DIMM_HANDLE(0, 0, 0, 0, 1) }, 1, 1, "blk", SZ_18M, SZ_32M, + .namespaces = { + [0] = &namespace3_blk0, + [1] = &namespace3_blk1, + }, + .btts = { + [0] = &default_btt, + }, + }, + { { DIMM_HANDLE(0, 0, 1, 0, 0) }, 1, 1, "blk", SZ_27M, SZ_32M, + .namespaces = { + [0] = &namespace4_blk0, + }, + .btts = { + [0] = &default_btt, + }, + }, + { { DIMM_HANDLE(0, 0, 1, 0, 1) }, 1, 1, "blk", SZ_27M, SZ_32M, + .namespaces = { + [0] = &namespace5_blk0, + }, + .btts = { + [0] = &default_btt, + }, + }, }; static struct namespace namespace1 = { @@ -294,14 +337,6 @@ static struct region regions1[] = { }, }; -static struct btt btts0[] = { - { 0, { 0, }, 7, { 512, 520, 528, 4096, 4104, 4160, 4224, }, }, -}; - -static struct btt btts1[] = { - { 0, { 0, }, 7, { 512, 520, 528, 4096, 4104, 4160, 4224, }, }, -}; - static unsigned long commands0 = 1UL << ND_CMD_GET_CONFIG_SIZE | 1UL << ND_CMD_GET_CONFIG_DATA | 1UL << ND_CMD_SET_CONFIG_DATA; @@ -317,11 +352,11 @@ static struct ndctl_dimm *get_dimm_by_handle(struct ndctl_bus *bus, unsigned int return NULL; } -static struct ndctl_btt *get_idle_btt(struct ndctl_bus *bus) +static struct ndctl_btt *get_idle_btt(struct ndctl_region *region) { struct ndctl_btt *btt; - ndctl_btt_foreach(bus, btt) + ndctl_btt_foreach(region, btt) if (!ndctl_btt_is_enabled(btt) && !ndctl_btt_is_configured(btt)) return btt; @@ -388,6 +423,7 @@ static struct ndctl_region *get_blk_region_by_dimm_handle(struct ndctl_bus *bus, static int check_namespaces(struct ndctl_region *region, struct namespace **namespaces); +static int check_btts(struct ndctl_region *region, struct btt **btts); static int check_regions(struct ndctl_bus *bus, struct region *regions, int n) { @@ -464,6 +500,10 @@ static int check_regions(struct ndctl_bus *bus, struct region *regions, int n) return -ENXIO; } + rc = check_btts(region, regions[i].btts); + if (rc) + return rc; + if (regions[i].namespaces) rc = check_namespaces(region, regions[i].namespaces); if (rc) @@ -473,9 +513,10 @@ static int check_regions(struct ndctl_bus *bus, struct region *regions, int n) return rc; } -static int check_btt_create(struct ndctl_bus *bus, struct ndctl_namespace *ndns, - struct btt *create_btt) +static int check_btt_create(struct ndctl_region *region, struct ndctl_namespace *ndns, + struct namespace *namespace) { + struct btt *btt_s = namespace->btt_settings; int i, fd, retry = 10; struct ndctl_btt *btt; const char *devname; @@ -483,25 +524,41 @@ static int check_btt_create(struct ndctl_bus *bus, struct ndctl_namespace *ndns, void *buf = NULL; ssize_t rc; - if (!create_btt) + if (!namespace->btt_settings) return 0; if (posix_memalign(&buf, 4096, 4096) != 0) return -ENXIO; - for (i = 0; i < create_btt->num_sector_sizes; i++) { - btt = get_idle_btt(bus); + for (i = 0; i < btt_s->num_sector_sizes; i++) { + btt = get_idle_btt(region); if (!btt) return -ENXIO; - sprintf(bdevpath, "/dev/%s", ndctl_namespace_get_block_device(ndns)); - ndctl_btt_set_uuid(btt, create_btt->uuid); - ndctl_btt_set_sector_size(btt, create_btt->sector_sizes[i]); - ndctl_btt_set_backing_dev(btt, bdevpath); - ndctl_btt_enable(btt); + devname = ndctl_btt_get_devname(btt); + ndctl_btt_set_uuid(btt, btt_s->uuid); + ndctl_btt_set_sector_size(btt, btt_s->sector_sizes[i]); + ndctl_btt_set_namespace(btt, ndns); + ndctl_namespace_disable(ndns); + rc = ndctl_btt_enable(btt); + if (namespace->ro == (rc == 0)) { + fprintf(stderr, "%s: expected btt enable %s, %s read-%s\n", + devname, + namespace->ro ? "failure" : "success", + ndctl_region_get_devname(region), + namespace->ro ? "only" : "write"); + return -ENXIO; + } + if (namespace->ro) { + ndctl_region_set_ro(region, 0); + rc = ndctl_btt_enable(btt); + fprintf(stderr, "%s: failed to enable after setting rw\n", + devname); + ndctl_region_set_ro(region, 1); + return -ENXIO; + } sprintf(bdevpath, "/dev/%s", ndctl_btt_get_block_device(btt)); - devname = ndctl_btt_get_devname(btt); rc = -ENXIO; fd = open(bdevpath, O_RDWR|O_DIRECT); if (fd < 0) @@ -531,6 +588,8 @@ static int check_btt_create(struct ndctl_bus *bus, struct ndctl_namespace *ndns, rc = 0; break; } + if (namespace->ro) + ndctl_region_set_ro(region, 1); if (fd >= 0) close(fd); @@ -591,16 +650,16 @@ static int check_btt_autodetect(struct ndctl_bus *bus, struct ndctl_namespace *ndns, void *buf, struct namespace *namespace) { - const char *ndns_bdev = ndctl_namespace_get_block_device(ndns); + struct ndctl_region *region = ndctl_namespace_get_region(ndns); const char *devname = ndctl_namespace_get_devname(ndns); struct btt *auto_btt = namespace->btt_settings; struct ndctl_btt *btt, *found = NULL; - int btt_fd = -1, backing_fd = -1, ro; - const char *backing_bdev; ssize_t rc = -ENXIO; - char btt_bdev[50]; + char bdev[50]; + int fd, ro; - ndctl_btt_foreach(bus, btt) { + ndctl_btt_foreach(region, btt) { + struct ndctl_namespace *btt_ndns; uuid_t uu; ndctl_btt_get_uuid(btt, uu); @@ -608,9 +667,11 @@ static int check_btt_autodetect(struct ndctl_bus *bus, continue; if (!ndctl_btt_is_enabled(btt)) continue; - backing_bdev = ndctl_btt_get_backing_dev(btt); - if (strcmp(backing_bdev+5, ndns_bdev) != 0) + btt_ndns = ndctl_btt_get_namespace(btt); + if (strcmp(ndctl_namespace_get_devname(btt_ndns), devname) != 0) continue; + fprintf(stderr, "%s: btt_ndns: %p ndns: %p\n", __func__, + btt_ndns, ndns); found = btt; break; } @@ -618,13 +679,13 @@ static int check_btt_autodetect(struct ndctl_bus *bus, if (!found) return -ENXIO; - sprintf(btt_bdev, "/dev/%s", ndctl_btt_get_block_device(btt)); - btt_fd = open(btt_bdev, O_RDONLY); - if (btt_fd < 0) + sprintf(bdev, "/dev/%s", ndctl_btt_get_block_device(btt)); + fd = open(bdev, O_RDONLY); + if (fd < 0) return -ENXIO; - rc = ioctl(btt_fd, BLKROGET, &ro); + rc = ioctl(fd, BLKROGET, &ro); if (rc < 0) { - fprintf(stderr, "%s: failed to open %s\n", __func__, btt_bdev); + fprintf(stderr, "%s: failed to open %s\n", __func__, bdev); rc = -ENXIO; goto out; } @@ -632,70 +693,40 @@ static int check_btt_autodetect(struct ndctl_bus *bus, rc = -ENXIO; if (ro != namespace->ro) { fprintf(stderr, "%s: read-%s expected read-%s by default\n", - btt_bdev, ro ? "only" : "write", + bdev, ro ? "only" : "write", namespace->ro ? "only" : "write"); goto out; } - backing_fd = open(backing_bdev, O_RDONLY); - if (backing_fd < 0) { - fprintf(stderr, "%s: failed to open %s to set rw\n", - __func__, backing_bdev); - goto out; - } - - ro = 0; - rc = ioctl(backing_fd, BLKROSET, &ro); - if (rc < 0) { - fprintf(stderr, "failed to set %s rw\n", backing_bdev); - rc = -ENXIO; - goto out; - } - - rc = ioctl(btt_fd, BLKROGET, &ro); - if (rc < 0) { - fprintf(stderr, "failed to verify that %s is now rw\n", - btt_bdev); - rc = -ENXIO; - goto out; - } - - if (ro) { - fprintf(stderr, "setting %s rw did not set %s rw\n", - backing_bdev, btt_bdev); - rc = -ENXIO; - goto out; - } - - backing_bdev = strdup(backing_bdev); - if (!backing_bdev) { - fprintf(stderr, "%s: failed to dup backing_bdev\n", devname); - goto out; - } - + /* destroy btt device */ ndctl_btt_delete(found); - /* destroy btt */ - backing_fd = open(backing_bdev, O_RDWR|O_DIRECT|O_EXCL); - if (backing_fd < 0) { + /* 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 btt 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 btt\n", - devname, backing_bdev); + devname, bdev); goto out; } memset(buf, 0, 4096); - rc = pwrite(backing_fd, buf, 4096, 4096); + rc = pwrite(fd, buf, 4096, 4096); if (rc < 4096) { rc = -ENXIO; fprintf(stderr, "%s: failed to overwrite btt on %s\n", - devname, backing_bdev); + devname, bdev); } out: - free((char *) backing_bdev); - if (backing_fd >= 0) - close(backing_fd); - if (btt_fd >= 0) - close(btt_fd); + ndctl_region_set_ro(region, namespace->ro); + ndctl_namespace_set_raw_mode(ndns, 0); + if (fd >= 0) + close(fd); return rc; } @@ -846,7 +877,7 @@ static int check_namespaces(struct ndctl_region *region, close(fd); fd = -1; - if (check_btt_create(bus, ndns, namespace->btt_settings) < 0) { + if (check_btt_create(region, ndns, namespace) < 0) { fprintf(stderr, "%s: failed to create btt\n", devname); rc = -ENXIO; break; @@ -976,17 +1007,18 @@ static int check_btt_supported_sectors(struct ndctl_btt *btt, struct btt *expect return 0; } -static int check_btts(struct ndctl_bus *bus, struct btt *btts, int n) +static int check_btts(struct ndctl_region *region, struct btt **btts) { + struct btt *btt_s; int i; - for (i = 0; i < n; i++) { + for (i = 0; (btt_s = btts[i]); i++) { struct ndctl_btt *btt; char devname[50]; uuid_t btt_uuid; int rc; - btt = get_idle_btt(bus); + btt = get_idle_btt(region); if (!btt) { fprintf(stderr, "failed to find idle btt\n"); return -ENXIO; @@ -994,24 +1026,24 @@ static int check_btts(struct ndctl_bus *bus, struct btt *btts, int n) snprintf(devname, sizeof(devname), "btt%d", ndctl_btt_get_id(btt)); ndctl_btt_get_uuid(btt, btt_uuid); - if (uuid_compare(btt_uuid, btts[i].uuid) != 0) { + if (uuid_compare(btt_uuid, btt_s->uuid) != 0) { char expect[40], actual[40]; uuid_unparse(btt_uuid, actual); - uuid_unparse(btts[i].uuid, expect); + uuid_unparse(btt_s->uuid, expect); fprintf(stderr, "%s: expected uuid: %s got: %s\n", devname, expect, actual); return -ENXIO; } - if (ndctl_btt_get_num_sector_sizes(btt) != btts[i].num_sector_sizes) { + if (ndctl_btt_get_num_sector_sizes(btt) != btt_s->num_sector_sizes) { fprintf(stderr, "%s: expected num_sector_sizes: %d got: %d\n", - devname, btts[i].num_sector_sizes, + devname, btt_s->num_sector_sizes, ndctl_btt_get_num_sector_sizes(btt)); } - rc = check_btt_supported_sectors(btt, &btts[i]); + rc = check_btt_supported_sectors(btt, btt_s); if (rc) return rc; - if (btts[i].enabled && ndctl_btt_is_enabled(btt)) { + if (btt_s->enabled && ndctl_btt_is_enabled(btt)) { fprintf(stderr, "%s: expected disabled by default\n", devname); return -ENXIO; @@ -1289,10 +1321,6 @@ static int do_test0(struct ndctl_ctx *ctx) if (rc) return rc; - rc = check_btts(bus, btts0, ARRAY_SIZE(btts0)); - if (rc) - return rc; - /* set regions back to their default state */ ndctl_region_foreach(bus, region) ndctl_region_enable(region); @@ -1312,10 +1340,6 @@ static int do_test1(struct ndctl_ctx *ctx) if (rc) return rc; - rc = check_btts(bus, btts1, ARRAY_SIZE(btts1)); - if (rc) - return rc; - return check_regions(bus, regions1, ARRAY_SIZE(regions1)); } diff --git a/ndctl.h b/ndctl.h index 2a04206e3bbe..e678a48cd976 100644 --- a/ndctl.h +++ b/ndctl.h @@ -181,7 +181,6 @@ static __inline__ const char *nvdimm_cmd_name(unsigned cmd) #define ND_DEVICE_NAMESPACE_IO 4 /* legacy persistent memory */ #define ND_DEVICE_NAMESPACE_PMEM 5 /* PMEM namespace (may alias with BLK) */ #define ND_DEVICE_NAMESPACE_BLK 6 /* BLK namespace (may alias with PMEM) */ -#define ND_DEVICE_BTT 7 /* block-translation table device */ enum nd_driver_flags { ND_DRIVER_DIMM = 1 << ND_DEVICE_DIMM, @@ -190,7 +189,6 @@ enum nd_driver_flags { ND_DRIVER_NAMESPACE_IO = 1 << ND_DEVICE_NAMESPACE_IO, ND_DRIVER_NAMESPACE_PMEM = 1 << ND_DEVICE_NAMESPACE_PMEM, ND_DRIVER_NAMESPACE_BLK = 1 << ND_DEVICE_NAMESPACE_BLK, - ND_DRIVER_BTT = 1 << ND_DEVICE_BTT, }; enum {