Add field path resolving functions
authorFrancis Deslauriers <francis.deslauriers@efficios.com>
Thu, 16 Dec 2021 16:50:10 +0000 (11:50 -0500)
committerFrancis Deslauriers <francis.deslauriers@efficios.com>
Fri, 15 Jul 2022 18:08:35 +0000 (14:08 -0400)
Signed-off-by: Francis Deslauriers <francis.deslauriers@efficios.com>
Change-Id: I8003a554838ad97f856099e57566556e7781e8ac

src/Kbuild
src/field-path-resolving.c [new file with mode: 0644]
src/field-path-resolving.h [new file with mode: 0644]

index ed7638504ccc93ce7ff7fe052760d0f742719fcb..b7292f9d84da3f72fa526475832e3eaeecf15f40 100644 (file)
@@ -51,6 +51,7 @@ lttng-tracer-objs := lib/msgpack/msgpack.o \
                      metadata-printer.o \
                      clock-utils.o \
                      ctf1-8.o \
+                     field-path-resolving.o \
                      lttng-context-pid.o lttng-context-procname.o \
                      lttng-context-prio.o lttng-context-nice.o \
                      lttng-context-vpid.o lttng-context-tid.o \
diff --git a/src/field-path-resolving.c b/src/field-path-resolving.c
new file mode 100644 (file)
index 0000000..6b221c3
--- /dev/null
@@ -0,0 +1,195 @@
+/* SPDX-License-Identifier: (GPL-2.0-only or LGPL-2.1-only)
+ *
+ * src/field-path-resolving.c
+ *
+ * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (C) 2021 Francis Deslauriers <francis.deslauriers@efficios.com>
+ */
+
+#include <linux/errno.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include <lttng/events.h>
+#include <lttng/events-internal.h>
+
+#include "field-path-resolving.h"
+
+static int append_path_element(struct field_path *field_path, const char *name,
+                              const struct lttng_kernel_event_field *field)
+{
+       struct field_path_node *field_path_node;
+
+       field_path_node = kzalloc(sizeof(*field_path_node), GFP_KERNEL);
+       if (!field_path_node)
+               return -ENOMEM;
+
+       field_path_node->field = field;
+       field_path_node->name = name;
+
+       list_add(&field_path_node->node, &field_path->path);
+       field_path->path_entry_count++;
+
+       return 0;
+}
+
+struct field_path *field_path_resolve(struct field_location_ctx *ctx,
+                                     const char *target_field_name)
+{
+       struct field_path *field_path = NULL;
+       struct field_location_stack_node *node;
+       bool field_found = false;
+       int ret;
+
+       field_path = kzalloc(sizeof(*field_path), GFP_KERNEL);
+       if (!field_path)
+               return NULL;
+
+       INIT_LIST_HEAD(&field_path->path);
+
+       /*
+        * The scope stack contains all the fields processed up until this
+        * point in the current scope and outter scopes.
+        *
+        * Iterate on the stack from the top until we find a integer field
+        * matching the target field name.
+        *
+        * Once found, continue the iteration but only record struct fields.
+        */
+
+       list_for_each_entry (node, &ctx->field_location_stack, node) {
+               if (!field_found) {
+                       /* The location can't be a scope. */
+                       if (node->type == SCOPE_STACK_NODE_TYPE_SCOPE) {
+                               continue;
+                       }
+
+                       /* The location field must be a integer or an enum. */
+                       if (node->field->type->type !=
+                                   lttng_kernel_type_integer &&
+                           node->field->type->type != lttng_kernel_type_enum) {
+                               continue;
+                       }
+
+                       /*
+                        * If the target field name is NULL, use the first
+                        * element encountered, else compare the field names.
+                        */
+                       if (target_field_name == NULL ||
+                           strcmp(node->field_name, target_field_name) == 0) {
+                               field_found = true;
+                               ret = append_path_element(field_path,
+                                                         node->field_name,
+                                                         node->field);
+                               if (ret)
+                                       goto err;
+                       }
+               } else {
+                       /*
+                        * The actual location field was found, from this point
+                        * on we record all surrounding scopes to create the
+                        * full path.
+                        */
+                       if (node->type == SCOPE_STACK_NODE_TYPE_SCOPE) {
+                               ret = append_path_element(
+                                       field_path, node->field_name, NULL);
+                               if (ret)
+                                       goto err;
+                       }
+               }
+       }
+
+       return field_path;
+
+err:
+       field_path_destroy(field_path);
+       return NULL;
+}
+
+void field_path_destroy(struct field_path *fp)
+{
+       struct field_path_node *node, *tmp;
+
+       if (!fp) {
+               return;
+       }
+
+       list_for_each_entry_safe (node, tmp, &fp->path, node) {
+               kfree(node);
+       }
+
+       kfree(fp);
+}
+
+int field_location_stack_push(struct field_location_ctx *ctx,
+                             enum field_location_stack_node_type type,
+                             const char *field_name,
+                             const struct lttng_kernel_event_field *field)
+{
+       struct field_location_stack_node *field_location_stack_node;
+
+       field_location_stack_node =
+               kzalloc(sizeof(*field_location_stack_node), GFP_KERNEL);
+       if (!field_location_stack_node)
+               return -ENOMEM;
+
+       field_location_stack_node->type = type;
+       field_location_stack_node->field = field;
+       field_location_stack_node->field_name = field_name;
+
+       list_add(&field_location_stack_node->node, &ctx->field_location_stack);
+       ctx->field_location_stack_len++;
+
+       return 0;
+}
+
+static void field_location_stack_pop(struct field_location_ctx *ctx)
+{
+       struct field_location_stack_node *node;
+
+       node = list_first_entry(&ctx->field_location_stack,
+                               struct field_location_stack_node, node);
+
+       list_del(&node->node);
+       kfree(node);
+       ctx->field_location_stack_len--;
+}
+
+void field_location_stack_pop_n_elem(struct field_location_ctx *ctx,
+                                    unsigned int number_to_pop)
+{
+       unsigned int i;
+
+       for (i = 0; i < number_to_pop; i++) {
+               field_location_stack_pop(ctx);
+       }
+}
+
+struct field_location_ctx *field_location_ctx_create(void)
+{
+       struct field_location_ctx *ctx;
+
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+       if (!ctx)
+               return NULL;
+
+       INIT_LIST_HEAD(&ctx->field_location_stack);
+
+       return ctx;
+}
+
+void field_location_ctx_destroy(struct field_location_ctx *ctx)
+{
+       struct field_location_stack_node *node, *tmp;
+
+       if (!ctx) {
+               return;
+       }
+
+       list_for_each_entry_safe (node, tmp, &ctx->field_location_stack, node) {
+               kfree(node);
+       }
+
+       kfree(ctx);
+}
diff --git a/src/field-path-resolving.h b/src/field-path-resolving.h
new file mode 100644 (file)
index 0000000..75f64e2
--- /dev/null
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: (GPL-2.0-only or LGPL-2.1-only)
+ *
+ * src/field-path-resolving.h
+ *
+ * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (C) 2021 Francis Deslauriers <francis.deslauriers@efficios.com>
+ */
+
+#ifndef LTTNG_FIELD_PATH_RESOLVING_H
+#define LTTNG_FIELD_PATH_RESOLVING_H
+
+#include <wrapper/list.h>
+
+enum field_location_stack_node_type {
+       SCOPE_STACK_NODE_TYPE_FIELD,
+       SCOPE_STACK_NODE_TYPE_SCOPE,
+};
+
+struct field_location_stack_node {
+       struct list_head node;
+       enum field_location_stack_node_type type;
+       const char *field_name;
+       const struct lttng_kernel_event_field *field;
+};
+
+struct field_location_ctx {
+       struct list_head field_location_stack;
+       unsigned int field_location_stack_len;
+};
+
+struct field_path_node {
+       struct list_head node;
+       const char *name;
+       const struct lttng_kernel_event_field *field;
+};
+
+struct field_path {
+       unsigned int path_entry_count;
+       struct list_head path;
+};
+
+struct field_path *field_path_resolve(struct field_location_ctx *ctx,
+                                     const char *target_field_name);
+
+void field_path_destroy(struct field_path *fp);
+
+struct field_location_ctx *field_location_ctx_create(void);
+
+void field_location_ctx_destroy(struct field_location_ctx *ctx);
+
+int field_location_stack_push(struct field_location_ctx *ctx,
+                             enum field_location_stack_node_type type,
+                             const char *field_name,
+                             const struct lttng_kernel_event_field *field);
+
+void field_location_stack_pop_n_elem(struct field_location_ctx *ctx,
+                                    unsigned int number);
+
+#endif /* LTTNG_FIELD_PATH_RESOLVING_H */
This page took 0.034891 seconds and 5 git commands to generate.