From c5ccbf29c54b5a3d9cb1c138c06c8d5ac3ee80c2 Mon Sep 17 00:00:00 2001 From: Vaibhav Jain Date: Tue, 22 Feb 2022 17:45:19 +0530 Subject: [PATCH 129/217] ndctl,libndctl: Update nvdimm flags after smart-inject Presently after performing an inject-smart command the nvdimm flags reported are out of date as shown below where no 'smart_notify' or 'flush_fail' flags were reported even though they are set after injecting the smart error: $ sudo ndctl inject-smart -fU nmem0 [ { "dev":"nmem0", "health":{ "health_state":"fatal", "shutdown_state":"dirty", "shutdown_count":0 } } ] $ sudo cat /sys/class/nd/ndctl0/device/nmem0/papr/flags flush_fail smart_notify This happens because nvdimm flags are only parsed once during its probe and not refreshed even after a inject-smart operation makes them out of date. To fix this the patch forces an update of nvdimm flags via newly introduced export from libndctl named ndctl_dimm_refresh_flags() thats called from dimm_inject_smart() after inject-smart command is successfully submitted. This ensures that correct nvdimm flags are displayed later in that function. With this implemented correct nvdimm flags are reported after a inject-smart operation: $ sudo ndctl inject-smart -fU nmem0 [ { "dev":"nmem0", "flag_failed_flush":true, "flag_smart_event":true, "health":{ "health_state":"fatal", "shutdown_state":"dirty", "shutdown_count":0 } } ] The patch refactors populate_dimm_attributes() to move the nvdimm flags parsing code to the newly introduced ndctl_dimm_refresh_flags() export. Since reading nvdimm flags requires constructing path using 'bus_prefix' which is only available during add_dimm(), the patch introduces a new member 'struct ndctl_dimm.bus_prefix' to cache its value. During ndctl_dimm_refresh_flags() the cached bus_prefix is used to read the contents of the nvdimm flag file and pass it on to the appropriate flag parsing function. Finally dimm_inject_smart() is updated to issue call to ndctl_dimm_refresh_flags() before generating json output of the nvdimm status Link: https://lore.kernel.org/r/20220222121519.1674117-1-vaibhav@linux.ibm.com Signed-off-by: Vaibhav Jain Signed-off-by: Shivaprasad G Bhat Signed-off-by: Vishal Verma --- ndctl/inject-smart.c | 4 +++ ndctl/lib/libndctl.c | 55 +++++++++++++++++++++++++++++++----------- ndctl/lib/libndctl.sym | 4 +++ ndctl/lib/private.h | 1 + ndctl/libndctl.h | 1 + 5 files changed, 51 insertions(+), 14 deletions(-) diff -up ndctl-71.1/ndctl/inject-smart.c.orig ndctl-71.1/ndctl/inject-smart.c --- ndctl-71.1/ndctl/inject-smart.c.orig 2022-10-07 16:40:24.610615979 -0400 +++ ndctl-71.1/ndctl/inject-smart.c 2022-10-07 16:40:35.031651459 -0400 @@ -467,6 +467,10 @@ static int dimm_inject_smart(struct ndct jdimms = json_object_new_array(); if (!jdimms) goto out; + + /* Ensure the dimm flags are upto date before reporting them */ + ndctl_dimm_refresh_flags(dimm); + jdimm = util_dimm_to_json(dimm, sctx.flags); if (!jdimm) goto out; diff -up ndctl-71.1/ndctl/lib/libndctl.c.orig ndctl-71.1/ndctl/lib/libndctl.c --- ndctl-71.1/ndctl/lib/libndctl.c.orig 2022-10-07 16:40:24.608615972 -0400 +++ ndctl-71.1/ndctl/lib/libndctl.c 2022-10-07 16:40:35.032651462 -0400 @@ -588,6 +588,7 @@ static void free_dimm(struct ndctl_dimm free(dimm->unique_id); free(dimm->dimm_buf); free(dimm->dimm_path); + free(dimm->bus_prefix); if (dimm->module) kmod_module_unref(dimm->module); if (dimm->health_eventfd > -1) @@ -1645,14 +1646,34 @@ static enum ndctl_fwa_result fwa_result_ return NDCTL_FWA_RESULT_INVALID; } +NDCTL_EXPORT void ndctl_dimm_refresh_flags(struct ndctl_dimm *dimm) +{ + struct ndctl_ctx *ctx = dimm->bus->ctx; + char *path = dimm->dimm_buf; + char buf[SYSFS_ATTR_SIZE]; + + /* Construct path to dimm flags sysfs file */ + sprintf(path, "%s/%s/flags", dimm->dimm_path, dimm->bus_prefix); + + if (sysfs_read_attr(ctx, path, buf) < 0) + return; + + /* Reset the flags */ + dimm->flags.flags = 0; + if (ndctl_bus_has_nfit(dimm->bus)) + parse_nfit_mem_flags(dimm, buf); + else if (ndctl_bus_is_papr_scm(dimm->bus)) + parse_papr_flags(dimm, buf); +} + static int populate_dimm_attributes(struct ndctl_dimm *dimm, - const char *dimm_base, - const char *bus_prefix) + const char *dimm_base) { int i, rc = -1; char buf[SYSFS_ATTR_SIZE]; struct ndctl_ctx *ctx = dimm->bus->ctx; char *path = calloc(1, strlen(dimm_base) + 100); + const char *bus_prefix = dimm->bus_prefix; if (!path) return -ENOMEM; @@ -1736,16 +1757,10 @@ static int populate_dimm_attributes(stru } sprintf(path, "%s/%s/flags", dimm_base, bus_prefix); - if (sysfs_read_attr(ctx, path, buf) == 0) { - if (ndctl_bus_has_nfit(dimm->bus)) - parse_nfit_mem_flags(dimm, buf); - else if (ndctl_bus_is_papr_scm(dimm->bus)) { - dimm->cmd_family = NVDIMM_FAMILY_PAPR; - parse_papr_flags(dimm, buf); - } - } - dimm->health_eventfd = open(path, O_RDONLY|O_CLOEXEC); + + ndctl_dimm_refresh_flags(dimm); + rc = 0; err_read: @@ -1801,8 +1816,9 @@ static int add_papr_dimm(struct ndctl_di rc = 0; } else if (strcmp(buf, "nvdimm_test") == 0) { + dimm->cmd_family = NVDIMM_FAMILY_PAPR; /* probe via common populate_dimm_attributes() */ - rc = populate_dimm_attributes(dimm, dimm_base, "papr"); + rc = populate_dimm_attributes(dimm, dimm_base); } out: free(path); @@ -1899,9 +1915,20 @@ static void *add_dimm(void *parent, int dimm->formats = formats; /* Check if the given dimm supports nfit */ if (ndctl_bus_has_nfit(bus)) { - rc = populate_dimm_attributes(dimm, dimm_base, "nfit"); + dimm->bus_prefix = strdup("nfit"); + if (!dimm->bus_prefix) { + rc = -ENOMEM; + goto out; + } + rc = populate_dimm_attributes(dimm, dimm_base); + } else if (ndctl_bus_has_of_node(bus)) { - rc = add_papr_dimm(dimm, dimm_base); + dimm->bus_prefix = strdup("papr"); + if (!dimm->bus_prefix) { + rc = -ENOMEM; + goto out; + } + rc = add_papr_dimm(dimm, dimm_base); } if (rc == -ENODEV) { diff -up ndctl-71.1/ndctl/lib/libndctl.sym.orig ndctl-71.1/ndctl/lib/libndctl.sym --- ndctl-71.1/ndctl/lib/libndctl.sym.orig 2022-10-07 16:40:24.344615073 -0400 +++ ndctl-71.1/ndctl/lib/libndctl.sym 2022-10-07 16:40:35.032651462 -0400 @@ -456,3 +456,7 @@ LIBNDCTL_26 { ndctl_bus_nfit_translate_spa; ndctl_dimm_sizeof_namespace_index; } LIBNDCTL_25; + +LIBNDCTL_27 { + ndctl_dimm_refresh_flags; +} LIBNDCTL_26; diff -up ndctl-71.1/ndctl/lib/private.h.orig ndctl-71.1/ndctl/lib/private.h --- ndctl-71.1/ndctl/lib/private.h.orig 2022-10-07 16:40:24.455615451 -0400 +++ ndctl-71.1/ndctl/lib/private.h 2022-10-07 16:40:35.032651462 -0400 @@ -75,6 +75,7 @@ struct ndctl_dimm { char *unique_id; char *dimm_path; char *dimm_buf; + char *bus_prefix; int health_eventfd; int buf_len; int id; diff -up ndctl-71.1/ndctl/libndctl.h.orig ndctl-71.1/ndctl/libndctl.h --- ndctl-71.1/ndctl/libndctl.h.orig 2022-10-07 16:40:24.611615982 -0400 +++ ndctl-71.1/ndctl/libndctl.h 2022-10-07 16:40:35.033651466 -0400 @@ -221,6 +221,7 @@ int ndctl_dimm_is_active(struct ndctl_di int ndctl_dimm_is_enabled(struct ndctl_dimm *dimm); int ndctl_dimm_disable(struct ndctl_dimm *dimm); int ndctl_dimm_enable(struct ndctl_dimm *dimm); +void ndctl_dimm_refresh_flags(struct ndctl_dimm *dimm); struct ndctl_cmd; struct ndctl_cmd *ndctl_bus_cmd_new_ars_cap(struct ndctl_bus *bus,