diff mbox series

[05/12] libtracefs: Reimplement tracefs_kprobes_get API

Message ID 20211028120907.101847-6-tz.stoyanov@gmail.com (mailing list archive)
State Superseded
Headers show
Series libtracefs dynamic events support | expand

Commit Message

Tzvetomir Stoyanov (VMware) Oct. 28, 2021, 12:09 p.m. UTC
In order to unify the code and reuse the internal helpers for dynamic
events helpers, the tracefs_kprobes_get() API is reimplemented using
the new dynamic events APIs.

Signed-off-by: Tzvetomir Stoyanov (VMware) <tz.stoyanov@gmail.com>
---
 include/tracefs.h     |   2 +-
 src/tracefs-kprobes.c | 127 +++++++++++-------------------------------
 2 files changed, 33 insertions(+), 96 deletions(-)

Comments

Steven Rostedt Oct. 29, 2021, 3:01 a.m. UTC | #1
On Thu, 28 Oct 2021 15:09:00 +0300
"Tzvetomir Stoyanov (VMware)" <tz.stoyanov@gmail.com> wrote:

> In order to unify the code and reuse the internal helpers for dynamic
> events helpers, the tracefs_kprobes_get() API is reimplemented using
> the new dynamic events APIs.
> 
> Signed-off-by: Tzvetomir Stoyanov (VMware) <tz.stoyanov@gmail.com>
> ---
>  include/tracefs.h     |   2 +-
>  src/tracefs-kprobes.c | 127 +++++++++++-------------------------------
>  2 files changed, 33 insertions(+), 96 deletions(-)
> 
> diff --git a/include/tracefs.h b/include/tracefs.h
> index c7b9179..d4ac8fb 100644
> --- a/include/tracefs.h
> +++ b/include/tracefs.h
> @@ -259,7 +259,7 @@ int tracefs_kprobe_raw(const char *system, const char *event,
>  		       const char *addr, const char *format);
>  int tracefs_kretprobe_raw(const char *system, const char *event,
>  			  const char *addr, const char *format);
> -char **tracefs_kprobes_get(enum tracefs_kprobe_type type);
> +int tracefs_kprobes_get(enum tracefs_kprobe_type type, struct tracefs_dynevent ***kprobes);

Like I mentioned for the other patches. This should return the array,
and not be passing in an object to allocate.

General rule is, if you need to have a parameter with three
dereferences (***) you're doing it wrong. ;-)

>  enum tracefs_kprobe_type tracefs_kprobe_info(const char *group, const char *event,
>  					     char **type, char **addr, char **format);
>  
> diff --git a/src/tracefs-kprobes.c b/src/tracefs-kprobes.c


-- Steve
diff mbox series

Patch

diff --git a/include/tracefs.h b/include/tracefs.h
index c7b9179..d4ac8fb 100644
--- a/include/tracefs.h
+++ b/include/tracefs.h
@@ -259,7 +259,7 @@  int tracefs_kprobe_raw(const char *system, const char *event,
 		       const char *addr, const char *format);
 int tracefs_kretprobe_raw(const char *system, const char *event,
 			  const char *addr, const char *format);
-char **tracefs_kprobes_get(enum tracefs_kprobe_type type);
+int tracefs_kprobes_get(enum tracefs_kprobe_type type, struct tracefs_dynevent ***kprobes);
 enum tracefs_kprobe_type tracefs_kprobe_info(const char *group, const char *event,
 					     char **type, char **addr, char **format);
 
diff --git a/src/tracefs-kprobes.c b/src/tracefs-kprobes.c
index 1e08b75..2e24051 100644
--- a/src/tracefs-kprobes.c
+++ b/src/tracefs-kprobes.c
@@ -287,77 +287,32 @@  static int parse_kprobe(char *content, char **saveptr,
 }
 
 /**
- * tracefs_kprobes_get - return a list kprobes (by group/event name)
+ * tracefs_kprobes_get - return an array of pointers to kprobes
  * @type: The type of kprobes to return.
+ * @kprobes: return, array of pointers to kprobes
  *
- * If @type is TRACEFS_ALL_KPROBES all kprobes in the kprobe_events
- * are returned. Otherwise if it is TRACEFS_KPROBE, then only
+ * If @type is TRACEFS_ALL_KPROBES all kprobes in the system are returned.
+ * Otherwise if it is TRACEFS_KPROBE, then only
  * normal kprobes (p:) are returned, or if type is TRACEFS_KRETPROBE
  * then only kretprobes (r:) are returned.
  *
- * Returns a list of strings that contain the kprobes that exist
- * in the kprobe_events files. The strings returned are in the
- * "group/event" format.
- * The list must be freed with tracefs_list_free().
- * If there are no kprobes, a list is still returned, but it contains
- * only a NULL pointer.
- * On error, NULL is returned.
+ * In case of an error, -1 is returned and @kprobes is not modified.
+ * In case of success, the count of requested kprobes is returned. An array of
+ * pointers to kprobes is allocated and returned in @kprobes. The size of this array
+ * is the returned count + 1, as the last element is a NULL pointer. The array must be
+ * freed with tracefs_dynevent_list_free().
+ * The @kprobes parameter is optional. If NULL is passed, only the count of the kprobes is returned.
  */
