@@ -15,6 +15,8 @@ SYNOPSIS
Walk the CXL capable device hierarchy in the system and list all device
instances along with some of their major attributes.
+Options can be specified to limit the output to specific objects.
+
EXAMPLE
-------
----
@@ -1,10 +1,16 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2015-2020 Intel Corporation. All rights reserved.
+#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
+#include <util/log.h>
+#include <util/json.h>
#include <cxl/libcxl.h>
+#include <json-c/json.h>
+
#include "filter.h"
+#include "json.h"
static const char *which_sep(const char *filter)
{
@@ -48,3 +54,47 @@ struct cxl_memdev *util_cxl_memdev_filter(struct cxl_memdev *memdev,
return memdev;
return NULL;
}
+
+static unsigned long params_to_flags(struct cxl_filter_params *param)
+{
+ unsigned long flags = 0;
+
+ if (param->idle)
+ flags |= UTIL_JSON_IDLE;
+ if (param->human)
+ flags |= UTIL_JSON_HUMAN;
+ if (param->health)
+ flags |= UTIL_JSON_HEALTH;
+ return flags;
+}
+
+int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p)
+{
+ struct json_object *jplatform = json_object_new_array();
+ unsigned long flags = params_to_flags(p);
+ struct cxl_memdev *memdev;
+
+ if (!jplatform) {
+ dbg(p, "platform object allocation failure\n");
+ return -ENOMEM;
+ }
+
+ cxl_memdev_foreach(ctx, memdev) {
+ struct json_object *jdev;
+
+ if (!util_cxl_memdev_filter(memdev, p->memdev_filter))
+ continue;
+ if (p->memdevs) {
+ jdev = util_cxl_memdev_to_json(memdev, flags);
+ if (!jdev) {
+ dbg(p, "memdev object allocation failure\n");
+ continue;
+ }
+ json_object_array_add(jplatform, jdev);
+ }
+ }
+
+ util_display_json_array(stdout, jplatform, flags);
+
+ return 0;
+}
@@ -1,7 +1,21 @@
/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright (C) 2015-2020 Intel Corporation. All rights reserved. */
+/* Copyright (C) 2021 Intel Corporation. All rights reserved. */
#ifndef _CXL_UTIL_FILTER_H_
#define _CXL_UTIL_FILTER_H_
+
+#include <stdbool.h>
+#include <util/log.h>
+
+struct cxl_filter_params {
+ const char *memdev_filter;
+ bool memdevs;
+ bool idle;
+ bool human;
+ bool health;
+ struct log_ctx ctx;
+};
+
struct cxl_memdev *util_cxl_memdev_filter(struct cxl_memdev *memdev,
- const char *ident);
+ const char *ident);
+int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *param);
#endif /* _CXL_UTIL_FILTER_H_ */
@@ -9,60 +9,27 @@
#include <json-c/json.h>
#include <cxl/libcxl.h>
#include <util/parse-options.h>
-#include <ccan/array_size/array_size.h>
-#include "json.h"
#include "filter.h"
-static struct {
- bool memdevs;
- bool idle;
- bool human;
- bool health;
-} list;
-
-static unsigned long listopts_to_flags(void)
-{
- unsigned long flags = 0;
-
- if (list.idle)
- flags |= UTIL_JSON_IDLE;
- if (list.human)
- flags |= UTIL_JSON_HUMAN;
- if (list.health)
- flags |= UTIL_JSON_HEALTH;
- return flags;
-}
-
-static struct {
- const char *memdev;
-} param;
-
-static int did_fail;
-
-#define fail(fmt, ...) \
-do { \
- did_fail = 1; \
- fprintf(stderr, "cxl-%s:%s:%d: " fmt, \
- VERSION, __func__, __LINE__, ##__VA_ARGS__); \
-} while (0)
+static struct cxl_filter_params param;
static int num_list_flags(void)
{
- return list.memdevs;
+ return param.memdevs;
}
int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx)
{
const struct option options[] = {
- OPT_STRING('m', "memdev", ¶m.memdev, "memory device name",
+ OPT_STRING('m', "memdev", ¶m.memdev_filter, "memory device name",
"filter by CXL memory device name"),
- OPT_BOOLEAN('M', "memdevs", &list.memdevs,
+ OPT_BOOLEAN('M', "memdevs", ¶m.memdevs,
"include CXL memory device info"),
- OPT_BOOLEAN('i', "idle", &list.idle, "include idle devices"),
- OPT_BOOLEAN('u', "human", &list.human,
+ OPT_BOOLEAN('i', "idle", ¶m.idle, "include disabled devices"),
+ OPT_BOOLEAN('u', "human", ¶m.human,
"use human friendly number formats "),
- OPT_BOOLEAN('H', "health", &list.health,
+ OPT_BOOLEAN('H', "health", ¶m.health,
"include memory device health information "),
OPT_END(),
};
@@ -70,9 +37,6 @@ int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx)
"cxl list [<options>]",
NULL
};
- struct json_object *jdevs = NULL;
- unsigned long list_flags;
- struct cxl_memdev *memdev;
int i;
argc = parse_options(argc, argv, options, u, 0);
@@ -83,46 +47,22 @@ int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx)
usage_with_options(u, options);
if (num_list_flags() == 0) {
- /*
- * TODO: We likely want to list regions by default if nothing
- * was explicitly asked for. But until we have region support,
- * print this error asking for devices explicitly.
- * Once region support is added, this TODO can be removed.
- */
- error("please specify entities to list, e.g. using -m/-M\n");
- usage_with_options(u, options);
- }
-
- list_flags = listopts_to_flags();
-
- cxl_memdev_foreach(ctx, memdev) {
- struct json_object *jdev = NULL;
-
- if (!util_cxl_memdev_filter(memdev, param.memdev))
- continue;
-
- if (list.memdevs) {
- if (!jdevs) {
- jdevs = json_object_new_array();
- if (!jdevs) {
- fail("\n");
- continue;
- }
- }
-
- jdev = util_cxl_memdev_to_json(memdev, list_flags);
- if (!jdev) {
- fail("\n");
- continue;
- }
- json_object_array_add(jdevs, jdev);
+ if (param.memdev_filter)
+ param.memdevs = true;
+ else {
+ /*
+ * TODO: We likely want to list regions by default if
+ * nothing was explicitly asked for. But until we have
+ * region support, print this error asking for devices
+ * explicitly. Once region support is added, this TODO
+ * can be removed.
+ */
+ error("please specify entities to list, e.g. using -m/-M\n");
+ usage_with_options(u, options);
}
}
- if (jdevs)
- util_display_json_array(stdout, jdevs, list_flags);
+ log_init(¶m.ctx, "cxl list", "CXL_LIST_LOG");
- if (did_fail)
- return -ENOMEM;
- return 0;
+ return cxl_filter_walk(ctx, ¶m);
}
@@ -3,6 +3,7 @@ cxl_src = [
'list.c',
'memdev.c',
'../util/json.c',
+ '../util/log.c',
'json.c',
'filter.c',
]
In preparation for introducing more objects and filtering options for 'cxl list' introduce cxl_filter_walk() to centralize CXL topology walks. It fills the same role as ndctl_filter_walk() as a way to distribute topology interrogation beyond 'cxl list' to other commands, and serve as the template for CXL object hierarchy in JSON output payloads. Use the common dbg() logger for log messages. Signed-off-by: Dan Williams <dan.j.williams@intel.com> --- Documentation/cxl/cxl-list.txt | 2 + cxl/filter.c | 50 ++++++++++++++++++++ cxl/filter.h | 18 ++++++- cxl/list.c | 102 ++++++++-------------------------------- cxl/meson.build | 1 5 files changed, 90 insertions(+), 83 deletions(-)