Adding helper functions to iterate through sysfs region persistence domain
attribute. The region will display the domain with the most persistence for the
region. The bus will display the domain attribute with the least persistence
amongst all the regions. ndctl_bus_get_persistence_domain() and
ndctl_region_get_persistence_domain are exported. ndctl list will also display
the region persistence domain as well.
Signed-off-by: Dave Jiang
---
v3:
- fixed up return types per Ross's comments
- removed persistence_domain for bus and calculate on the fly per Dan's comment
v2:
- Simplied scanning of persistence domain from Ross's comments.
ndctl/lib/libndctl.c | 85
ndctl/lib/libndctl.sym |2 +
ndctl/libndctl.h | 11 ++
ndctl/list.c | 16 +
4 files changed, 114 insertions(+)
diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
index a165e697..bd2afa01 100644
--- a/ndctl/lib/libndctl.c
+++ b/ndctl/lib/libndctl.c
@@ -180,6 +180,7 @@ struct ndctl_region {
} iset;
FILE *badblocks;
struct badblock bb;
+ enum ndctl_persistence persistence_domain;
};
/**
@@ -916,6 +917,22 @@ NDCTL_EXPORT struct ndctl_bus
*ndctl_bus_get_by_provider(struct ndctl_ctx *ctx,
return NULL;
}
+NDCTL_EXPORT enum ndctl_persistence
+ndctl_bus_get_persistence_domain(struct ndctl_bus *bus)
+{
+ struct ndctl_region *region;
+ enum ndctl_persistence pd = PERSISTENCE_UNKNOWN;
+
+ /* iterate through region to get the region persistence domain */
+ ndctl_region_foreach(bus, region) {
+ /* we are looking for the least persistence domain */
+ if (pd > region->persistence_domain)
+ pd = region->persistence_domain;
+ }
+
+ return pd;
+}
+
NDCTL_EXPORT struct ndctl_btt *ndctl_region_get_btt_seed(struct ndctl_region
*region)
{
struct ndctl_ctx *ctx = ndctl_region_get_ctx(region);
@@ -1755,6 +1772,62 @@ static int region_set_type(struct ndctl_region *region,
char *path)
return 0;
}
+static enum ndctl_persistence region_get_pd_type(char *name)
+{
+ if (strncmp("cpu_cache", name, 9) == 0)
+ return PERSISTENCE_CPU_CACHE;
+ else if (strncmp("memory_controller", name, 17) == 0)
+ return PERSISTENCE_MEM_CTRL;
+ else
+ return PERSISTENCE_UNKNOWN;
+}
+
+static int region_persistence_scan(struct ndctl_region *region)
+{
+ struct ndctl_ctx *ctx = ndctl_region_get_ctx(region);
+ char *pd_path;
+ FILE *pf;
+ char buf[64];
+ int rc = 0;
+ enum ndctl_persistence pd = PERSISTENCE_NONE;
+
+ region->persistence_domain = PERSISTENCE_NONE;
+ if (asprintf(&pd_path, "%s/persistence_domain",
+ region->region_path) < 0) {
+ rc = -errno;
+ err(ctx, "region persist domain path allocation failure\n");
+ return rc;
+ }
+
+ pf = fopen(pd_path, "re");
+ if (!pf) {
+ rc = -errno;
+ free(pd_path);
+ return rc;
+ }
+
+ do {
+ rc = fscanf(pf, "%s", buf);
+ if (rc == EOF) {
+ if (ferror(pf)) {
+ rc = -errno;
+ goto out;
+ }
+ } else if (rc == 1)
+ pd = region_get_pd_type(buf);
+
+ if (region->persistence_domain < pd)
+ region->persistence_domain = pd;
+ } while (rc != EOF);
+
+ rc = 0;
+
+out:
+ fclose(pf);
+ free(pd_path);
+ return rc;
+}
+
static void *add_region(void *parent, int id, const char *region_base)
{
char buf[SYSFS_ATTR_SIZE];
@@ -1831,6 +1904,12 @@ static void *add_region(void *parent, int id, const char
*region_base)
list_add(&bus->regions, ®ion->list);
free(path);
+
+ /* get the persistence domain attribs */
+ if (region_persistence_scan(region) < 0)
+ err(ctx, "%s: region persistence scan failed\n",
+ ndctl_region_get_devname(region));
+
return region;
err_read:
@@ -2093,6 +2172,12 @@ NDCTL_EXPORT struct badblock
*ndctl_region_get_first_badblock(struct ndctl_regio
return ndctl_region_get_next_badblock(region);
}
+NDCTL_EXPORT enum ndctl_persistence
+ndctl_region_get_persistence_domain(struct ndctl_region *region)
+{
+ return region->persistence_domain;
+}
+
static struct nd_cmd_vendor_tail *to_vendor_tail(struct ndctl_cmd *cmd)
{
struct nd_cmd_vendor_tail *tail = (struct nd_cmd_vendor_tail *)
diff --git a/ndctl/lib/libndctl.sym b/ndctl/lib/libndctl.sym
index 21276614..3209aefe 100644
--- a/ndctl/lib/libndctl.sym
+++ b/ndctl/lib/libndctl.sym
@@ -350,4 +350,6 @@ global:
ndctl_dimm_cmd_new_ack_shutdown_count;
ndctl_