diff mbox series

[ndctl,v3,2/5] libndctl: Implement the smart_get_shutdown_count dimm-op for Hyper-V

Message ID 20190323042028.4310-3-decui@microsoft.com (mailing list archive)
State Accepted
Commit 28651d2885e2057478f4682db72fced93def1f2b
Headers show
Series Add the support for Hyper-V virtual NVDIMM | expand

Commit Message

Dexuan Cui March 23, 2019, 4:20 a.m. UTC
The "smart_get_shutdown_count" dimm-op is expected to return a shutdown
count, but for the Hyper-V family this is only available from a separate
DSM. Perform a command submission in the "hyperv_cmd_get_shutdown_count"
dimm-op and the "hyperv_cmd_get_flags" dimm-op to retrieve this info, so
that a smart health listing can display this info.

Now "ndctl list --dimms --health" can show a line of "shutdown_count"
for Hyper-V NVDIMM, e.g.

{
    "dev":"nmem0",
    "id":"04d5-01-1701-00000000",
    "handle":0,
    "phys_id":0,
    "health":{
      "health_state":"ok",
      "shutdown_count":2
    }
}

Signed-off-by: Dexuan Cui <decui@microsoft.com>
---
 ndctl/lib/hyperv.c | 43 +++++++++++++++++++++++++++++++++++++++++++
 ndctl/lib/hyperv.h |  8 ++++++++
 2 files changed, 51 insertions(+)
diff mbox series

Patch

diff --git a/ndctl/lib/hyperv.c b/ndctl/lib/hyperv.c
index 6ed2125..efd8b03 100644
--- a/ndctl/lib/hyperv.c
+++ b/ndctl/lib/hyperv.c
@@ -72,9 +72,33 @@  static int hyperv_valid_health_info(struct ndctl_cmd *cmd)
 	return hyperv_cmd_valid(cmd, ND_HYPERV_CMD_GET_HEALTH_INFO);
 }
 
+static int hyperv_get_shutdown_count(struct ndctl_cmd *cmd, unsigned int *count)
+{
+	unsigned int command = ND_HYPERV_CMD_GET_SHUTDOWN_INFO;
+	struct ndctl_cmd *cmd_get_shutdown_info;
+	int rc;
+
+	cmd_get_shutdown_info = alloc_hyperv_cmd(cmd->dimm, command);
+	if (!cmd_get_shutdown_info)
+		return -EINVAL;
+
+	if (ndctl_cmd_submit_xlat(cmd_get_shutdown_info) < 0 ||
+	    hyperv_cmd_valid(cmd_get_shutdown_info, command) < 0) {
+		rc = -EINVAL;
+		goto out;
+	}
+
+	*count = cmd_get_shutdown_info->hyperv->u.shutdown_info.count;
+	rc = 0;
+out:
+	ndctl_cmd_unref(cmd_get_shutdown_info);
+	return rc;
+}
+
 static unsigned int hyperv_cmd_get_flags(struct ndctl_cmd *cmd)
 {
 	unsigned int flags = 0;
+	unsigned int count;
 	int rc;
 
 	rc = hyperv_valid_health_info(cmd);
@@ -84,6 +108,9 @@  static unsigned int hyperv_cmd_get_flags(struct ndctl_cmd *cmd)
 	}
 	flags |= ND_SMART_HEALTH_VALID;
 
+	if (hyperv_get_shutdown_count(cmd, &count) == 0)
+		flags |= ND_SMART_SHUTDOWN_COUNT_VALID;
+
 	return flags;
 }
 
@@ -113,6 +140,21 @@  static unsigned int hyperv_cmd_get_health(struct ndctl_cmd *cmd)
 	return health;
 }
 
+static unsigned int hyperv_cmd_get_shutdown_count(struct ndctl_cmd *cmd)
+{
+	unsigned int count;
+	int rc;;
+
+	rc = hyperv_get_shutdown_count(cmd, &count);
+
+	if (rc < 0) {
+		errno = -rc;
+		return UINT_MAX;
+	}
+
+	return count;
+}
+
 static int hyperv_cmd_xlat_firmware_status(struct ndctl_cmd *cmd)
 {
 	return cmd->hyperv->u.status == 0 ? 0 : -EINVAL;
@@ -122,5 +164,6 @@  struct ndctl_dimm_ops * const hyperv_dimm_ops = &(struct ndctl_dimm_ops) {
 	.new_smart = hyperv_dimm_cmd_new_smart,
 	.smart_get_flags = hyperv_cmd_get_flags,
 	.smart_get_health = hyperv_cmd_get_health,
+	.smart_get_shutdown_count = hyperv_cmd_get_shutdown_count,
 	.xlat_firmware_status = hyperv_cmd_xlat_firmware_status,
 };
diff --git a/ndctl/lib/hyperv.h b/ndctl/lib/hyperv.h
index 45bbc12..0c1677f 100644
--- a/ndctl/lib/hyperv.h
+++ b/ndctl/lib/hyperv.h
@@ -9,6 +9,7 @@ 
 enum {
 	ND_HYPERV_CMD_QUERY_SUPPORTED_FUNCTIONS	= 0,
 	ND_HYPERV_CMD_GET_HEALTH_INFO		= 1,
+	ND_HYPERV_CMD_GET_SHUTDOWN_INFO		= 2,
 };
 
 /* Get Health Information (Function Index 1) */
@@ -17,9 +18,16 @@  struct nd_hyperv_health_info {
 	__u32	health;
 } __attribute__((packed));
 
+/* Get Unsafe Shutdown Count (Function Index 2) */
+struct nd_hyperv_shutdown_info {
+	 __u32   status;
+	 __u32   count;
+} __attribute__((packed));
+
 union nd_hyperv_cmd {
 	__u32				status;
 	struct nd_hyperv_health_info	health_info;
+	struct nd_hyperv_shutdown_info	shutdown_info;
 } __attribute__((packed));
 
 struct nd_pkg_hyperv {