nvdimm.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
* [ndctl PATCH 0/5] Address Range Scrub (ARS) Utilities
@ 2018-04-04 21:11 Dan Williams
  2018-04-04 21:12 ` [ndctl PATCH 1/5] ndctl, scrub: fix ndctl_bus_wait_for_scrub_completion() Dan Williams
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Dan Williams @ 2018-04-04 21:11 UTC (permalink / raw)
  To: linux-nvdimm

Add ndctl utility support for listing the state of ARS operations,
waiting for an existing ARS run to complete, and initiating new ARS
runs. A few fixes and new apis fall out as a result.

---

Dan Williams (5):
      ndctl, scrub: fix ndctl_bus_wait_for_scrub_completion()
      ndctl, scrub: report the bus scrub state in 'ndctl list'
      ndctl, scrub: add ndctl_bus_start_scrub()
      ndctl: add new START and WAIT actions
      ndctl, scrub: add {wait,start}-scrub helper utilities


 Documentation/ndctl/Makefile.am           |    3 +
 Documentation/ndctl/ars-description.txt   |    9 ++
 Documentation/ndctl/ndctl-start-scrub.txt |   61 ++++++++++++++
 Documentation/ndctl/ndctl-wait-scrub.txt  |   61 ++++++++++++++
 builtin.h                                 |    2 
 ndctl/Makefile.am                         |    1 
 ndctl/action.h                            |    2 
 ndctl/bus.c                               |  129 +++++++++++++++++++++++++++++
 ndctl/lib/libndctl.c                      |  107 ++++++++++++++++--------
 ndctl/lib/libndctl.sym                    |    2 
 ndctl/libndctl.h                          |    2 
 ndctl/namespace.c                         |    3 +
 ndctl/ndctl.c                             |    2 
 util/json.c                               |   10 ++
 14 files changed, 359 insertions(+), 35 deletions(-)
 create mode 100644 Documentation/ndctl/ars-description.txt
 create mode 100644 Documentation/ndctl/ndctl-start-scrub.txt
 create mode 100644 Documentation/ndctl/ndctl-wait-scrub.txt
 create mode 100644 ndctl/bus.c
_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [ndctl PATCH 1/5] ndctl, scrub: fix ndctl_bus_wait_for_scrub_completion()
  2018-04-04 21:11 [ndctl PATCH 0/5] Address Range Scrub (ARS) Utilities Dan Williams
@ 2018-04-04 21:12 ` Dan Williams
  2018-04-04 21:12 ` [ndctl PATCH 2/5] ndctl, scrub: report the bus scrub state in 'ndctl list' Dan Williams
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Dan Williams @ 2018-04-04 21:12 UTC (permalink / raw)
  To: linux-nvdimm

Given that we trust the kernel to increment the scrub count when
transitioning from in-progress to idle it is safe to wait forever.
Previously this routine was mistakenly waiting 120ms when it thought it
was waiting 120 seconds, was not verifying the in-progress was
cleared after a wakeup, and was not checking for the POLLMSG events that
sysfs files emit.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 ndctl/lib/libndctl.c |   45 ++++++++++++++++++++-------------------------
 1 file changed, 20 insertions(+), 25 deletions(-)

diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
index 580a450e837c..743863b5c7e7 100644
--- a/ndctl/lib/libndctl.c
+++ b/ndctl/lib/libndctl.c
@@ -1154,55 +1154,50 @@ NDCTL_EXPORT unsigned int ndctl_bus_get_scrub_count(struct ndctl_bus *bus)
 NDCTL_EXPORT int ndctl_bus_wait_for_scrub_completion(struct ndctl_bus *bus)
 {
 	struct ndctl_ctx *ctx = ndctl_bus_get_ctx(bus);
-	unsigned int tmo = 120, scrub_count;
+	unsigned int scrub_count;
 	char buf[SYSFS_ATTR_SIZE];
-	char in_progress = '\0';
 	struct pollfd fds;
+	char in_progress;
 	int fd = 0, rc;
 
 	fd = open(bus->scrub_path, O_RDONLY|O_CLOEXEC);
+	memset(&fds, 0, sizeof(fds));
 	fds.fd = fd;
-	fds.events =  POLLPRI | POLLIN;
-	do {
+	for (;;) {
 		rc = sysfs_read_attr(ctx, bus->scrub_path, buf);
-		if (rc < 0)
+		if (rc < 0) {
+			rc = -EOPNOTSUPP;
 			break;
+		}
 
 		rc = sscanf(buf, "%u%c", &scrub_count, &in_progress);
-		if (rc < 0)
+		if (rc < 0) {
+			rc = -EOPNOTSUPP;
 			break;
-		else if (rc <= 1) {
+		}
+
+		if (rc == 1) {
 			/* scrub complete, break successfully */
 			rc = 0;
 			break;
 		} else if (rc == 2 && in_progress == '+') {
 			/* scrub in progress, wait */
-			rc = poll(&fds, 1, tmo);
+			rc = poll(&fds, 1, -1);
 			if (rc < 0) {
-				dbg(ctx, "poll error: %d\n", errno);
-				break;
-			} else if (rc == 0) {
-				dbg(ctx, "poll timeout after: %d seconds", tmo);
-				rc = -ENXIO;
+				rc = -errno;
+				dbg(ctx, "poll error: %s\n", strerror(errno));
 				break;
 			}
-			if (fds.revents & (POLLERR | POLLHUP | POLLNVAL)) {
-				dbg(ctx, "poll error, revents: %d\n",
-					fds.revents);
-				rc = -ENXIO;
-				break;
-			}
-		} else {
-			/* unknown condition */
-			rc = -ENXIO;
-			break;
+			dbg(ctx, "poll wake: revents: %d\n", fds.revents);
+			pread(fd, buf, 1, 0);
+			fds.revents = 0;
 		}
-	} while (in_progress);
+	}
 
 	dbg(ctx, "bus%d: scrub complete\n", ndctl_bus_get_id(bus));
 	if (fd)
 		close (fd);
-	return rc < 0 ? -ENXIO : 0;
+	return rc;
 }
 
 static int ndctl_bind(struct ndctl_ctx *ctx, struct kmod_module *module,

_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [ndctl PATCH 2/5] ndctl, scrub: report the bus scrub state in 'ndctl list'
  2018-04-04 21:11 [ndctl PATCH 0/5] Address Range Scrub (ARS) Utilities Dan Williams
  2018-04-04 21:12 ` [ndctl PATCH 1/5] ndctl, scrub: fix ndctl_bus_wait_for_scrub_completion() Dan Williams
