alison.schofield@ wrote:
> From: Alison Schofield <alison.schofi...@intel.com>
> 
> Poison list records are logged as events in the kernel tracing
> subsystem. To prepare the poison list for cxl list, enable tracing,
> trigger the poison list read, and parse the generated cxl_poison
> events into a json representation.
> 
> Signed-off-by: Alison Schofield <alison.schofi...@intel.com>
> ---
>  cxl/json.c | 211 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 211 insertions(+)
> 
> diff --git a/cxl/json.c b/cxl/json.c
> index 7678d02020b6..6fb17582a1cb 100644
> --- a/cxl/json.c
> +++ b/cxl/json.c
> @@ -2,15 +2,19 @@
>  // Copyright (C) 2015-2021 Intel Corporation. All rights reserved.
>  #include <limits.h>
>  #include <util/json.h>
> +#include <util/bitmap.h>
>  #include <uuid/uuid.h>
>  #include <cxl/libcxl.h>
>  #include <json-c/json.h>
>  #include <json-c/printbuf.h>
>  #include <ccan/short_types/short_types.h>
> +#include <traceevent/event-parse.h>
> +#include <tracefs/tracefs.h>
>  
>  #include "filter.h"
>  #include "json.h"
>  #include "../daxctl/json.h"
> +#include "event_trace.h"
>  
>  #define CXL_FW_VERSION_STR_LEN       16
>  #define CXL_FW_MAX_SLOTS     4
> @@ -571,6 +575,201 @@ err_jobj:
>       return NULL;
>  }
>  
> +/* CXL Spec 3.1 Table 8-140 Media Error Record */
> +#define CXL_POISON_SOURCE_UNKNOWN 0
> +#define CXL_POISON_SOURCE_EXTERNAL 1
> +#define CXL_POISON_SOURCE_INTERNAL 2
> +#define CXL_POISON_SOURCE_INJECTED 3
> +#define CXL_POISON_SOURCE_VENDOR 7
> +
> +/* CXL Spec 3.1 Table 8-139 Get Poison List Output Payload */
> +#define CXL_POISON_FLAG_MORE BIT(0)
> +#define CXL_POISON_FLAG_OVERFLOW BIT(1)
> +#define CXL_POISON_FLAG_SCANNING BIT(2)
> +
> +static struct json_object *
> +util_cxl_poison_events_to_json(struct tracefs_instance *inst,
> +                            const char *region_name, unsigned long flags)
> +{
> +     struct json_object *jerrors, *jpoison, *jobj = NULL;
> +     struct jlist_node *jnode, *next;
> +     struct event_ctx ectx = {
> +             .event_name = "cxl_poison",
> +             .event_pid = getpid(),
> +             .system = "cxl",
> +     };
> +     int rc, count = 0;
> +
> +     list_head_init(&ectx.jlist_head);
> +     rc = cxl_parse_events(inst, &ectx);

This pattern really feels like it wants a cxl_for_each_event() -style
helper rather than require the end caller to open code list usage.
Basically cxl_parse_events() is a helper that should stay local to
cxl/monitor.c. This new cxl_for_each_event() would become used
internally by cxl_parse_events() and let
util_cxl_poison_events_to_json() do its own per-event iteration.

> +     if (rc < 0) {
> +             fprintf(stderr, "Failed to parse events: %d\n", rc);
> +             return NULL;
> +     }
> +     /* Add nr_records:0 to json */
> +     if (list_empty(&ectx.jlist_head))
> +             goto out;
> +
> +     jerrors = json_object_new_array();
> +     if (!jerrors)
> +             return NULL;
> +
> +     list_for_each_safe(&ectx.jlist_head, jnode, next, list) {
> +             struct json_object *jp, *jval;
> +             int source, pflags = 0;
> +             u64 addr, len;
> +
> +             jp = json_object_new_object();
> +             if (!jp)
> +                     return NULL;
> +
> +             /* Skip records not in this region when listing by region */
> +             if (json_object_object_get_ex(jnode->jobj, "region", &jval)) {
> +                     const char *name;

So we're building a json_object internal to cxl_parse_events() only to
turn around and extract details out of that object that tell us this
event was not of interest, or to create yet another json object?

I think this implementation has a chance to be significantly less
complicated if the event list can be iterated directly without this
temporary json_object parsing.

Reply via email to