The newly introduced set of APIs tracefs_dynevent_...() can be used to manage kprobes. These legacy APIs are removed as redundant: tracefs_kprobe_clear_all(); tracefs_kprobe_clear_probe(); tracefs_get_kprobes() There is one functionality, missing in the new clear API - clearing all dynamic events from specific system only. If this is needed, tracefs_dynevent_destroy() can be extended with that use case. Signed-off-by: Tzvetomir Stoyanov (VMware) <tz.stoyanov@xxxxxxxxx> --- include/tracefs.h | 3 - src/tracefs-kprobes.c | 247 ------------------------------------------ 2 files changed, 250 deletions(-) diff --git a/include/tracefs.h b/include/tracefs.h index b8f7c09..6bf45c3 100644 --- a/include/tracefs.h +++ b/include/tracefs.h @@ -276,11 +276,8 @@ 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_get_kprobes(enum tracefs_kprobe_type type); enum tracefs_kprobe_type tracefs_kprobe_info(const char *group, const char *event, char **type, char **addr, char **format); -int tracefs_kprobe_clear_all(bool force); -int tracefs_kprobe_clear_probe(const char *system, const char *event, bool force); enum tracefs_hist_key_type { TRACEFS_HIST_KEY_NORMAL = 0, diff --git a/src/tracefs-kprobes.c b/src/tracefs-kprobes.c index d1279ff..72a4a35 100644 --- a/src/tracefs-kprobes.c +++ b/src/tracefs-kprobes.c @@ -262,80 +262,6 @@ static int parse_kprobe(char *content, char **saveptr, return 0; } -/** - * tracefs_get_kprobes - return a list kprobes (by group/event name) - * @type: The type of kprobes to return. - * - * If @type is TRACEFS_ALL_KPROBES all kprobes in the kprobe_events - * 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. - */ -char **tracefs_get_kprobes(enum tracefs_kprobe_type type) -{ - 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(); - } - - 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 (!list) - list = trace_list_create_empty(); - out: - free(content); - return list; - fail: - tracefs_list_free(list); - list = NULL; - goto out; -} - /** * tracefs_kprobe_info - return the type of kprobe specified. * @group: The group the kprobe is in (NULL for the default "kprobes") @@ -406,176 +332,3 @@ enum tracefs_kprobe_type tracefs_kprobe_info(const char *group, const char *even free(content); return rtype; } - -static void disable_events(const char *system, const char *event, - char **list) -{ - struct tracefs_instance *instance; - int i; - - /* - * Note, this will not fail even on error. - * That is because even if something fails, it may still - * work enough to clear the kprobes. If that's the case - * the clearing after the loop will succeed and the function - * is a success, even though other parts had failed. If - * one of the kprobe events is enabled in one of the - * instances that fail, then the clearing will fail too - * and the function will return an error. - */ - - tracefs_event_disable(NULL, system, event); - /* No need to test results */ - - if (!list) - return; - - for (i = 0; list[i]; i++) { - instance = tracefs_instance_alloc(NULL, list[i]); - /* If this fails, try the next one */ - if (!instance) - continue; - tracefs_event_disable(instance, system, event); - tracefs_instance_free(instance); - } - 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) -{ - char **instance_list; - char **kprobe_list; - char *saveptr; - char *system; - char *kprobe; - char *event; - int ret; - int i; - - kprobe_list = tracefs_get_kprobes(TRACEFS_ALL_KPROBES); - if (!kprobe_list) - return -1; - - instance_list = tracefs_instances(NULL); - /* - * Even if the above failed and instance_list is NULL, - * keep going, as the enabled event may simply be in the - * top level. - */ - - /* - * If a system is defined, the default is to pass unless - * an event fails to be removed. If a system is not defined, - * the default is to fail, unless all are removed. - */ - 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; - - /* Skip if this does not match a given system */ - if (group && strcmp(system, group) != 0) - continue; - - if (force) - disable_events(system, event, instance_list); - - if (group) { - ret = clear_kprobe(system, event); - if (ret < 0) - goto out; - } else { - ret = tracefs_instance_file_clear(NULL, KPROBE_EVENTS); - /* On success stop the loop */ - if (!ret) - goto out; - } - - /* Set the default for whether a system is defined or not */ - ret = group ? 0 : -1; - } - out: - tracefs_list_free(instance_list); - tracefs_list_free(kprobe_list); - return ret; -} - -/** - * tracefs_kprobe_clear_all - clear kprobe events - * @force: Will attempt to disable all kprobe events and clear them - * - * Will remove all defined kprobe events. If any of them are enabled, - * and @force is not set, then it will error with -1 and errno to be - * EBUSY. If @force is set, then it will attempt to disable all the kprobe - * events in all instances, and try again. - * - * Returns zero on success, -1 otherwise. - */ -int tracefs_kprobe_clear_all(bool force) -{ - if (tracefs_instance_file_clear(NULL, KPROBE_EVENTS) == 0) - return 0; - - if (!force) - return -1; - - /* Attempt to disable all kprobe events */ - return kprobe_clear_probes(NULL, force); -} - -/** - * tracefs_kprobe_clear_all - clear kprobe events - * @system: System to clear (NULL means default) - * @event: Name of probe to clear in system (NULL for all probes in system) - * @force: Will attempt to disable all kprobe events and clear them - * - * Will remove the kprobes that match the @system and @event. If @system - * is NULL, then "kprobes" is used and will ignore all other system - * groups of kprobes. The @event is NULL then all events under the given - * @system are removed, otherwise only the event that matches. - * - * Returns zero on success, -1 otherwise. - */ -int tracefs_kprobe_clear_probe(const char *system, const char *event, bool force) -{ - char **instance_list; - int ret; - - if (!system) - system = "kprobes"; - - if (!event) - return kprobe_clear_probes(system, force); - - /* - * Since we know we are disabling a specific event, try - * to disable it first before clearing it. - */ - if (force) { - instance_list = tracefs_instances(NULL); - disable_events(system, event, instance_list); - tracefs_list_free(instance_list); - } - - ret = clear_kprobe(system, event); - - return ret < 0 ? -1 : 0; -} -- 2.31.1