-char **tracefs_kprobes_get(enum tracefs_kprobe_type type)
+int tracefs_kprobes_get(enum tracefs_kprobe_type type, struct tracefs_dynevent ***kprobes)
 {
-	char **list = NULL;
-	char *content;
-	char *saveptr;
-	char *event;
-	char *ktype;
-	int ret;
-
-	errno = 0;
-	content = tracefs_instance_file_read(NULL, KPROBE_EVENTS, NULL);
-	if (!content) {
-		if (errno)
-			return NULL;
-		/* content is NULL on empty file, return an empty list */
-		return trace_list_create_empty();
-	}
+	unsigned long mask = 0;
 
-	ret = parse_kprobe(content, &saveptr, &ktype, NULL, &event, NULL, NULL);
-
-	while (!ret) {
-		char **tmp;
-
-		if (type != TRACEFS_ALL_KPROBES) {
-			switch (*ktype) {
-			case 'p':
-				if (type != TRACEFS_KPROBE)
-					goto next;
-				break;
-			case 'r':
-				if (type != TRACEFS_KRETPROBE)
-					goto next;
-				break;
-			default:
-				goto next;
-			}
-		}
-
-		tmp = tracefs_list_add(list, event);
-		if (!tmp)
-			goto fail;
-		list = tmp;
- next:
-		ret = parse_kprobe(NULL, &saveptr, &ktype, NULL, &event, NULL, NULL);
-	}
+	if (type == TRACEFS_KPROBE || type == TRACEFS_ALL_KPROBES)
+		DYNEVENT_ADD_BIT(mask, TRACE_DYNEVENT_KPROBE);
+	if (type == TRACEFS_KRETPROBE || type == TRACEFS_ALL_KPROBES)
+		DYNEVENT_ADD_BIT(mask, TRACE_DYNEVENT_KRETPROBE);
 
-	if (!list)
-		list = trace_list_create_empty();
- out:
-	free(content);
-	return list;
- fail:
-	tracefs_list_free(list);
-	list = NULL;
-	goto out;
+	return dynevent_get_all(mask, NULL, kprobes);
 }
 
 /**
@@ -465,30 +420,17 @@  static void disable_events(const char *system, const char *event,
 	return;
 }
 
-static int clear_kprobe(const char *system, const char *event)
-{
-	/* '-' + ':' + '/' + '\n' + '\0' = 5 bytes */
-	int len = strlen(system) + strlen(event) + 5;
-	char content[len];
-
-	sprintf(content, "-:%s/%s", system, event);
-	return tracefs_instance_file_append(NULL, KPROBE_EVENTS, content);
-}
-
 static int kprobe_clear_probes(const char *group, bool force)
 {
+	struct tracefs_dynevent **kprobes;
 	char **instance_list;
-	char **kprobe_list;
-	char *saveptr;
-	char *system;
-	char *kprobe;
-	char *event;
 	int ret;
 	int i;
 
-	kprobe_list = tracefs_kprobes_get(TRACEFS_ALL_KPROBES);
-	if (!kprobe_list)
-		return -1;
+	ret = tracefs_kprobes_get(TRACEFS_ALL_KPROBES, &kprobes);
+	/* No krpobes or error getting them */
+	if (ret <= 0)
+		return ret;
 
 	instance_list = tracefs_instances(NULL);
 	/*
@@ -504,26 +446,21 @@  static int kprobe_clear_probes(const char *group, bool force)
 	 */
 	ret = group ? 0 : -1;
 
-	for (i = 0; kprobe_list[i]; i++) {
-		kprobe = kprobe_list[i];
-
-		system = strtok_r(kprobe, "/", &saveptr);
-		if (!system)
-			goto out;
-
-		event = strtok_r(NULL," ", &saveptr);
-		if (!event)
-			goto out;
+	for (i = 0; kprobes[i]; i++) {
 
 		/* Skip if this does not match a given system */
-		if (group && strcmp(system, group) != 0)
-			continue;
+		if (group) {
+			if (!kprobes[i]->system)
+				continue;
+			if (strcmp(kprobes[i]->system, group) != 0)
+				continue;
+		}
 
 		if (force)
-			disable_events(system, event, instance_list);
+			disable_events(kprobes[i]->system, kprobes[i]->event, instance_list);
 
 		if (group) {
-			ret = clear_kprobe(system, event);
+			ret = dynevent_destroy(kprobes[i]);
 			if (ret < 0)
 				goto out;
 		} else {
@@ -538,7 +475,7 @@  static int kprobe_clear_probes(const char *group, bool force)
 	}
  out:
 	tracefs_list_free(instance_list);
-	tracefs_list_free(kprobe_list);
+	tracefs_dynevent_list_free(&kprobes);
 	return ret;
 }