linux-nvdimm.lists.01.org archive mirror
 help / color / mirror / Atom feed
* [ndctl PATCH] ndctl/namespace: Reconfigure in-place
@ 2020-11-20  2:37 Dan Williams
  0 siblings, 0 replies; only message in thread
From: Dan Williams @ 2020-11-20  2:37 UTC (permalink / raw)
  To: linux-nvdimm; +Cc: Steve Scargall

While it has been documented that the namespace reconfiguration process
involves destroying and recreating a namespace, the kernel device changing
as result of a reconfigure operation is surprising. For example a sequence
like:

ndctl create-namespace -s 4G
ndctl create-namespace -s 4G
ndctl create-namespace -s 4G

Results in 3 namespaces:

namespace0.0
namespace0.1
namespace0.2

...whereby after each creation step the next seed is incremented. At the
end of this process namespace0.3 is the next namespace that will be
created. However, when reconfiguration also picks the seed for the target
vessel of the new namespace configuration it is unexpected that:

ndctl create-namespace -e namespace0.1 -m sector

...results in namespace0.3 becoming enabled.

Teach the reconfigure path in ndctl to try to reuse the existing kernel
device whenever possible.

Reported-by: Steve Scargall <steve.scargall@intel.com>
Link: https://github.com/pmem/ndctl/issues/152
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 ndctl/namespace.c |   69 +++++++++++++++++++++++++++++++++++------------------
 1 file changed, 45 insertions(+), 24 deletions(-)

diff --git a/ndctl/namespace.c b/ndctl/namespace.c
index f61e0fcda015..f223650628b8 100644
--- a/ndctl/namespace.c
+++ b/ndctl/namespace.c
@@ -1091,11 +1091,10 @@ static int zero_info_block(struct ndctl_namespace *ndns)
 	return rc;
 }
 
-static int namespace_destroy(struct ndctl_region *region,
+static int namespace_prep_reconfig(struct ndctl_region *region,
 		struct ndctl_namespace *ndns)
 {
 	const char *devname = ndctl_namespace_get_devname(ndns);
-	unsigned long long size;
 	bool did_zero = false;
 	int rc;
 
@@ -1109,12 +1108,12 @@ static int namespace_destroy(struct ndctl_region *region,
 		error("%s is active, specify --force for re-configuration\n",
 				devname);
 		return -EBUSY;
-	} else {
-		rc = ndctl_namespace_disable_safe(ndns);
-		if (rc)
-			return rc;
 	}
 
+	rc = ndctl_namespace_disable_safe(ndns);
+	if (rc)
+		return rc;
+
 	ndctl_namespace_set_enforce_mode(ndns, NDCTL_NS_MODE_RAW);
 
 	rc = zero_info_block(ndns);
@@ -1126,6 +1125,7 @@ static int namespace_destroy(struct ndctl_region *region,
 	switch (ndctl_namespace_get_type(ndns)) {
         case ND_DEVICE_NAMESPACE_PMEM:
         case ND_DEVICE_NAMESPACE_BLK:
+		rc = 2;
 		break;
 	default:
 		/*
@@ -1137,14 +1137,31 @@ static int namespace_destroy(struct ndctl_region *region,
 			rc = 0;
 		else
 			rc = 1;
-		goto out;
+		break;
 	}
 
+	return rc;
+}
+
+static int namespace_destroy(struct ndctl_region *region,
+		struct ndctl_namespace *ndns)
+{
+	const char *devname = ndctl_namespace_get_devname(ndns);
+	unsigned long long size;
+	int rc;
+
+	rc = namespace_prep_reconfig(region, ndns);
+	if (rc < 0)
+		return rc;
+
 	size = ndctl_namespace_get_size(ndns);
 
-	rc = ndctl_namespace_delete(ndns);
-	if (rc)
-		debug("%s: failed to reclaim\n", devname);
+	/* Labeled namespace, destroy label / allocation */
+	if (rc == 2) {
+		rc = ndctl_namespace_delete(ndns);
+		if (rc)
+			debug("%s: failed to reclaim\n", devname);
+	}
 
 	/*
 	 * Don't report a destroyed namespace when no capacity was
@@ -1153,7 +1170,6 @@ static int namespace_destroy(struct ndctl_region *region,
 	if (size == 0 && rc == 0)
 		rc = 1;
 
-out:
 	return rc;
 }
 
@@ -1167,7 +1183,7 @@ static int enable_labels(struct ndctl_region *region)
 
 	/* no dimms => no labels */
 	if (!mappings)
-		return 0;
+		return -ENODEV;
 
 	count = 0;
 	ndctl_dimm_foreach_in_region(region, dimm) {
@@ -1182,7 +1198,7 @@ static int enable_labels(struct ndctl_region *region)
 
 	/* all the dimms must support labeling */
 	if (count != mappings)
-		return 0;
+		return -ENODEV;
 
 	ndctl_region_disable_invalidate(region);
 	count = 0;
@@ -1250,23 +1266,28 @@ static int namespace_reconfig(struct ndctl_region *region,
 	if (rc)
 		return rc;
 
-	rc = namespace_destroy(region, ndns);
+	rc = namespace_prep_reconfig(region, ndns);
 	if (rc < 0)
 		return rc;
 
 	/* check if we can enable labels on this region */
 	if (ndctl_region_get_nstype(region) == ND_DEVICE_NAMESPACE_IO
 			&& p.autolabel) {
-		/* if this fails, try to continue label-less */
-		enable_labels(region);
-	}
-
-	ndns = region_get_namespace(region);
-	if (!ndns || !ndctl_namespace_is_configuration_idle(ndns)) {
-		debug("%s: no %s namespace seed\n",
-				ndctl_region_get_devname(region),
-				ndns ? "idle" : "available");
-		return -ENODEV;
+		/*
+		 * If this fails, try to continue label-less, if this
+		 * got far enough to invalidate the region than @ndns is
+		 * now invalid.
+		 */
+		rc = enable_labels(region);
+		if (rc != -ENODEV)
+			ndns = region_get_namespace(region);
+		if (!ndns || (rc != -ENODEV
+				&& !ndctl_namespace_is_configuration_idle(ndns))) {
+			debug("%s: no %s namespace seed\n",
+					ndctl_region_get_devname(region),
+					ndns ? "idle" : "available");
+			return -ENODEV;
+		}
 	}
 
 	return setup_namespace(region, ndns, &p);
_______________________________________________
Linux-nvdimm mailing list -- linux-nvdimm@lists.01.org
To unsubscribe send an email to linux-nvdimm-leave@lists.01.org

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2020-11-20  2:37 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-20  2:37 [ndctl PATCH] ndctl/namespace: Reconfigure in-place Dan Williams

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).