Message ID | 157480898913.2804089.3499900417147974083.stgit@dwillia2-desk3.amr.corp.intel.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | [ndctl] ndctl/list: Add 'target_node' to region and namespace verbose listings | expand |
On Tue, Nov 26, 2019 at 3:10 PM Dan Williams <dan.j.williams@intel.com> wrote: > > Historically the 'numa_node' attribute of a device has been the local, > or closest cpu numa node that can access the device. With the ACPI HMAT > and other platform descriptions of performance differentiated memory, > memory device targets may have their own numa identifier. The > target_node property indicates that target information and the effective > online numa node the memory range would receive if it were onlined. > > While this property has been available to device-dax instances since > kernel commit 21c75763a3ae "device-dax: Add a 'target_node' attribute", > recent kernels have also started exporting for regions and namespaces. > Add it to the verbose listing. > > Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.ibm.com> > Signed-off-by: Dan Williams <dan.j.williams@intel.com> > --- > ndctl/lib/libndctl.c | 25 ++++++++++++++++++++++++- > ndctl/lib/libndctl.sym | 2 ++ > ndctl/lib/private.h | 3 ++- > ndctl/libndctl.h | 2 ++ > ndctl/list.c | 9 ++++++++- > util/json.c | 9 ++++++++- > 6 files changed, 46 insertions(+), 4 deletions(-) > > diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c > index d6a28002e7d6..469815a8f04b 100644 > --- a/ndctl/lib/libndctl.c > +++ b/ndctl/lib/libndctl.c > @@ -135,6 +135,7 @@ struct ndctl_mapping { > * @generation: incremented everytime the region is disabled > * @nstype: the resulting type of namespace this region produces > * @numa_node: numa node attribute > + * @target_node: target node were this region to be onlined > * > * A region may alias between pmem and block-window access methods. The > * region driver is tasked with parsing the label (if their is one) and > @@ -160,7 +161,7 @@ struct ndctl_region { > char *region_buf; > int buf_len; > int generation; > - int numa_node; > + int numa_node, target_node; > struct list_head btts; > struct list_head pfns; > struct list_head daxs; > @@ -2151,6 +2152,12 @@ static void *add_region(void *parent, int id, const char *region_base) > else > region->numa_node = -1; > > + sprintf(path, "%s/target_node", region_base); > + if (sysfs_read_attr(ctx, path, buf) == 0) > + region->target_node = strtol(buf, NULL, 0); > + else > + region->target_node = -1; > + > if (region_set_type(region, path) < 0) > goto err_read; > > @@ -2424,6 +2431,11 @@ NDCTL_EXPORT int ndctl_region_get_numa_node(struct ndctl_region *region) > return region->numa_node; > } > > +NDCTL_EXPORT int ndctl_region_get_target_node(struct ndctl_region *region) > +{ > + return region->target_node; > +} > + > NDCTL_EXPORT struct badblock *ndctl_region_get_next_badblock(struct ndctl_region *region) > { > return badblocks_iter_next(®ion->bb_iter); > @@ -3477,6 +3489,12 @@ static void *add_namespace(void *parent, int id, const char *ndns_base) > else > ndns->numa_node = -1; > > + sprintf(path, "%s/target_node", ndns_base); > + if (sysfs_read_attr(ctx, path, buf) == 0) > + ndns->target_node = strtol(buf, NULL, 0); > + else > + ndns->target_node = -1; > + > sprintf(path, "%s/holder_class", ndns_base); > if (sysfs_read_attr(ctx, path, buf) == 0) > ndns->enforce_mode = enforce_name_to_id(buf); > @@ -4393,6 +4411,11 @@ NDCTL_EXPORT int ndctl_namespace_get_numa_node(struct ndctl_namespace *ndns) > return ndns->numa_node; > } > > +NDCTL_EXPORT int ndctl_namespace_get_target_node(struct ndctl_namespace *ndns) > +{ > + return ndns->target_node; > +} > + > static int __ndctl_namespace_set_write_cache(struct ndctl_namespace *ndns, > int state) > { > diff --git a/ndctl/lib/libndctl.sym b/ndctl/lib/libndctl.sym > index 4e767789dfe1..bf049af1393a 100644 > --- a/ndctl/lib/libndctl.sym > +++ b/ndctl/lib/libndctl.sym > @@ -426,4 +426,6 @@ LIBNDCTL_22 { > > LIBNDCTL_23 { > ndctl_namespace_is_configuration_idle; > + ndctl_namespace_get_target_node; > + ndctl_region_get_target_node; > } LIBNDCTL_22; > diff --git a/ndctl/lib/private.h b/ndctl/lib/private.h > index 1f6a01c55377..e4453013d706 100644 > --- a/ndctl/lib/private.h > +++ b/ndctl/lib/private.h > @@ -201,6 +201,7 @@ struct badblocks_iter { > * @bdev: associated block_device of a namespace > * @size: unsigned > * @numa_node: numa node attribute > + * @target_node: target node were this region to be onlined > * > * A 'namespace' is the resulting device after region-aliasing and > * label-parsing is resolved. > @@ -220,7 +221,7 @@ struct ndctl_namespace { > char *alt_name; > uuid_t uuid; > struct ndctl_lbasize lbasize; > - int numa_node; > + int numa_node, target_node; > struct list_head injected_bb; > }; > > diff --git a/ndctl/libndctl.h b/ndctl/libndctl.h > index 9a53049e7f61..208240b20aee 100644 > --- a/ndctl/libndctl.h > +++ b/ndctl/libndctl.h > @@ -383,6 +383,7 @@ struct ndctl_dimm *ndctl_region_get_first_dimm(struct ndctl_region *region); > struct ndctl_dimm *ndctl_region_get_next_dimm(struct ndctl_region *region, > struct ndctl_dimm *dimm); > int ndctl_region_get_numa_node(struct ndctl_region *region); > +int ndctl_region_get_target_node(struct ndctl_region *region); > struct ndctl_region *ndctl_bus_get_region_by_physical_address(struct ndctl_bus *bus, > unsigned long long address); > #define ndctl_dimm_foreach_in_region(region, dimm) \ > @@ -511,6 +512,7 @@ int ndctl_namespace_set_sector_size(struct ndctl_namespace *ndns, > int ndctl_namespace_get_raw_mode(struct ndctl_namespace *ndns); > int ndctl_namespace_set_raw_mode(struct ndctl_namespace *ndns, int raw_mode); > int ndctl_namespace_get_numa_node(struct ndctl_namespace *ndns); > +int ndctl_namespace_get_target_node(struct ndctl_namespace *ndns); > int ndctl_namespace_inject_error(struct ndctl_namespace *ndns, > unsigned long long block, unsigned long long count, > bool notify); > diff --git a/ndctl/list.c b/ndctl/list.c > index 1c3e34d58ddb..607996a85784 100644 > --- a/ndctl/list.c > +++ b/ndctl/list.c > @@ -80,7 +80,7 @@ static struct json_object *region_to_json(struct ndctl_region *region, > unsigned int bb_count = 0; > unsigned long long extent; > enum ndctl_persistence_domain pd; > - int numa; > + int numa, target; > > if (!jregion) > return NULL; > @@ -130,6 +130,13 @@ static struct json_object *region_to_json(struct ndctl_region *region, > json_object_object_add(jregion, "numa_node", jobj); > } > > + target = ndctl_region_get_target_node(region); > + if (target >= 0 && flags & UTIL_JSON_VERBOSE) { > + jobj = json_object_new_int(target); > + if (jobj) > + json_object_object_add(jregion, "target_node", jobj); > + } > + > iset = ndctl_region_get_interleave_set(region); > if (iset) { > jobj = util_json_object_hex( > diff --git a/util/json.c b/util/json.c > index 497c52ba1a00..1369a068398c 100644 > --- a/util/json.c > +++ b/util/json.c > @@ -912,7 +912,7 @@ struct json_object *util_namespace_to_json(struct ndctl_namespace *ndns, > unsigned long align = 0; > char buf[40]; > uuid_t uuid; > - int numa; > + int numa, target; > > if (!jndns) > return NULL; > @@ -1092,6 +1092,13 @@ struct json_object *util_namespace_to_json(struct ndctl_namespace *ndns, > json_object_object_add(jndns, "numa_node", jobj); > } > > + target= ndctl_namespace_get_target_node(ndns); > + if (target>= 0 && flags & UTIL_JSON_VERBOSE) { Ugh, not sure how the whitespace after 'target' got dropped. v2 inbound.
diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c index d6a28002e7d6..469815a8f04b 100644 --- a/ndctl/lib/libndctl.c +++ b/ndctl/lib/libndctl.c @@ -135,6 +135,7 @@ struct ndctl_mapping { * @generation: incremented everytime the region is disabled * @nstype: the resulting type of namespace this region produces * @numa_node: numa node attribute + * @target_node: target node were this region to be onlined * * A region may alias between pmem and block-window access methods. The * region driver is tasked with parsing the label (if their is one) and @@ -160,7 +161,7 @@ struct ndctl_region { char *region_buf; int buf_len; int generation; - int numa_node; + int numa_node, target_node; struct list_head btts; struct list_head pfns; struct list_head daxs; @@ -2151,6 +2152,12 @@ static void *add_region(void *parent, int id, const char *region_base) else region->numa_node = -1; + sprintf(path, "%s/target_node", region_base); + if (sysfs_read_attr(ctx, path, buf) == 0) + region->target_node = strtol(buf, NULL, 0); + else + region->target_node = -1; + if (region_set_type(region, path) < 0) goto err_read; @@ -2424,6 +2431,11 @@ NDCTL_EXPORT int ndctl_region_get_numa_node(struct ndctl_region *region) return region->numa_node; } +NDCTL_EXPORT int ndctl_region_get_target_node(struct ndctl_region *region) +{ + return region->target_node; +} + NDCTL_EXPORT struct badblock *ndctl_region_get_next_badblock(struct ndctl_region *region) { return badblocks_iter_next(®ion->bb_iter); @@ -3477,6 +3489,12 @@ static void *add_namespace(void *parent, int id, const char *ndns_base) else ndns->numa_node = -1; + sprintf(path, "%s/target_node", ndns_base); + if (sysfs_read_attr(ctx, path, buf) == 0) + ndns->target_node = strtol(buf, NULL, 0); + else + ndns->target_node = -1; + sprintf(path, "%s/holder_class", ndns_base); if (sysfs_read_attr(ctx, path, buf) == 0) ndns->enforce_mode = enforce_name_to_id(buf); @@ -4393,6 +4411,11 @@ NDCTL_EXPORT int ndctl_namespace_get_numa_node(struct ndctl_namespace *ndns) return ndns->numa_node; } +NDCTL_EXPORT int ndctl_namespace_get_target_node(struct ndctl_namespace *ndns) +{ + return ndns->target_node; +} + static int __ndctl_namespace_set_write_cache(struct ndctl_namespace *ndns, int state) { diff --git a/ndctl/lib/libndctl.sym b/ndctl/lib/libndctl.sym index 4e767789dfe1..bf049af1393a 100644 --- a/ndctl/lib/libndctl.sym +++ b/ndctl/lib/libndctl.sym @@ -426,4 +426,6 @@ LIBNDCTL_22 { LIBNDCTL_23 { ndctl_namespace_is_configuration_idle; + ndctl_namespace_get_target_node; + ndctl_region_get_target_node; } LIBNDCTL_22; diff --git a/ndctl/lib/private.h b/ndctl/lib/private.h index 1f6a01c55377..e4453013d706 100644 --- a/ndctl/lib/private.h +++ b/ndctl/lib/private.h @@ -201,6 +201,7 @@ struct badblocks_iter { * @bdev: associated block_device of a namespace * @size: unsigned * @numa_node: numa node attribute + * @target_node: target node were this region to be onlined * * A 'namespace' is the resulting device after region-aliasing and * label-parsing is resolved. @@ -220,7 +221,7 @@ struct ndctl_namespace { char *alt_name; uuid_t uuid; struct ndctl_lbasize lbasize; - int numa_node; + int numa_node, target_node; struct list_head injected_bb; }; diff --git a/ndctl/libndctl.h b/ndctl/libndctl.h index 9a53049e7f61..208240b20aee 100644 --- a/ndctl/libndctl.h +++ b/ndctl/libndctl.h @@ -383,6 +383,7 @@ struct ndctl_dimm *ndctl_region_get_first_dimm(struct ndctl_region *region); struct ndctl_dimm *ndctl_region_get_next_dimm(struct ndctl_region *region, struct ndctl_dimm *dimm); int ndctl_region_get_numa_node(struct ndctl_region *region); +int ndctl_region_get_target_node(struct ndctl_region *region); struct ndctl_region *ndctl_bus_get_region_by_physical_address(struct ndctl_bus *bus, unsigned long long address); #define ndctl_dimm_foreach_in_region(region, dimm) \ @@ -511,6 +512,7 @@ int ndctl_namespace_set_sector_size(struct ndctl_namespace *ndns, int ndctl_namespace_get_raw_mode(struct ndctl_namespace *ndns); int ndctl_namespace_set_raw_mode(struct ndctl_namespace *ndns, int raw_mode); int ndctl_namespace_get_numa_node(struct ndctl_namespace *ndns); +int ndctl_namespace_get_target_node(struct ndctl_namespace *ndns); int ndctl_namespace_inject_error(struct ndctl_namespace *ndns, unsigned long long block, unsigned long long count, bool notify); diff --git a/ndctl/list.c b/ndctl/list.c index 1c3e34d58ddb..607996a85784 100644 --- a/ndctl/list.c +++ b/ndctl/list.c @@ -80,7 +80,7 @@ static struct json_object *region_to_json(struct ndctl_region *region, unsigned int bb_count = 0; unsigned long long extent; enum ndctl_persistence_domain pd; - int numa; + int numa, target; if (!jregion) return NULL; @@ -130,6 +130,13 @@ static struct json_object *region_to_json(struct ndctl_region *region, json_object_object_add(jregion, "numa_node", jobj); } + target = ndctl_region_get_target_node(region); + if (target >= 0 && flags & UTIL_JSON_VERBOSE) { + jobj = json_object_new_int(target); + if (jobj) + json_object_object_add(jregion, "target_node", jobj); + } + iset = ndctl_region_get_interleave_set(region); if (iset) { jobj = util_json_object_hex( diff --git a/util/json.c b/util/json.c index 497c52ba1a00..1369a068398c 100644 --- a/util/json.c +++ b/util/json.c @@ -912,7 +912,7 @@ struct json_object *util_namespace_to_json(struct ndctl_namespace *ndns, unsigned long align = 0; char buf[40]; uuid_t uuid; - int numa; + int numa, target; if (!jndns) return NULL; @@ -1092,6 +1092,13 @@ struct json_object *util_namespace_to_json(struct ndctl_namespace *ndns, json_object_object_add(jndns, "numa_node", jobj); } + target= ndctl_namespace_get_target_node(ndns); + if (target>= 0 && flags & UTIL_JSON_VERBOSE) { + jobj = json_object_new_int(target); + if (jobj) + json_object_object_add(jndns, "target_node", jobj); + } + if (pfn) jbbs = util_pfn_badblocks_to_json(pfn, &bb_count, flags); else if (dax)
Historically the 'numa_node' attribute of a device has been the local, or closest cpu numa node that can access the device. With the ACPI HMAT and other platform descriptions of performance differentiated memory, memory device targets may have their own numa identifier. The target_node property indicates that target information and the effective online numa node the memory range would receive if it were onlined. While this property has been available to device-dax instances since kernel commit 21c75763a3ae "device-dax: Add a 'target_node' attribute", recent kernels have also started exporting for regions and namespaces. Add it to the verbose listing. Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.ibm.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com> --- ndctl/lib/libndctl.c | 25 ++++++++++++++++++++++++- ndctl/lib/libndctl.sym | 2 ++ ndctl/lib/private.h | 3 ++- ndctl/libndctl.h | 2 ++ ndctl/list.c | 9 ++++++++- util/json.c | 9 ++++++++- 6 files changed, 46 insertions(+), 4 deletions(-)