转发:/ linux-nvdimm
by 蔡瑾芸
linux-nvdimm//讨论主题
为什么现在的合伙人制度这么红火,因为资本的光环正在褪去,现在是人本为王的新时代!
在过去,是创始人单干制;在现在,提倡合伙人兵团作战。
在过去,利益是上下级分配制;在现在,提倡合伙人之间利益分享。
在过去,职业经理人用脚投票;在现在,提倡合伙人之间背靠背共进退。
详----细 大----纲 请 ----阅 读 ----附---- 件
2 years, 11 months
[RFC PATCH] ndctl, list: add ndctl_filter_opts for sharing filter
by QI Fuli
I wrote a patch for refactoring cmd_list(). It would be appreciated
if you could check it.
This patch refactors the filter in cmd_list() into ndctl_filter_opts
object with callback functions. So that the filter used for matching
a given object can be shared between "list" and "monitor".
Signed-off-by: QI Fuli <qi.fuli(a)jp.fujitsu.com>
---
ndctl/list.c | 142 +++++++++++++++++++++++++++++++++++++++--------------------
ndctl/list.h | 35 +++++++++++++++
2 files changed, 129 insertions(+), 48 deletions(-)
create mode 100644 ndctl/list.h
diff --git a/ndctl/list.c b/ndctl/list.c
index 37a224a..c1a095d 100644
--- a/ndctl/list.c
+++ b/ndctl/list.c
@@ -22,7 +22,7 @@
#include <ndctl/libndctl.h>
#include <util/parse-options.h>
#include <ccan/array_size/array_size.h>
-
+#include "list.h"
#include <ndctl.h>
static struct {
@@ -52,7 +52,7 @@ static unsigned long listopts_to_flags(void)
return flags;
}
-static struct {
+static struct parameter {
const char *bus;
const char *region;
const char *type;
@@ -61,6 +61,13 @@ static struct {
const char *namespace;
} param;
+struct ndctl_filter_opts *ndfop = &(struct ndctl_filter_opts) {
+ .match_bus = util_match_bus,
+ .match_dimm = util_match_dimm,
+ .match_region = util_match_region,
+ .match_namespace = util_match_namespace,
+};
+
static int did_fail;
static int jflag = JSON_C_TO_STRING_PRETTY;
@@ -108,15 +115,17 @@ static struct json_object *list_namespaces(struct ndctl_region *region,
if (!list.namespaces)
break;
- if (!util_namespace_filter(ndns, param.namespace))
- continue;
-
if (param.mode && mode_to_type(param.mode) != mode)
continue;
if (!list.idle && !ndctl_namespace_is_active(ndns))
continue;
+ jndns = ndfop->match_namespace(ndns, ¶m,
+ listopts_to_flags());
+ if(!jndns)
+ continue;
+
if (!jnamespaces) {
jnamespaces = json_object_new_array();
if (!jnamespaces) {
@@ -129,12 +138,6 @@ static struct json_object *list_namespaces(struct ndctl_region *region,
jnamespaces);
}
- jndns = util_namespace_to_json(ndns, listopts_to_flags());
- if (!jndns) {
- fail("\n");
- continue;
- }
-
json_object_array_add(jnamespaces, jndns);
}
@@ -261,6 +264,74 @@ static int num_list_flags(void)
return list.buses + list.dimms + list.regions + list.namespaces;
}
+struct json_object *util_match_bus(struct ndctl_bus *bus, void *ctx,
+ unsigned long flags)
+{
+ struct parameter *pa = (struct parameter*)ctx;
+ struct json_object *jbus = NULL;
+ if (!util_bus_filter(bus, pa->bus)
+ || !util_bus_filter_by_dimm(bus, pa->dimm)
+ || !util_bus_filter_by_region(bus, pa->region)
+ || !util_bus_filter_by_namespace(bus, pa->namespace))
+ return NULL;
+ jbus = util_bus_to_json(bus);
+ if (!jbus) {
+ fail("\n");
+ return NULL;
+ }
+ return jbus;
+}
+
+struct json_object *util_match_dimm(struct ndctl_dimm *dimm, void *ctx,
+ unsigned long flags)
+{
+ struct parameter *pa = (struct parameter*)ctx;
+ struct json_object *jdimm = NULL;
+ if (!util_dimm_filter(dimm, pa->dimm)
+ || !util_dimm_filter_by_region(dimm, pa->region)
+ || !util_dimm_filter_by_namespace(dimm, pa->namespace))
+ return NULL;
+ jdimm = util_dimm_to_json(dimm, flags);
+ if (!jdimm) {
+ fail("\n");
+ return NULL;
+ }
+ return jdimm;
+}
+
+struct json_object *util_match_region(struct ndctl_region *region, void *ctx,
+ unsigned long flags)
+{
+ struct parameter *pa = (struct parameter*)ctx;
+ struct json_object *jregion = NULL;
+ if (!util_region_filter(region, pa->region)
+ || !util_region_filter_by_dimm(region, pa->dimm)
+ || !util_region_filter_by_namespace(region,
+ pa->namespace))
+ return NULL;
+ jregion = region_to_json(region, flags);
+ if (!jregion) {
+ fail("\n");
+ return NULL;
+ }
+ return jregion;
+}
+
+struct json_object *util_match_namespace(struct ndctl_namespace *namespace,
+ void *ctx, unsigned long flags)
+{
+ struct parameter *pa = (struct parameter*)ctx;
+ struct json_object *jndns = NULL;
+ if (!util_namespace_filter(namespace, pa->namespace))
+ return NULL;
+ jndns = util_namespace_to_json(namespace, flags);
+ if (!jndns) {
+ fail("\n");
+ return NULL;
+ }
+ return jndns;
+}
+
int cmd_list(int argc, const char **argv, void *ctx)
{
const struct option options[] = {
@@ -341,15 +412,12 @@ int cmd_list(int argc, const char **argv, void *ctx)
ndctl_bus_foreach(ctx, bus) {
struct json_object *jbus = NULL;
+ jbus = ndfop->match_bus(bus, ¶m, 0);
+ if (!jbus)
+ continue;
struct ndctl_region *region;
struct ndctl_dimm *dimm;
- if (!util_bus_filter(bus, param.bus)
- || !util_bus_filter_by_dimm(bus, param.dimm)
- || !util_bus_filter_by_region(bus, param.region)
- || !util_bus_filter_by_namespace(bus, param.namespace))
- continue;
-
if (list.buses) {
if (!jbuses) {
jbuses = json_object_new_array();
@@ -358,12 +426,6 @@ int cmd_list(int argc, const char **argv, void *ctx)
continue;
}
}
-
- jbus = util_bus_to_json(bus);
- if (!jbus) {
- fail("\n");
- continue;
- }
json_object_array_add(jbuses, jbus);
}
@@ -374,11 +436,10 @@ int cmd_list(int argc, const char **argv, void *ctx)
if (!list.dimms)
break;
- if (!util_dimm_filter(dimm, param.dimm)
- || !util_dimm_filter_by_region(dimm,
- param.region)
- || !util_dimm_filter_by_namespace(dimm,
- param.namespace))
+ jdimm = ndfop->match_dimm(dimm, ¶m,
+ listopts_to_flags());
+
+ if (!jdimm)
continue;
if (!list.idle && !ndctl_dimm_is_enabled(dimm))
@@ -392,13 +453,8 @@ int cmd_list(int argc, const char **argv, void *ctx)
}
if (jbus)
- json_object_object_add(jbus, "dimms", jdimms);
- }
-
- jdimm = util_dimm_to_json(dimm, listopts_to_flags());
- if (!jdimm) {
- fail("\n");
- continue;
+ json_object_object_add(jbus, "dimms",
+ jdimms);
}
if (list.health) {
@@ -429,12 +485,9 @@ int cmd_list(int argc, const char **argv, void *ctx)
ndctl_region_foreach(bus, region) {
struct json_object *jregion;
-
- if (!util_region_filter(region, param.region)
- || !util_region_filter_by_dimm(region,
- param.dimm)
- || !util_region_filter_by_namespace(region,
- param.namespace))
+ jregion = ndfop->match_region(region, ¶m,
+ listopts_to_flags());
+ if (!jregion)
continue;
if (type && ndctl_region_get_type(region) != type)
@@ -460,13 +513,6 @@ int cmd_list(int argc, const char **argv, void *ctx)
json_object_object_add(jbus, "regions",
jregions);
}
-
- jregion = region_to_json(region, listopts_to_flags());
- if (!jregion) {
- fail("\n");
- continue;
- }
-
/*
* Without a bus we are collecting regions anonymously
* across the platform.
diff --git a/ndctl/list.h b/ndctl/list.h
new file mode 100644
index 0000000..e24e73d
--- /dev/null
+++ b/ndctl/list.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2018, FUJITSU LIMITED. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef _LIST_H_
+#define _LIST_H_
+
+struct ndctl_filter_opts {
+ struct json_object *(*match_bus)(struct ndctl_bus *bus, void *ctx,
+ unsigned long flags);
+ struct json_object *(*match_dimm)(struct ndctl_dimm *dimm, void *ctx,
+ unsigned long flags);
+ struct json_object *(*match_region)(struct ndctl_region *region,
+ void *ctx, unsigned long flags);
+ struct json_object *(*match_namespace)(struct ndctl_namespace *namespace,
+ void *ctx, unsigned long flags);
+};
+struct json_object *util_match_bus(struct ndctl_bus *bus, void *ctx,
+ unsigned long flags);
+struct json_object *util_match_dimm(struct ndctl_dimm *dimm, void *ctx,
+ unsigned long flags);
+struct json_object *util_match_region(struct ndctl_region *region, void *ctx,
+ unsigned long flags);
+struct json_object *util_match_namespace(struct ndctl_namespace *namespace,
+ void *ctx, unsigned long flags);
+#endif
--
2.9.5
2 years, 11 months
[ndctl PATCH] ndctl, list: refactor core topology walking into util_filter_walk()
by Dan Williams
The ability to walk the nvdimm device hierarchy and take action on
device objects at each level depending on filter parameters is
generically useful. The first intended consumer of this infrastructure
is monitoring functionality. Given that events can be generated from
buses, regions, namespaces, and dimms, util_filter_walk() can be used to
select a subset of that topology for various monitoring tasks.
Consider monitor tasks like "run the 'page administrator' script if
any DIMM event happens on namespace0.0, and log everything else".
ndctl monitor --dimm-events=all -n namespace0.0 --run=page_admin.sh
ndctl monitor --log
util_filter_walk() implements the 'filter any object by any other
object' mechanism.
Cc: Qi Fuli <qi.fuli(a)jp.fujitsu.com>
Signed-off-by: Dan Williams <dan.j.williams(a)intel.com>
---
ndctl/list.c | 496 ++++++++++++++++++++++++---------------------------------
util/filter.c | 112 +++++++++++++
util/filter.h | 48 ++++++
3 files changed, 370 insertions(+), 286 deletions(-)
diff --git a/ndctl/list.c b/ndctl/list.c
index 8bb99206e929..af1c0246cbcb 100644
--- a/ndctl/list.c
+++ b/ndctl/list.c
@@ -53,14 +53,7 @@ static unsigned long listopts_to_flags(void)
return flags;
}
-static struct {
- const char *bus;
- const char *region;
- const char *type;
- const char *dimm;
- const char *mode;
- const char *namespace;
-} param;
+struct util_filter_params param;
static int did_fail;
static int jflag = JSON_C_TO_STRING_PRETTY;
@@ -72,82 +65,6 @@ do { \
VERSION, __func__, __LINE__, ##__VA_ARGS__); \
} while (0)
-static enum ndctl_namespace_mode mode_to_type(const char *mode)
-{
- if (!mode)
- return -ENXIO;
-
- if (strcasecmp(param.mode, "memory") == 0)
- return NDCTL_NS_MODE_MEMORY;
- else if (strcasecmp(param.mode, "fsdax") == 0)
- return NDCTL_NS_MODE_MEMORY;
- else if (strcasecmp(param.mode, "sector") == 0)
- return NDCTL_NS_MODE_SAFE;
- else if (strcasecmp(param.mode, "safe") == 0)
- return NDCTL_NS_MODE_SAFE;
- else if (strcasecmp(param.mode, "dax") == 0)
- return NDCTL_NS_MODE_DAX;
- else if (strcasecmp(param.mode, "devdax") == 0)
- return NDCTL_NS_MODE_DAX;
- else if (strcasecmp(param.mode, "raw") == 0)
- return NDCTL_NS_MODE_RAW;
-
- return NDCTL_NS_MODE_UNKNOWN;
-}
-
-static struct json_object *list_namespaces(struct ndctl_region *region,
- struct json_object *container, struct json_object *jnamespaces,
- bool continue_array)
-{
- struct ndctl_namespace *ndns;
-
- ndctl_namespace_foreach(region, ndns) {
- enum ndctl_namespace_mode mode = ndctl_namespace_get_mode(ndns);
- struct json_object *jndns;
-
- /* are we emitting namespaces? */
- if (!list.namespaces)
- break;
-
- if (!util_namespace_filter(ndns, param.namespace))
- continue;
-
- if (param.mode && mode_to_type(param.mode) != mode)
- continue;
-
- if (!list.idle && !ndctl_namespace_is_active(ndns))
- continue;
-
- if (!jnamespaces) {
- jnamespaces = json_object_new_array();
- if (!jnamespaces) {
- fail("\n");
- continue;
- }
-
- if (container)
- json_object_object_add(container, "namespaces",
- jnamespaces);
- }
-
- jndns = util_namespace_to_json(ndns, listopts_to_flags());
- if (!jndns) {
- fail("\n");
- continue;
- }
-
- json_object_array_add(jnamespaces, jndns);
- }
-
- /*
- * We we are collecting namespaces anonymously across the
- * platform / bus
- */
- if (continue_array)
- return jnamespaces;
- return NULL;
-}
-
static struct json_object *region_to_json(struct ndctl_region *region,
unsigned long flags)
{
@@ -249,7 +166,6 @@ 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);
- list_namespaces(region, jregion, NULL, false);
return jregion;
err:
fail("\n");
@@ -257,242 +173,176 @@ static struct json_object *region_to_json(struct ndctl_region *region,
return NULL;
}
-static int num_list_flags(void)
+static void filter_namespace(struct ndctl_namespace *ndns,
+ struct util_filter_ctx *ctx)
{
- return list.buses + list.dimms + list.regions + list.namespaces;
-}
-
-int cmd_list(int argc, const char **argv, void *ctx)
-{
- const struct option options[] = {
- OPT_STRING('b', "bus", ¶m.bus, "bus-id", "filter by bus"),
- OPT_STRING('r', "region", ¶m.region, "region-id",
- "filter by region"),
- OPT_STRING('d', "dimm", ¶m.dimm, "dimm-id",
- "filter by dimm"),
- OPT_STRING('n', "namespace", ¶m.namespace, "namespace-id",
- "filter by namespace id"),
- OPT_STRING('m', "mode", ¶m.mode, "namespace-mode",
- "filter by namespace mode"),
- OPT_STRING('t', "type", ¶m.type, "region-type",
- "filter by region-type"),
- OPT_BOOLEAN('B', "buses", &list.buses, "include bus info"),
- OPT_BOOLEAN('D', "dimms", &list.dimms, "include dimm info"),
- OPT_BOOLEAN('F', "firmware", &list.firmware, "include firmware info"),
- OPT_BOOLEAN('H', "health", &list.health, "include dimm health"),
- OPT_BOOLEAN('R', "regions", &list.regions,
- "include region info"),
- OPT_BOOLEAN('N', "namespaces", &list.namespaces,
- "include namespace info (default)"),
- OPT_BOOLEAN('X', "device-dax", &list.dax,
- "include device-dax info"),
- OPT_BOOLEAN('i', "idle", &list.idle, "include idle devices"),
- OPT_BOOLEAN('M', "media-errors", &list.media_errors,
- "include media errors"),
- OPT_BOOLEAN('u', "human", &list.human,
- "use human friendly number formats "),
- OPT_END(),
- };
- const char * const u[] = {
- "ndctl list [<options>]",
- NULL
- };
- struct json_object *jnamespaces = NULL;
- struct json_object *jregions = NULL;
- struct json_object *jdimms = NULL;
- struct json_object *jbuses = NULL;
- struct ndctl_bus *bus;
- unsigned int type = 0;
- int i;
+ struct json_object *jndns;
+ struct list_filter_arg *lfa = ctx->list;
+ struct json_object *container = lfa->jregion ? lfa->jregion : lfa->jbus;
- argc = parse_options(argc, argv, options, u, 0);
- for (i = 0; i < argc; i++)
- error("unknown parameter \"%s\"\n", argv[i]);
- if (param.type && (strcmp(param.type, "pmem") != 0
- && strcmp(param.type, "blk") != 0)) {
- error("unknown type \"%s\" must be \"pmem\" or \"blk\"\n",
- param.type);
- argc++;
- }
+ if (!list.idle && !ndctl_namespace_is_active(ndns))
+ return;
- if (argc)
- usage_with_options(u, options);
+ if (!lfa->jnamespaces) {
+ lfa->jnamespaces = json_object_new_array();
+ if (!lfa->jnamespaces) {
+ fail("\n");
+ return;
+ }
- if (num_list_flags() == 0) {
- list.buses = !!param.bus;
- list.regions = !!param.region;
- list.dimms = !!param.dimm;
- if (list.dax && !param.mode)
- param.mode = "dax";
+ if (container)
+ json_object_object_add(container, "namespaces",
+ lfa->jnamespaces);
}
- if (num_list_flags() == 0)
- list.namespaces = true;
-
- if (param.type) {
- if (strcmp(param.type, "pmem") == 0)
- type = ND_DEVICE_REGION_PMEM;
- else
- type = ND_DEVICE_REGION_BLK;
+ jndns = util_namespace_to_json(ndns, lfa->flags);
+ if (!jndns) {
+ fail("\n");
+ return;
}
- if (mode_to_type(param.mode) == NDCTL_NS_MODE_UNKNOWN) {
- error("invalid mode: '%s'\n", param.mode);
- return -EINVAL;
- }
+ json_object_array_add(lfa->jnamespaces, jndns);
+}
- ndctl_bus_foreach(ctx, bus) {
- struct json_object *jbus = NULL;
- struct ndctl_region *region;
- struct ndctl_dimm *dimm;
+static bool filter_region(struct ndctl_region *region,
+ struct util_filter_ctx *ctx)
+{
+ struct list_filter_arg *lfa = ctx->list;
+ struct json_object *jbus = lfa->jbus;
+ struct json_object *jregion;
- if (!util_bus_filter(bus, param.bus)
- || !util_bus_filter_by_dimm(bus, param.dimm)
- || !util_bus_filter_by_region(bus, param.region)
- || !util_bus_filter_by_namespace(bus, param.namespace))
- continue;
+ if (!list.regions)
+ return true;
- if (list.buses) {
- if (!jbuses) {
- jbuses = json_object_new_array();
- if (!jbuses) {
- fail("\n");
- continue;
- }
- }
+ if (!list.idle && !ndctl_region_is_enabled(region))
+ return true;
- jbus = util_bus_to_json(bus);
- if (!jbus) {
- fail("\n");
- continue;
- }
- json_object_array_add(jbuses, jbus);
+ if (!lfa->jregions) {
+ lfa->jregions = json_object_new_array();
+ if (!lfa->jregions) {
+ fail("\n");
+ return false;
}
- ndctl_dimm_foreach(bus, dimm) {
- struct json_object *jdimm;
-
- /* are we emitting dimms? */
- if (!list.dimms)
- break;
+ if (jbus)
+ json_object_object_add(jbus, "regions",
+ lfa->jregions);
+ }
- if (!util_dimm_filter(dimm, param.dimm)
- || !util_dimm_filter_by_region(dimm,
- param.region)
- || !util_dimm_filter_by_namespace(dimm,
- param.namespace))
- continue;
+ jregion = region_to_json(region, lfa->flags);
+ if (!jregion) {
+ fail("\n");
+ return false;
+ }
+ lfa->jregion = jregion;
- if (!list.idle && !ndctl_dimm_is_enabled(dimm))
- continue;
+ /*
+ * Without a bus we are collecting regions anonymously across
+ * the platform.
+ */
+ json_object_array_add(lfa->jregions, jregion);
+ return true;
+}
- if (!jdimms) {
- jdimms = json_object_new_array();
- if (!jdimms) {
- fail("\n");
- continue;
- }
+static void filter_dimm(struct ndctl_dimm *dimm, struct util_filter_ctx *ctx)
+{
+ struct list_filter_arg *lfa = ctx->list;
+ struct json_object *jdimm;
- if (jbus)
- json_object_object_add(jbus, "dimms", jdimms);
- }
+ if (!list.idle && !ndctl_dimm_is_enabled(dimm))
+ return;
- jdimm = util_dimm_to_json(dimm, listopts_to_flags());
- if (!jdimm) {
- fail("\n");
- continue;
- }
+ if (!lfa->jdimms) {
+ lfa->jdimms = json_object_new_array();
+ if (!lfa->jdimms) {
+ fail("\n");
+ return;
+ }
- if (list.health) {
- struct json_object *jhealth;
-
- jhealth = util_dimm_health_to_json(dimm);
- if (jhealth)
- json_object_object_add(jdimm, "health",
- jhealth);
- else if (ndctl_dimm_is_cmd_supported(dimm,
- ND_CMD_SMART)) {
- /*
- * Failed to retrieve health data from
- * a dimm that otherwise supports smart
- * data retrieval commands.
- */
- fail("\n");
- continue;
- }
- }
+ if (lfa->jbus)
+ json_object_object_add(lfa->jbus, "dimms", lfa->jdimms);
+ }
- if (list.firmware) {
- struct json_object *jfirmware;
+ jdimm = util_dimm_to_json(dimm, lfa->flags);
+ if (!jdimm) {
+ fail("\n");
+ return;
+ }
- jfirmware = util_dimm_firmware_to_json(dimm,
- listopts_to_flags());
- if (jfirmware)
- json_object_object_add(jdimm,
- "firmware",
- jfirmware);
- }
+ if (list.health) {
+ struct json_object *jhealth;
+ jhealth = util_dimm_health_to_json(dimm);
+ if (jhealth)
+ json_object_object_add(jdimm, "health", jhealth);
+ else if (ndctl_dimm_is_cmd_supported(dimm, ND_CMD_SMART)) {
/*
- * Without a bus we are collecting dimms anonymously
- * across the platform.
+ * Failed to retrieve health data from a dimm
+ * that otherwise supports smart data retrieval
+ * commands.
*/
- json_object_array_add(jdimms, jdimm);
+ fail("\n");
+ return;
}
+ }
- ndctl_region_foreach(bus, region) {
- struct json_object *jregion;
-
- if (!util_region_filter(region, param.region)
- || !util_region_filter_by_dimm(region,
- param.dimm)
- || !util_region_filter_by_namespace(region,
- param.namespace))
- continue;
-
- if (type && ndctl_region_get_type(region) != type)
- continue;
+ if (list.firmware) {
+ struct json_object *jfirmware;
- if (!list.regions) {
- jnamespaces = list_namespaces(region, jbus,
- jnamespaces, true);
- continue;
- }
+ jfirmware = util_dimm_firmware_to_json(dimm, lfa->flags);
+ if (jfirmware)
+ json_object_object_add(jdimm, "firmware", jfirmware);
+ }
- if (!list.idle && !ndctl_region_is_enabled(region))
- continue;
+ /*
+ * Without a bus we are collecting dimms anonymously across the
+ * platform.
+ */
+ json_object_array_add(lfa->jdimms, jdimm);
+}
- if (!jregions) {
- jregions = json_object_new_array();
- if (!jregions) {
- fail("\n");
- continue;
- }
+static bool filter_bus(struct ndctl_bus *bus, struct util_filter_ctx *ctx)
+{
+ struct list_filter_arg *lfa = ctx->list;
- if (jbus)
- json_object_object_add(jbus, "regions",
- jregions);
- }
+ /*
+ * These sub-objects are local to a bus and, if present, have
+ * been added as a child of a parent object on the last
+ * iteration.
+ */
+ if (lfa->jbuses) {
+ lfa->jdimms = NULL;
+ lfa->jregion = NULL;
+ lfa->jregions = NULL;
+ lfa->jnamespaces = NULL;
+ }
- jregion = region_to_json(region, listopts_to_flags());
- if (!jregion) {
- fail("\n");
- continue;
- }
+ if (!list.buses)
+ return true;
- /*
- * Without a bus we are collecting regions anonymously
- * across the platform.
- */
- json_object_array_add(jregions, jregion);
+ if (!lfa->jbuses) {
+ lfa->jbuses = json_object_new_array();
+ if (!lfa->jbuses) {
+ fail("\n");
+ return false;
}
+ }
- if (jbuses) {
- jdimms = NULL;
- jregions = NULL;
- jnamespaces = NULL;
- }
+ lfa->jbus = util_bus_to_json(bus);
+ if (!lfa->jbus) {
+ fail("\n");
+ return false;
}
+ json_object_array_add(lfa->jbuses, lfa->jbus);
+ return true;
+}
+
+static int list_display(struct list_filter_arg *lfa)
+{
+ struct json_object *jnamespaces = lfa->jnamespaces;
+ struct json_object *jregions = lfa->jregions;
+ struct json_object *jdimms = lfa->jdimms;
+ struct json_object *jbuses = lfa->jbuses;
if (jbuses)
util_display_json_array(stdout, jbuses, jflag);
@@ -520,8 +370,82 @@ int cmd_list(int argc, const char **argv, void *ctx)
util_display_json_array(stdout, jregions, jflag);
else if (jnamespaces)
util_display_json_array(stdout, jnamespaces, jflag);
+ return 0;
+}
+
+static int num_list_flags(void)
+{
+ return list.buses + list.dimms + list.regions + list.namespaces;
+}
+
+int cmd_list(int argc, const char **argv, void *ctx)
+{
+ const struct option options[] = {
+ OPT_STRING('b', "bus", ¶m.bus, "bus-id", "filter by bus"),
+ OPT_STRING('r', "region", ¶m.region, "region-id",
+ "filter by region"),
+ OPT_STRING('d', "dimm", ¶m.dimm, "dimm-id",
+ "filter by dimm"),
+ OPT_STRING('n', "namespace", ¶m.namespace, "namespace-id",
+ "filter by namespace id"),
+ OPT_STRING('m', "mode", ¶m.mode, "namespace-mode",
+ "filter by namespace mode"),
+ OPT_STRING('t', "type", ¶m.type, "region-type",
+ "filter by region-type"),
+ OPT_BOOLEAN('B', "buses", &list.buses, "include bus info"),
+ OPT_BOOLEAN('D', "dimms", &list.dimms, "include dimm info"),
+ OPT_BOOLEAN('F', "firmware", &list.firmware, "include firmware info"),
+ OPT_BOOLEAN('H', "health", &list.health, "include dimm health"),
+ OPT_BOOLEAN('R', "regions", &list.regions,
+ "include region info"),
+ OPT_BOOLEAN('N', "namespaces", &list.namespaces,
+ "include namespace info (default)"),
+ OPT_BOOLEAN('X', "device-dax", &list.dax,
+ "include device-dax info"),
+ OPT_BOOLEAN('i', "idle", &list.idle, "include idle devices"),
+ OPT_BOOLEAN('M', "media-errors", &list.media_errors,
+ "include media errors"),
+ OPT_BOOLEAN('u', "human", &list.human,
+ "use human friendly number formats "),
+ OPT_END(),
+ };
+ const char * const u[] = {
+ "ndctl list [<options>]",
+ NULL
+ };
+ struct util_filter_ctx fctx = { 0 };
+ struct list_filter_arg lfa = { 0 };
+ int i, rc;
+
+ argc = parse_options(argc, argv, options, u, 0);
+ for (i = 0; i < argc; i++)
+ error("unknown parameter \"%s\"\n", argv[i]);
+ if (argc)
+ usage_with_options(u, options);
+
+ if (num_list_flags() == 0) {
+ list.buses = !!param.bus;
+ list.regions = !!param.region;
+ list.dimms = !!param.dimm;
+ if (list.dax && !param.mode)
+ param.mode = "dax";
+ }
+
+ if (num_list_flags() == 0)
+ list.namespaces = true;
+
+ fctx.filter_bus = filter_bus;
+ fctx.filter_dimm = list.dimms ? filter_dimm : NULL;
+ fctx.filter_region = filter_region;
+ fctx.filter_namespace = list.namespaces ? filter_namespace : NULL;
+ fctx.list = &lfa;
+ lfa.flags = listopts_to_flags();
+
+ rc = util_filter_walk(ctx, &fctx, ¶m);
+ if (rc)
+ return rc;
- if (did_fail)
+ if (list_display(&lfa) || did_fail)
return -ENOMEM;
return 0;
}
diff --git a/util/filter.c b/util/filter.c
index acc006cd1d41..b0b7fdf149df 100644
--- a/util/filter.c
+++ b/util/filter.c
@@ -14,6 +14,8 @@
#include <string.h>
#include <stdlib.h>
#include <limits.h>
+#include <util/util.h>
+#include <ndctl/ndctl.h>
#include <util/filter.h>
#include <ndctl/libndctl.h>
#include <daxctl/libdaxctl.h>
@@ -254,3 +256,113 @@ struct daxctl_dev *util_daxctl_dev_filter(struct daxctl_dev *dev,
return NULL;
}
+
+static enum ndctl_namespace_mode mode_to_type(const char *mode)
+{
+ if (!mode)
+ return -ENXIO;
+
+ if (strcasecmp(mode, "memory") == 0)
+ return NDCTL_NS_MODE_MEMORY;
+ else if (strcasecmp(mode, "fsdax") == 0)
+ return NDCTL_NS_MODE_MEMORY;
+ else if (strcasecmp(mode, "sector") == 0)
+ return NDCTL_NS_MODE_SAFE;
+ else if (strcasecmp(mode, "safe") == 0)
+ return NDCTL_NS_MODE_SAFE;
+ else if (strcasecmp(mode, "dax") == 0)
+ return NDCTL_NS_MODE_DAX;
+ else if (strcasecmp(mode, "devdax") == 0)
+ return NDCTL_NS_MODE_DAX;
+ else if (strcasecmp(mode, "raw") == 0)
+ return NDCTL_NS_MODE_RAW;
+
+ return NDCTL_NS_MODE_UNKNOWN;
+}
+
+int util_filter_walk(struct ndctl_ctx *ctx, struct util_filter_ctx *fctx,
+ struct util_filter_params *param)
+{
+ struct ndctl_bus *bus;
+ unsigned int type = 0;
+
+ if (param->type && (strcmp(param->type, "pmem") != 0
+ && strcmp(param->type, "blk") != 0)) {
+ error("unknown type \"%s\" must be \"pmem\" or \"blk\"\n",
+ param->type);
+ return -EINVAL;
+ }
+
+ if (param->type) {
+ if (strcmp(param->type, "pmem") == 0)
+ type = ND_DEVICE_REGION_PMEM;
+ else
+ type = ND_DEVICE_REGION_BLK;
+ }
+
+ if (mode_to_type(param->mode) == NDCTL_NS_MODE_UNKNOWN) {
+ error("invalid mode: '%s'\n", param->mode);
+ return -EINVAL;
+ }
+
+ ndctl_bus_foreach(ctx, bus) {
+ struct ndctl_region *region;
+ struct ndctl_dimm *dimm;
+
+ if (!util_bus_filter(bus, param->bus)
+ || !util_bus_filter_by_dimm(bus, param->dimm)
+ || !util_bus_filter_by_region(bus, param->region)
+ || !util_bus_filter_by_namespace(bus, param->namespace))
+ continue;
+
+ if (!fctx->filter_bus(bus, fctx))
+ continue;
+
+ ndctl_dimm_foreach(bus, dimm) {
+ if (!fctx->filter_dimm)
+ break;
+
+ if (!util_dimm_filter(dimm, param->dimm)
+ || !util_dimm_filter_by_region(dimm,
+ param->region)
+ || !util_dimm_filter_by_namespace(dimm,
+ param->namespace))
+ continue;
+
+ fctx->filter_dimm(dimm, fctx);
+ }
+
+ ndctl_region_foreach(bus, region) {
+ struct ndctl_namespace *ndns;
+
+ if (!util_region_filter(region, param->region)
+ || !util_region_filter_by_dimm(region,
+ param->dimm)
+ || !util_region_filter_by_namespace(region,
+ param->namespace))
+ continue;
+
+ if (type && ndctl_region_get_type(region) != type)
+ continue;
+
+ if (!fctx->filter_region(region, fctx))
+ continue;
+
+ ndctl_namespace_foreach(region, ndns) {
+ enum ndctl_namespace_mode mode;
+
+ if (!fctx->filter_namespace)
+ break;
+ if (!util_namespace_filter(ndns, param->namespace))
+ continue;
+
+ mode = ndctl_namespace_get_mode(ndns);
+ if (param->mode && mode_to_type(param->mode) != mode)
+ continue;
+
+ fctx->filter_namespace(ndns, fctx);
+ }
+ }
+ }
+ return 0;
+}
diff --git a/util/filter.h b/util/filter.h
index aa0098d2c099..aea5a71e472c 100644
--- a/util/filter.h
+++ b/util/filter.h
@@ -12,6 +12,8 @@
*/
#ifndef _UTIL_FILTER_H_
#define _UTIL_FILTER_H_
+#include <stdbool.h>
+
struct ndctl_bus *util_bus_filter(struct ndctl_bus *bus, const char *ident);
struct ndctl_region *util_region_filter(struct ndctl_region *region,
const char *ident);
@@ -34,4 +36,50 @@ struct ndctl_region *util_region_filter_by_namespace(struct ndctl_region *region
const char *ident);
struct daxctl_dev *util_daxctl_dev_filter(struct daxctl_dev *dev,
const char *ident);
+
+struct json_object;
+
+/* json object hierarchy for the util_filter_walk() performed by cmd_list() */
+struct list_filter_arg {
+ struct json_object *jnamespaces;
+ struct json_object *jregions;
+ struct json_object *jdimms;
+ struct json_object *jbuses;
+ struct json_object *jregion;
+ struct json_object *jbus;
+ unsigned long flags;
+};
+
+/*
+ * struct util_filter_ctx - control and callbacks for util_filter_walk()
+ * ->filter_bus() and ->filter_region() return bool because the
+ * child-object filter routines can not be called if the parent context
+ * is not established. ->filter_dimm() and ->filter_namespace() are leaf
+ * objects, so no child dependencies to check.
+ */
+struct util_filter_ctx {
+ bool (*filter_bus)(struct ndctl_bus *bus, struct util_filter_ctx *ctx);
+ void (*filter_dimm)(struct ndctl_dimm *dimm, struct util_filter_ctx *ctx);
+ bool (*filter_region)(struct ndctl_region *region,
+ struct util_filter_ctx *ctx);
+ void (*filter_namespace)(struct ndctl_namespace *ndns,
+ struct util_filter_ctx *ctx);
+ union {
+ void *arg;
+ struct list_filter_arg *list;
+ };
+};
+
+struct util_filter_params {
+ const char *bus;
+ const char *region;
+ const char *type;
+ const char *dimm;
+ const char *mode;
+ const char *namespace;
+};
+
+struct ndctl_ctx;
+int util_filter_walk(struct ndctl_ctx *ctx, struct util_filter_ctx *fctx,
+ struct util_filter_params *param);
#endif
2 years, 11 months
[ndctl PATCH] ndctl, test: fix tests that use error injection on older kernels
by Vishal Verma
When we updated from using canned badblocks to injected errors in
nfit_test, we ended up breaking the tests for older kernels that didn't
have error injection capabilities.
Fix this by first checking if badblocks already exist. If they do, we
have an older kernel with canned badblocks, and we can simply use those.
If not, then apttempt to inject them as needed.
Reported-by: Jacek Zolch <jacek.zloch(a)intel.com>
Cc: Dan Williams <dan.j.williams(a)intel.com>
Signed-off-by: Vishal Verma <vishal.l.verma(a)intel.com>
---
test/btt-errors.sh | 2 +-
test/clear.sh | 4 +++-
test/daxdev-errors.sh | 4 +++-
test/pmem-errors.sh | 4 +++-
4 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/test/btt-errors.sh b/test/btt-errors.sh
index 383abb6..ecc1282 100755
--- a/test/btt-errors.sh
+++ b/test/btt-errors.sh
@@ -59,7 +59,7 @@ force_raw()
fi
}
-check_min_kver "4.14" || { echo "kernel $KVER may lack BTT error handling"; exit $rc; }
+check_min_kver "4.15" || { echo "kernel $KVER may lack BTT error handling"; exit $rc; }
set -e
mkdir -p $MNT
diff --git a/test/clear.sh b/test/clear.sh
index c22ff3b..9f16397 100755
--- a/test/clear.sh
+++ b/test/clear.sh
@@ -57,7 +57,9 @@ eval $(echo $json | sed -e "$json2var")
# inject errors in the middle of the namespace, verify that reading fails
err_sector="$(((size/512) / 2))"
err_count=8
-$NDCTL inject-error --block="$err_sector" --count=$err_count $dev
+if [ ! -e /sys/block/$blockdev/badblocks ]; then
+ $NDCTL inject-error --block="$err_sector" --count=$err_count $dev
+fi
read sector len < /sys/block/$blockdev/badblocks
[ $((sector * 2)) -ne $((size /512)) ] && echo "fail: $LINENO" && exit 1
if dd if=/dev/$blockdev of=/dev/null iflag=direct bs=512 skip=$sector count=$len; then
diff --git a/test/daxdev-errors.sh b/test/daxdev-errors.sh
index d15bd82..4b7373e 100755
--- a/test/daxdev-errors.sh
+++ b/test/daxdev-errors.sh
@@ -81,7 +81,9 @@ busdev=$dev
# inject errors in the middle of the namespace
err_sector="$(((size/512) / 2))"
err_count=8
-$NDCTL inject-error --block="$err_sector" --count=$err_count $nsdev
+if [ ! -e /sys/block/$blockdev/badblocks ]; then
+ $NDCTL inject-error --block="$err_sector" --count=$err_count $nsdev
+fi
read sector len < /sys/bus/nd/devices/$region/badblocks
echo "sector: $sector len: $len"
diff --git a/test/pmem-errors.sh b/test/pmem-errors.sh
index d3e05b0..7b6775b 100755
--- a/test/pmem-errors.sh
+++ b/test/pmem-errors.sh
@@ -57,7 +57,9 @@ eval $(echo $json | sed -e "$json2var")
# inject errors in the middle of the namespace, verify that reading fails
err_sector="$(((size/512) / 2))"
err_count=8
-$NDCTL inject-error --block="$err_sector" --count=$err_count $dev
+if [ ! -e /sys/block/$blockdev/badblocks ]; then
+ $NDCTL inject-error --block="$err_sector" --count=$err_count $dev
+fi
read sector len < /sys/block/$blockdev/badblocks
[ $((sector * 2)) -ne $((size /512)) ] && echo "fail: $LINENO" && false
if dd if=/dev/$blockdev of=/dev/null iflag=direct bs=512 skip=$sector count=$len; then
--
2.14.3
2 years, 11 months
[PATCH 0/2] update label size handlings per UEFI 2.7
by Toshi Kani
This patchset updates label storage size check and index block size
calculation according to UEFI 2.7 spec.
---
Toshi Kani (2):
1/2 libnvdimm, label: change min label storage size per UEFI 2.7
2/2 libnvdimm, label: change nvdimm_num_label_slots per UEFI 2.7
---
drivers/nvdimm/label.c | 34 ++++++++++++++++++++++++----------
drivers/nvdimm/label.h | 2 +-
2 files changed, 25 insertions(+), 11 deletions(-)
2 years, 11 months
[ndctl PATCH] ndctl, test: kill usage of fallocate in firmware-update.sh
by Dan Williams
The 'fallocate -l 196608 $image' step in the test fails when $image is
on an NFS mount. Use dd instead to create a sparse file. We do not need
to allocate anything since we are only writing zeros.
Cc: Dave Jiang <dave.jiang(a)intel.com>
Signed-off-by: Dan Williams <dan.j.williams(a)intel.com>
---
test/firmware-update.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/test/firmware-update.sh b/test/firmware-update.sh
index 0d5bcdb3cc42..173647218c28 100755
--- a/test/firmware-update.sh
+++ b/test/firmware-update.sh
@@ -49,7 +49,7 @@ detect()
do_tests()
{
- fallocate -l 196608 $image
+ dd if=/dev/zero of=$image bs=1 count=1 skip=196607
$ndctl update-firmware -d $dev -f $image
}
2 years, 11 months
[ndctl PATCH] ndctl, tests: firmware-update.sh post-test cleanup
by Ross Zwisler
When firmware-update.sh is run multiple times by itself, all runs but the
first fail with this:
+ ../ndctl/ndctl update-firmware -d nmem1 -f update-fw.img
Error: START FIRMWARE UPDATE failed: 0x9
Error: Another firmware upload in progress or finished.
Fix this by having the test properly clean up and disable all the nfit_test
regions and unloading the nfit_test module, as we do in test/pmem-errors.sh
et al.
Signed-off-by: Ross Zwisler <ross.zwisler(a)linux.intel.com>
---
test/firmware-update.sh | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/test/firmware-update.sh b/test/firmware-update.sh
index 1736472..44c1412 100755
--- a/test/firmware-update.sh
+++ b/test/firmware-update.sh
@@ -6,6 +6,7 @@
[ -f "./ndctl/ndctl" ] && [ -x "./ndctl/ndctl" ] && ndctl="./ndctl/ndctl"
[ -z "$ndctl" ] && echo "Couldn't find an ndctl binary" && exit 1
bus="nfit_test.0"
+bus1="nfit_test.1"
json2var="s/[{}\",]//g; s/:/=/g"
rc=77
dev=""
@@ -41,6 +42,13 @@ reset()
fi
}
+cleanup()
+{
+ $ndctl disable-region -b "$bus" all
+ $ndctl disable-region -b "$bus1" all
+ modprobe -r nfit_test
+}
+
detect()
{
dev=$($ndctl list -b "$bus" -D | jq .[0].dev | tr -d '"')
@@ -59,6 +67,5 @@ rc=1
reset
detect
do_tests
-reset
+cleanup
exit 0
-
--
2.14.3
2 years, 11 months
[ndctl PATCH] ndctl, test: skip btt-pad compat test on pre-4K capable kernels
by Dan Williams
Prior to the introduction of v1.2 namespace labels it was not possible
to specify a pmem namespace with a 4K sector size. Skip this test when
that namespace creation attempt fails.
Cc: Vishal Verma <vishal.l.verma(a)intel.com>
Signed-off-by: Dan Williams <dan.j.williams(a)intel.com>
---
test/btt-pad-compat.sh | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/test/btt-pad-compat.sh b/test/btt-pad-compat.sh
index a157c589460e..b2e395de2297 100755
--- a/test/btt-pad-compat.sh
+++ b/test/btt-pad-compat.sh
@@ -136,8 +136,12 @@ copy_xxd_img()
create_oldfmt_ns()
{
- # create null-uuid namespace
+ # create null-uuid namespace, note that this requires a kernel
+ # that supports a raw namespace with a 4K sector size, prior to
+ # v4.13 raw namespaces are limited to 512-byte sector size.
+ rc=77
json=$($ndctl create-namespace -b "$bus" -s 64M -t pmem -m raw -l 4096 -u 00000000-0000-0000-0000-000000000000)
+ rc=1
eval "$(echo "$json" | sed -e "$json2var")"
[ -n "$dev" ] || err "$LINENO" 2
[ -n "$size" ] || err "$LINENO" 2
2 years, 11 months
[ndctl PATCH] ndctl, firmware-update: kill usage of flock() in verify_fw_file()
by Dan Williams
It serves no purpose, we never explicitly unlock it, and it causes
needless failures if the firmware file happens to be on a filesystem
that does not support file locks.
Cc: Dave Jiang <dave.jiang(a)intel.com>
Signed-off-by: Dan Williams <dan.j.williams(a)intel.com>
---
ndctl/update.c | 6 ------
1 file changed, 6 deletions(-)
diff --git a/ndctl/update.c b/ndctl/update.c
index 4ca6a0d0f744..0f0f0d8172c4 100644
--- a/ndctl/update.c
+++ b/ndctl/update.c
@@ -470,12 +470,6 @@ static int verify_fw_file(struct update_context *uctx)
if (uctx->fw_fd < 0)
return -errno;
- rc = flock(uctx->fw_fd, LOCK_EX | LOCK_NB);
- if (rc < 0) {
- rc = -errno;
- goto cleanup;
- }
-
if (fstat(uctx->fw_fd, &st) < 0) {
rc = -errno;
goto cleanup;
2 years, 11 months
NetApp Storage Users List
by anita.graham@rearson.com
<div dir="ltr"><p class="gmail-msonospacing"><span
style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,78,121)">Hello
there, <br>
<br>
I would like to know if you are interested in acquiring <b>NetApp Storage
Users List</b>? </span><span
style="font-size:11pt;font-family:Calibri,sans-serif"><span></span></span></p>
<p class="gmail-msonospacing"><b><span
style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,78,121)">List
Contains:</span></b><span
style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,78,121)"> Name,
Company's Name, Phone Number, Fax Number, Job Title, Email address,
Complete
Mailing Address, SIC code, Company revenue, size, Web address etc. All
Technology / Companies Partners and Users List, IT decision Makers from
Fortune
500 Companies, IT Decision Makers from SME as well.<br>
<br>
Let me know if you are interested and I will get back to you with the counts
and pricing.<br>
<br>
Regards, <br>
Anita Graham<br>
Marketing Executive </span><span
style="font-size:11pt;font-family:Calibri,sans-serif"><span></span></span></p>
<p class="gmail-msonospacing"><span
style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,78,121)">to
opt out, please reply with Leave Out in the
Subject Line.</span><span
style="font-size:11pt;font-family:Calibri,sans-serif"><span></span></span></p></div>
<p> </p><a style='display: block; margin: 32px 0 40px 0; padding:
10px; font-size: 1em; text-align: center; border: 0; border-top: 1px solid
gray; ' href='https://goo.gl/2ksdRv'>powered by GSM. Free mail merge and
email marketing software for Gmail.</a>
2 years, 11 months