| // SPDX-License-Identifier: GPL-2.0 |
| /* |
| * Copyright (C) 2022 Google Inc, Steven Rostedt <rostedt@goodmis.org> |
| */ |
| #include "ktrace.h" |
| |
| static int enable_tracing(struct ccli *ccli, void *data, |
| int argc, char **argv) |
| { |
| ccli_printf(ccli, "# echo 1 > %s/tracing_on\n", tracefs_tracing_dir()); |
| return 0; |
| } |
| |
| static int disable_tracing(struct ccli *ccli, void *data, |
| int argc, char **argv) |
| { |
| ccli_printf(ccli, "# echo 0 > %s/tracing_on\n", tracefs_tracing_dir()); |
| return 0; |
| } |
| |
| static char *get_event(struct ccli *ccli, void *data, char *ename) |
| { |
| struct tep_handle *tep = data; |
| struct tep_event *event; |
| char *file; |
| char *sav; |
| int ret; |
| |
| if (strcmp(ename, "all") == 0) |
| return tracefs_instance_get_file(NULL, "events/enable"); |
| |
| sav = strchr(ename, '/'); |
| |
| /* Get the systme if no '/' or nothing after it */ |
| if (!sav || !sav[1]) { |
| if (sav) |
| *sav = '\0'; |
| ret = asprintf(&sav, "events/%s/enable", ename); |
| if (ret < 0) |
| return NULL; |
| printf("sav='%s'\n", sav); |
| if (!tracefs_file_exists(NULL, sav)) { |
| free(sav); |
| ccli_printf(ccli, "# System '%s' not found\n", ename); |
| return NULL; |
| } |
| file = tracefs_instance_get_file(NULL, sav); |
| free(sav); |
| return file; |
| } |
| |
| sav = strdup(ename); |
| /* Failure above will just print "(nul)" below */ |
| |
| event = find_event(tep, ename); |
| if (!event) { |
| ccli_printf(ccli, "# Event '%s' not found\n", sav); |
| return 0; |
| } |
| free(sav); |
| |
| return tracefs_event_get_file(NULL, event->system, event->name, "enable"); |
| } |
| |
| static int enable_event(struct ccli *ccli, void *data, |
| int argc, char **argv) |
| { |
| char *file; |
| |
| if (argc < 1) |
| return ktrace_help(ccli, "enable", "event"); |
| |
| file = get_event(ccli, data, argv[0]); |
| if (file) |
| ccli_printf(ccli, "# echo 1 > %s\n", file); |
| tracefs_put_tracing_file(file); |
| return 0; |
| } |
| |
| static int disable_event(struct ccli *ccli, void *data, |
| int argc, char **argv) |
| { |
| char *file; |
| |
| if (argc < 1) |
| return ktrace_help(ccli, "disable", "event"); |
| |
| file = get_event(ccli, data, argv[0]); |
| if (file) |
| ccli_printf(ccli, "# echo 0 > %s\n", file); |
| tracefs_put_tracing_file(file); |
| return 0; |
| } |
| |
| int cmd_enable(struct ccli *ccli, const char *command, const char *line, |
| void *data, int argc, char **argv) |
| { |
| if (argc < 2) |
| return ktrace_help(ccli, "enable", NULL); |
| |
| if (strcmp(argv[1], "tracing") == 0) |
| return enable_tracing(ccli, data, argc - 2, argv + 2); |
| |
| if (strcmp(argv[1], "event") == 0) |
| return enable_event(ccli, data, argc - 2, argv + 2); |
| |
| return ktrace_help(ccli, "enable", NULL); |
| } |
| |
| int cmd_disable(struct ccli *ccli, const char *command, const char *line, |
| void *data, int argc, char **argv) |
| { |
| if (argc < 2) |
| return ktrace_help(ccli, "disable", NULL); |
| |
| if (strcmp(argv[1], "tracing") == 0) |
| return disable_tracing(ccli, data, argc - 2, argv + 2); |
| |
| if (strcmp(argv[1], "event") == 0) |
| return disable_event(ccli, data, argc - 2, argv + 2); |
| |
| return ktrace_help(ccli, "disable", NULL); |
| } |
| |
| static int disenable_event_completion(struct ccli *ccli, void *data, |
| int argc, char **argv, |
| char ***list, int word, char *match) |
| { |
| struct tep_handle *tep = data; |
| int cnt = 0; |
| int ret = 0; |
| |
| if (word == 0) { |
| ret = ccli_list_add(ccli, list, &cnt, "all"); |
| /* Do not add '/' for 'all' */ |
| if (ret == 1 && strcmp(match, "all") == 0) |
| return 1; |
| ret = event_completion(ccli, tep, list, &cnt, match, 0); |
| } |
| |
| if (ret < 0) |
| ccli_list_free(ccli, list, cnt); |
| |
| return ret; |
| } |
| |
| int enable_completion(struct ccli *ccli, const char *command, |
| const char *line, int word, |
| char *match, char ***list, void *data) |
| { |
| char *types[] = { "tracing", "event" }; |
| char **argv; |
| int argc; |
| int cnt = 0; |
| int ret = 0; |
| int i; |
| |
| if (word == 1) { |
| for (i = 0; ret >= 0 && i < ARRAY_SIZE(types); i++) |
| ret = ccli_list_add(ccli, list, &cnt, types[i]); |
| return ret; |
| } |
| |
| argc = ccli_line_parse(line, &argv); |
| if (argc < 0) |
| return 0; |
| |
| if (strcmp(argv[1], "event") == 0) |
| ret = disenable_event_completion(ccli, data, argc - 2, argv + 2, |
| list, word - 2, match); |
| |
| ccli_argv_free(argv); |
| |
| return ret; |
| } |
| |
| |
| int disable_completion(struct ccli *ccli, const char *command, |
| const char *line, int word, |
| char *match, char ***list, void *data) |
| { |
| char *types[] = { "tracing", "event" }; |
| char **argv; |
| int argc; |
| int cnt = 0; |
| int ret = 0; |
| int i; |
| |
| if (word == 1) { |
| for (i = 0; ret >= 0 && i < ARRAY_SIZE(types); i++) |
| ret = ccli_list_add(ccli, list, &cnt, types[i]); |
| return ret; |
| } |
| |
| argc = ccli_line_parse(line, &argv); |
| if (argc < 0) |
| return 0; |
| |
| if (strcmp(argv[1], "event") == 0) |
| ret = disenable_event_completion(ccli, data, argc - 2, argv + 2, |
| list, word - 2, match); |
| |
| ccli_argv_free(argv); |
| |
| return ret; |
| } |