From patchwork Tue Mar 20 21:50:27 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Jiang X-Patchwork-Id: 10298011 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 6A0A4602B3 for ; Tue, 20 Mar 2018 21:50:35 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5999629688 for ; Tue, 20 Mar 2018 21:50:35 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4E0F5296AA; Tue, 20 Mar 2018 21:50:35 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from ml01.01.org (ml01.01.org [198.145.21.10]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id A6FA829688 for ; Tue, 20 Mar 2018 21:50:33 +0000 (UTC) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 8457822571B57; Tue, 20 Mar 2018 14:44:03 -0700 (PDT) X-Original-To: linux-nvdimm@lists.01.org Delivered-To: linux-nvdimm@lists.01.org Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=192.55.52.93; helo=mga11.intel.com; envelope-from=dave.jiang@intel.com; receiver=linux-nvdimm@lists.01.org Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id E4615224BBC5A for ; Tue, 20 Mar 2018 14:44:01 -0700 (PDT) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 20 Mar 2018 14:50:28 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.48,337,1517904000"; d="scan'208";a="184558534" Received: from djiang5-desk3.ch.intel.com ([143.182.136.93]) by orsmga004.jf.intel.com with ESMTP; 20 Mar 2018 14:50:28 -0700 Subject: [PATCH v3] ndctl: Add support for get bus and region persistence domain From: Dave Jiang To: vishal.l.verma@intel.com, dan.j.williams@intel.com Date: Tue, 20 Mar 2018 14:50:27 -0700 Message-ID: <152158255868.52915.9362618183529367890.stgit@djiang5-desk3.ch.intel.com> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 X-BeenThere: linux-nvdimm@lists.01.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "Linux-nvdimm developer list." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-nvdimm@lists.01.org Errors-To: linux-nvdimm-bounces@lists.01.org Sender: "Linux-nvdimm" X-Virus-Scanned: ClamAV using ClamSMTP 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_region_get_numa_node; ndctl_dimm_fw_update_supported; + ndctl_region_get_persistence_domain; + ndctl_bus_get_persistence_domain; } LIBNDCTL_14; diff --git a/ndctl/libndctl.h b/ndctl/libndctl.h index f3a27411..84f441ef 100644 --- a/ndctl/libndctl.h +++ b/ndctl/libndctl.h @@ -115,6 +115,7 @@ int ndctl_bus_is_cmd_supported(struct ndctl_bus *bus, int cmd); unsigned int ndctl_bus_get_revision(struct ndctl_bus *bus); unsigned int ndctl_bus_get_id(struct ndctl_bus *bus); const char *ndctl_bus_get_provider(struct ndctl_bus *bus); +enum ndctl_persistence ndctl_bus_get_persistence_domain(struct ndctl_bus *bus); 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); @@ -305,6 +306,14 @@ struct badblock { unsigned long long offset; unsigned int len; }; + +enum ndctl_persistence { + PERSISTENCE_NONE = 0, + PERSISTENCE_MEM_CTRL, + PERSISTENCE_CPU_CACHE, + PERSISTENCE_UNKNOWN, +}; + struct ndctl_region; struct ndctl_region *ndctl_region_get_first(struct ndctl_bus *bus); struct ndctl_region *ndctl_region_get_next(struct ndctl_region *region); @@ -347,6 +356,8 @@ struct ndctl_region *ndctl_bus_get_region_by_physical_address(struct ndctl_bus * for (dimm = ndctl_region_get_first_dimm(region); \ dimm != NULL; \ dimm = ndctl_region_get_next_dimm(region, dimm)) +enum ndctl_persistence ndctl_region_get_persistence_domain( + struct ndctl_region *region); int ndctl_region_is_enabled(struct ndctl_region *region); int ndctl_region_enable(struct ndctl_region *region); int ndctl_region_disable_invalidate(struct ndctl_region *region); diff --git a/ndctl/list.c b/ndctl/list.c index fe8036ea..59efa31d 100644 --- a/ndctl/list.c +++ b/ndctl/list.c @@ -73,6 +73,7 @@ static struct json_object *region_to_json(struct ndctl_region *region, struct ndctl_interleave_set *iset; struct ndctl_mapping *mapping; unsigned int bb_count = 0; + enum ndctl_persistence pd; int numa; if (!jregion) @@ -174,6 +175,21 @@ static struct json_object *region_to_json(struct ndctl_region *region, if ((flags & UTIL_JSON_MEDIA_ERRORS) && jbbs) json_object_object_add(jregion, "badblocks", jbbs); + pd = ndctl_region_get_persistence_domain(region); + switch (pd) { + case PERSISTENCE_CPU_CACHE: + jobj = json_object_new_string("cpu_cache"); + break; + case PERSISTENCE_MEM_CTRL: + jobj = json_object_new_string("memory_controller"); + break; + default: + jobj = NULL; + } + + if (jobj) + json_object_object_add(jregion, "persistence_domain", jobj); + return jregion; err: fail("\n");