@ 2018-04-04 21:12 ` Dan Williams
  2018-04-04 21:12 ` [ndctl PATCH 3/5] ndctl, scrub: add ndctl_bus_start_scrub() Dan Williams
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Dan Williams @ 2018-04-04 21:12 UTC (permalink / raw)
  To: linux-nvdimm

In preparation for adding 'wait-scrub' and 'start-scrub' utility
helpers, indicate the current state of ARS operations in the listing for
bus objects. The field is omitted if the bus does not support ARS
operations.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 ndctl/lib/libndctl.c   |   49 ++++++++++++++++++++++++++++++++++++++----------
 ndctl/lib/libndctl.sym |    1 +
 ndctl/libndctl.h       |    1 +
 util/json.c            |   10 ++++++++++
 4 files changed, 51 insertions(+), 10 deletions(-)

diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
index 743863b5c7e7..ff0d44ffefe6 100644
--- a/ndctl/lib/libndctl.c
+++ b/ndctl/lib/libndctl.c
@@ -1114,29 +1114,58 @@ NDCTL_EXPORT int ndctl_bus_wait_probe(struct ndctl_bus *bus)
 	return rc < 0 ? -ENXIO : 0;
 }
 
-NDCTL_EXPORT unsigned int ndctl_bus_get_scrub_count(struct ndctl_bus *bus)
+static int __ndctl_bus_get_scrub_state(struct ndctl_bus *bus,
+		unsigned int *scrub_count, bool *active)
 {
 	struct ndctl_ctx *ctx = ndctl_bus_get_ctx(bus);
 	char buf[SYSFS_ATTR_SIZE];
-	unsigned int scrub_count;
 	char in_progress = '\0';
 	int rc;
 
 	rc = sysfs_read_attr(ctx, bus->scrub_path, buf);
 	if (rc < 0)
-		return UINT_MAX;
+		return -EOPNOTSUPP;
 
-	rc = sscanf(buf, "%u%c", &scrub_count, &in_progress);
+	rc = sscanf(buf, "%u%c", scrub_count, &in_progress);
 	if (rc < 0)
-		return UINT_MAX;
-	if (rc == 0) {
+		return -ENXIO;
+
+	switch (rc) {
+	case 1:
+		*active = false;
+		return 0;
+	case 2:
+		if (in_progress == '+') {
+			*active = true;
+			return 0;
+		}
+		/* fall through */
+	default:
 		/* unable to read scrub count */
-		return UINT_MAX;
+		return -ENXIO;
 	}
-	if (rc >= 1)
-		return scrub_count;
+}
+
+NDCTL_EXPORT int ndctl_bus_get_scrub_state(struct ndctl_bus *bus)
+{
+	unsigned int scrub_count = 0;
+	bool active = false;
+	int rc;
+
+	rc = __ndctl_bus_get_scrub_state(bus, &scrub_count, &active);
+	if (rc < 0)
+		return rc;
+	return active;
+}
+
+NDCTL_EXPORT unsigned int ndctl_bus_get_scrub_count(struct ndctl_bus *bus)
+{
+	unsigned int scrub_count = 0;
+	bool active = false;
 
-	return UINT_MAX;
+	if (__ndctl_bus_get_scrub_state(bus, &scrub_count, &active))
+		return UINT_MAX;
+	return scrub_count;
 }
 
 /**
diff --git a/ndctl/lib/libndctl.sym b/ndctl/lib/libndctl.sym
index 3209aefe6672..06cace96724f 100644
--- a/ndctl/lib/libndctl.sym
+++ b/ndctl/lib/libndctl.sym
@@ -352,4 +352,5 @@ global:
 	ndctl_dimm_fw_update_supported;
 	ndctl_region_get_persistence_domain;
 	ndctl_bus_get_persistence_domain;
+	ndctl_bus_get_scrub_state;
 } LIBNDCTL_14;
diff --git a/ndctl/libndctl.h b/ndctl/libndctl.h
index cf6a77fd0992..36c04d871bd5 100644
--- a/ndctl/libndctl.h
+++ b/ndctl/libndctl.h
@@ -121,6 +121,7 @@ enum ndctl_persistence_domain ndctl_bus_get_persistence_domain(
 int ndctl_bus_wait_probe(struct ndctl_bus *bus);
 int ndctl_bus_wait_for_scrub_completion(struct ndctl_bus *bus);
 unsigned int ndctl_bus_get_scrub_count(struct ndctl_bus *bus);
+int ndctl_bus_get_scrub_state(struct ndctl_bus *bus);
 int ndctl_bus_has_error_injection(struct ndctl_bus *bus);
 
 struct ndctl_dimm;
diff --git a/util/json.c b/util/json.c
index a464f21d6d5a..5b4b4c374d44 100644
--- a/util/json.c
+++ b/util/json.c
@@ -124,6 +124,7 @@ struct json_object *util_bus_to_json(struct ndctl_bus *bus)
 {
 	struct json_object *jbus = json_object_new_object();
 	struct json_object *jobj;
+	int scrub;
 
 	if (!jbus)
 		return NULL;
@@ -138,6 +139,15 @@ struct json_object *util_bus_to_json(struct ndctl_bus *bus)
 		goto err;
 	json_object_object_add(jbus, "dev", jobj);
 
+	scrub = ndctl_bus_get_scrub_state(bus);
+	if (scrub < 0)
+		return jbus;
+
+	jobj = json_object_new_string(scrub ? "active" : "idle");
+	if (!jobj)
+		goto err;
+	json_object_object_add(jbus, "scrub_state", jobj);
+
 	return jbus;
  err:
 	json_object_put(jbus);

_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [ndctl PATCH 3/5] ndctl, scrub: add ndctl_bus_start_scrub()
  2018-04-04 21:11 [ndctl PATCH 0/5] Address Range Scrub (ARS) Utilities Dan Williams
  2018-04-04 21:12 ` [ndctl PATCH 1/5] ndctl, scrub: fix ndctl_bus_wait_for_scrub_completion() Dan Williams
  2018-04-04 21:12 ` [ndctl PATCH 2/5] ndctl, scrub: report the bus scrub state in 'ndctl list' Dan Williams
@ 2018-04-04 21:12 ` Dan Williams
  2018-04-04 21:12 ` [ndctl PATCH 4/5] ndctl: add new START and WAIT actions Dan Williams
  2018-04-04 21:12 ` [ndctl PATCH 5/5] ndctl, scrub: add {wait, start}-scrub helper utilities Dan Williams
  4 siblings, 0 replies; 6+ messages in thread
From: Dan Williams @ 2018-04-04 21:12 UTC (permalink / raw)
  To: linux-nvdimm

Provide a helper routine to kick off a new ARS scrub if one is not
already running, or otherwise detect if ARS functionality is available.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 ndctl/lib/libndctl.c   |   13 +++++++++++++
 ndctl/lib/libndctl.sym |    1 +
 ndctl/libndctl.h       |    1 +
 3 files changed, 15 insertions(+)

diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
index ff0d44ffefe6..21dd7207ea5e 100644
--- a/ndctl/lib/libndctl.c
+++ b/ndctl/lib/libndctl.c
@@ -1146,6 +1146,19 @@ static int __ndctl_bus_get_scrub_state(struct ndctl_bus *bus,
 	}
 }
 
+NDCTL_EXPORT int ndctl_bus_start_scrub(struct ndctl_bus *bus)
+{
+	struct ndctl_ctx *ctx = ndctl_bus_get_ctx(bus);
+	int rc;
+
+	rc = sysfs_write_attr(ctx, bus->scrub_path, "1\n");
+	if (rc == -EBUSY)
+		return rc;
+	else if (rc < 0)
+		return -EOPNOTSUPP;
+	return 0;
+}
+
 NDCTL_EXPORT int ndctl_bus_get_scrub_state(struct ndctl_bus *bus)
 {
 	unsigned int scrub_count = 0;
diff --git a/ndctl/lib/libndctl.sym b/ndctl/lib/libndctl.sym
index 06cace96724f..fd8f37d1783e 100644
--- a/ndctl/lib/libndctl.sym
+++ b/ndctl/lib/libndctl.sym
@@ -353,4 +353,5 @@ global:
 	ndctl_region_get_persistence_domain;
 	ndctl_bus_get_persistence_domain;
 	ndctl_bus_get_scrub_state;
+	ndctl_bus_start_scrub;
 } LIBNDCTL_14;
diff --git a/ndctl/libndctl.h b/ndctl/libndctl.h
index 36c04d871bd5..e690f9483fbf 100644
--- a/ndctl/libndctl.h
+++ b/ndctl/libndctl.h
@@ -122,6 +122,7 @@ int ndctl_bus_wait_probe(struct ndctl_bus *bus);
 int ndctl_bus_wait_for_scrub_completion(struct ndctl_bus *bus);
 unsigned int ndctl_bus_get_scrub_count(struct ndctl_bus *bus);
 int ndctl_bus_get_scrub_state(struct ndctl_bus *bus);
+int ndctl_bus_start_scrub(struct ndctl_bus *bus);
 int ndctl_bus_has_error_injection(struct ndctl_bus *bus);
 
 struct ndctl_dimm;

_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [ndctl PATCH 4/5] ndctl: add new START and WAIT actions
  2018-04-04 21:11 [ndctl PATCH 0/5] Address Range Scrub (ARS) Utilities Dan Williams
                   ` (2 preceding siblings ...)
  2018-04-04 21:12 ` [ndctl PATCH 3/5] ndctl, scrub: add ndctl_bus_start_scrub() Dan Williams
@ 2018-04-04 21:12 ` Dan Williams
  2018-04-04 21:12 ` [ndctl PATCH 5/5] ndctl, scrub: add {wait, start}-scrub helper utilities Dan Williams
  4 siblings, 0 replies; 6+ messages in thread
From: Dan Williams @ 2018-04-04 21:12 UTC (permalink / raw)
  To: linux-nvdimm

In preparation for adding 'start-scrub' and 'wait-scrub' utilities,
define new device actions for these operations.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 ndctl/action.h    |    2 ++
 ndctl/namespace.c |    3 +++
 2 files changed, 5 insertions(+)

diff --git a/ndctl/action.h b/ndctl/action.h
index 43ea62adbcd2..1ecad49530d5 100644
--- a/ndctl/action.h
+++ b/ndctl/action.h
@@ -11,5 +11,7 @@ enum device_action {
 	ACTION_CREATE,
 	ACTION_DESTROY,
 	ACTION_CHECK,
+	ACTION_WAIT,
+	ACTION_START,
 };
 #endif /* __NDCTL_ACTION_H__ */
diff --git a/ndctl/namespace.c b/ndctl/namespace.c
index aef356abbee1..1c39d9b01adc 100644
--- a/ndctl/namespace.c
+++ b/ndctl/namespace.c
@@ -1054,6 +1054,9 @@ static int do_xaction_namespace(const char *namespace,
 					if (rc < 0)
 						return rc;
 					return 1;
+				default:
+					rc = -EINVAL;
+					break;
 				}
 				if (rc >= 0)
 					success++;

_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [ndctl PATCH 5/5] ndctl, scrub: add {wait, start}-scrub helper utilities
  2018-04-04 21:11 [ndctl PATCH 0/5] Address Range Scrub (ARS) Utilities Dan Williams
                   ` (3 preceding siblings ...)
  2018-04-04 21:12 ` [ndctl PATCH 4/5] ndctl: add new START and WAIT actions Dan Williams
@ 2018-04-04 21:12 ` Dan Williams
  4 siblings, 0 replies; 6+ messages in thread
From: Dan Williams @ 2018-04-04 21:12 UTC (permalink / raw)
  To: linux-nvdimm

Provide utilities to make it easy for a platform owner to poll for the
completion of ARS scrubbing, or otherwise launch an ARS run across 1 or
more nvdimm buses.

These commands take 1 or more bus identifiers (bus device name, bus
number, or bus provider name), and runs a 'start' or 'wait' ARS
operation on each.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 Documentation/ndctl/Makefile.am           |    3 +
 Documentation/ndctl/ars-description.txt   |    9 ++
 Documentation/ndctl/ndctl-start-scrub.txt |   61 ++++++++++++++
 Documentation/ndctl/ndctl-wait-scrub.txt  |   61 ++++++++++++++
 builtin.h                                 |    2 
 ndctl/Makefile.am                         |    1 
 ndctl/bus.c                               |  129 +++++++++++++++++++++++++++++
 ndctl/ndctl.c                             |    2 
 8 files changed, 268 insertions(+)
 create mode 100644 Documentation/ndctl/ars-description.txt
 create mode 100644 Documentation/ndctl/ndctl-start-scrub.txt
 create mode 100644 Documentation/ndctl/ndctl-wait-scrub.txt
 create mode 100644 ndctl/bus.c

diff --git a/Documentation/ndctl/Makefile.am b/Documentation/ndctl/Makefile.am
index 9acb4acd966a..4f04087598b5 100644
--- a/Documentation/ndctl/Makefile.am
+++ b/Documentation/ndctl/Makefile.am
@@ -16,6 +16,8 @@ asciidoc.conf: ../asciidoc.conf.in
 
 man1_MANS = \
 	ndctl.1 \
+	ndctl-wait-scrub.1 \
+	ndctl-start-scrub.1 \
 	ndctl-zero-labels.1 \
 	ndctl-read-labels.1 \
 	ndctl-write-labels.1 \
@@ -46,6 +48,7 @@ XML_DEPS = \
 	dimm-description.txt \
 	xable-dimm-options.txt \
 	xable-namespace-options.txt \
+	ars-description.txt \
 	labels-description.txt \
 	labels-options.txt
 
diff --git a/Documentation/ndctl/ars-description.txt b/Documentation/ndctl/ars-description.txt
new file mode 100644
index 000000000000..23db8184dcf2
--- /dev/null
+++ b/Documentation/ndctl/ars-description.txt
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
+
+DESCRIPTION
+-----------
+NVDIMM Address Range Scrub is a capability provided by platform firmware
+that allows for the discovery of memory errors by system software. It
+enables system software to pre-emptively avoid accesses that could lead
+to uncorrectable memory error handling events, and it otherwise allows
+memory errors to be enumerated.
diff --git a/Documentation/ndctl/ndctl-start-scrub.txt b/Documentation/ndctl/ndctl-start-scrub.txt
new file mode 100644
index 000000000000..365918dec920
--- /dev/null
+++ b/Documentation/ndctl/ndctl-start-scrub.txt
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0
+
+ndctl-start-scrub(1)
+====================
+
+NAME
+----
+ndctl-start-scrub - start an Address Range Scrub (ARS) operation
+
+SYNOPSIS
+--------
+[verse]
+'ndctl start-scrub' [<bus-id> <bus-id2> ... <bus-idN>] [<options>]
+
+include::ars-description.txt[]
+
+The kernel provides a sysfs file ('scrub') that when written with the
+string "1\n" initiates an ARS operation. The 'ndctl start-scrub'
+operation starts an ARS, across all specified buses, and the kernel in
+turn proceeds to scrub every persistent memory address region on the
+specified buses.
+
+EXAMPLE
+-------
+Start a scrub on all nvdimm buses in the system. The json listing report
+only includes the buses that support ARS operations.
+[verse]
+
+# ndctl start-scrub
+[
+  {
+    "provider":"nfit_test.1",
+    "dev":"ndbus3",
+    "scrub_state":"active"
+  },
+  {
+    "provider":"nfit_test.0",
+    "dev":"ndbus2",
+    "scrub_state":"active"
+  }
+]
+
+When specifying an individual bus, or if there is only one bus in the
+system, the command reports whether ARS support is available.
+[verse]
+# ndctl start-scrub e820
+error starting scrub: Operation not supported
+
+OPTIONS
+-------
+-v::
+--verbose::
+	Emit debug messages for the ARS start process
+
+include::../copyright.txt[]
+
+SEE ALSO
+--------
+linkndctl:ndctl-wait-scrub[1],
+http://www.uefi.org/sites/default/files/resources/ACPI%206_2_A_Sept29.pdf[ACPI
+6.2 Specification Section 9.20.7.2 Address Range Scrubbing (ARS) Overview]
diff --git a/Documentation/ndctl/ndctl-wait-scrub.txt b/Documentation/ndctl/ndctl-wait-scrub.txt
new file mode 100644
index 000000000000..6b5f61fcf48f
--- /dev/null
+++ b/Documentation/ndctl/ndctl-wait-scrub.txt
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0
+
+ndctl-wait-scrub(1)
+====================
+
+NAME
+----
+ndctl-wait-scrub - wait for an Address Range Scrub (ARS) operation to complete
+
+SYNOPSIS
+--------
+[verse]
+'ndctl wait-scrub' [<bus-id> <bus-id2> ... <bus-idN>] [<options>]
+
+include::ars-description.txt[]
+
+The kernel provides a POLL(2) capable sysfs file ('scrub') to indicate
+the state of ARS. The 'scrub' file maintains a running count of ARS runs
+that have taken place. While a current run is in progress a '+'
+character is emitted along with the current count. The 'ndctl
+wait-scrub' operation waits for 'scrub', across all specified buses, to
+indicate not in-progress at least once.
+
+EXAMPLE
+-------
+Wait for scrub on all nvdimm buses in the system. The json listing
+report at the end only includes the buses that support ARS operations.
+[verse]
+# ndctl wait-scrub
+[
+  {
+    "provider":"nfit_test.1",
+    "dev":"ndbus3",
+    "scrub_state":"idle"
+  },
+  {
+    "provider":"nfit_test.0",
+    "dev":"ndbus2",
+    "scrub_state":"idle"
+  }
+]
+
+When specifying an individual bus, or if there is only one bus in the
+system, the command reports whether ARS support is available.
+[verse]
+# ndctl wait-scrub e820
+error waiting for scrub completion: Operation not supported
+
+OPTIONS
+-------
+-v::
+--verbose::
+	Emit debug messages for the ARS wait process
+
+include::../copyright.txt[]
+
+SEE ALSO
+--------
+linkndctl:ndctl-start-scrub[1],
+http://www.uefi.org/sites/default/files/resources/ACPI%206_2_A_Sept29.pdf[ACPI
+6.2 Specification Section 9.20.7.2 Address Range Scrubbing (ARS) Overview]
diff --git a/builtin.h b/builtin.h
index b24fc99781a9..d3cc7239cdd7 100644
--- a/builtin.h
+++ b/builtin.h
@@ -36,6 +36,8 @@ int cmd_write_labels(int argc, const char **argv, void *ctx);
 int cmd_init_labels(int argc, const char **argv, void *ctx);
 int cmd_check_labels(int argc, const char **argv, void *ctx);
 int cmd_inject_error(int argc, const char **argv, void *ctx);
+int cmd_wait_scrub(int argc, const char **argv, void *ctx);
+int cmd_start_scrub(int argc, const char **argv, void *ctx);
 int cmd_list(int argc, const char **argv, void *ctx);
 #ifdef ENABLE_TEST
 int cmd_test(int argc, const char **argv, void *ctx);
diff --git a/ndctl/Makefile.am b/ndctl/Makefile.am
index 213cabd77a39..d22a37951537 100644
--- a/ndctl/Makefile.am
+++ b/ndctl/Makefile.am
@@ -3,6 +3,7 @@ include $(top_srcdir)/Makefile.am.in
 bin_PROGRAMS = ndctl
 
 ndctl_SOURCES = ndctl.c \
+		bus.c \
 		create-nfit.c \
 		namespace.c \
 		check.c \
diff --git a/ndctl/bus.c b/ndctl/bus.c
new file mode 100644
index 000000000000..fc31d065b1a5
--- /dev/null
+++ b/ndctl/bus.c
@@ -0,0 +1,129 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2015-2018 Intel Corporation. All rights reserved. */
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "action.h"
+#include <syslog.h>
+#include <builtin.h>
+#include <util/json.h>
+#include <util/filter.h>
+#include <json-c/json.h>
+#include <util/parse-options.h>
+#include <ndctl/libndctl.h>
+#include <ccan/array_size/array_size.h>
+
+static struct {
+	bool verbose;
+} param;
+
+static const struct option bus_options[] = {
+	OPT_BOOLEAN('v',"verbose", &param.verbose, "turn on debug"),
+	OPT_END(),
+};
+
+static int scrub_action(struct ndctl_bus *bus, enum device_action action)
+{
+	switch (action) {
+	case ACTION_WAIT:
+		return ndctl_bus_wait_for_scrub_completion(bus);
+	case ACTION_START:
+		return ndctl_bus_start_scrub(bus);
+	default:
+		return -EINVAL;
+	}
+}
+
+static int bus_action(int argc, const char **argv, const char *usage,
+		const struct option *options, enum device_action action,
+		struct ndctl_ctx *ctx)
+{
+	const char * const u[] = {
+		usage,
+		NULL
+	};
+	struct json_object *jbuses, *jbus;
+	int i, rc, success = 0, fail = 0;
+	struct ndctl_bus *bus;
+	const char *all = "all";
+
+	argc = parse_options(argc, argv, options, u, 0);
+
+	if (param.verbose)
+		ndctl_set_log_priority(ctx, LOG_DEBUG);
+
+	if (argc == 0) {
+		argc = 1;
+		argv = &all;
+	} else
+		for (i = 0; i < argc; i++)
+			if (strcmp(argv[i], "all") == 0) {
+				argv[0] = "all";
+				argc = 1;
+				break;
+			}
+
+	jbuses = json_object_new_array();
+	if (!jbuses)
+		return -ENOMEM;
+	for (i = 0; i < argc; i++) {
+		int found = 0;
+
+		ndctl_bus_foreach(ctx, bus) {
+			if (!util_bus_filter(bus, argv[i]))
+				continue;
+			found++;
+			rc = scrub_action(bus, action);
+			if (rc == 0) {
+				success++;
+				jbus = util_bus_to_json(bus);
+				if (jbus)
+					json_object_array_add(jbuses, jbus);
+			} else if (!fail)
+				fail = rc;
+		}
+		if (!found && param.verbose)
+			fprintf(stderr, "no bus matches id: %s\n", argv[i]);
+	}
+
+	if (success)
+		util_display_json_array(stdout, jbuses,
+				JSON_C_TO_STRING_PRETTY);
+	else
+		json_object_put(jbuses);
+
+	if (success)
+		return success;
+	return fail ? fail : -ENXIO;
+}
+
+int cmd_start_scrub(int argc, const char **argv, void *ctx)
+{
+	char *usage = "ndctl start-scrub [<bus-id> <bus-id2> ... <bus-idN>] [<options>]";
+	int start = bus_action(argc, argv, usage, bus_options,
+			ACTION_START, ctx);
+
+	if (start <= 0) {
+		fprintf(stderr, "error starting scrub: %s\n",
+				strerror(-start));
+		return start;
+	} else {
+		return 0;
+	}
+}
+
+int cmd_wait_scrub(int argc, const char **argv, void *ctx)
+{
+	char *usage = "ndctl wait-scrub [<bus-id> <bus-id2> ... <bus-idN>] [<options>]";
+	int wait = bus_action(argc, argv, usage, bus_options,
+			ACTION_WAIT, ctx);
+
+	if (wait <= 0) {
+		fprintf(stderr, "error waiting for scrub completion: %s\n",
+				strerror(-wait));
+		return wait;
+	} else {
+		return 0;
+	}
+}
diff --git a/ndctl/ndctl.c b/ndctl/ndctl.c
index d3c6db1b6bf0..7daadebd52fc 100644
--- a/ndctl/ndctl.c
+++ b/ndctl/ndctl.c
@@ -86,6 +86,8 @@ static struct cmd_struct commands[] = {
 	{ "inject-error", cmd_inject_error },
 	{ "update-firmware", cmd_update_firmware },
 	{ "inject-smart", cmd_inject_smart },
+	{ "wait-scrub", cmd_wait_scrub },
+	{ "start-scrub", cmd_start_scrub },
 	{ "list", cmd_list },
 	{ "help", cmd_help },
 	#ifdef ENABLE_TEST

_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2018-04-04 21:22 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-04-04 21:11 [ndctl PATCH 0/5] Address Range Scrub (ARS) Utilities Dan Williams
2018-04-04 21:12 ` [ndctl PATCH 1/5] ndctl, scrub: fix ndctl_bus_wait_for_scrub_completion() Dan Williams
2018-04-04 21:12 ` [ndctl PATCH 2/5] ndctl, scrub: report the bus scrub state in 'ndctl list' Dan Williams
2018-04-04 21:12 ` [ndctl PATCH 3/5] ndctl, scrub: add ndctl_bus_start_scrub() Dan Williams
2018-04-04 21:12 ` [ndctl PATCH 4/5] ndctl: add new START and WAIT actions Dan Williams
2018-04-04 21:12 ` [ndctl PATCH 5/5] ndctl, scrub: add {wait, start}-scrub helper utilities 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).