1 // SPDX-License-Identifier: GPL-2.0
2 #include <internal/lib.h>
3 #include <subcmd/parse-options.h>
4 #include <api/fd/array.h>
5 #include <linux/zalloc.h>
6 #include <linux/string.h>
7 #include <linux/limits.h>
8 #include <linux/string.h>
16 #include <sys/inotify.h>
18 #include <sys/types.h>
19 #include <sys/socket.h>
22 #include <sys/signalfd.h>
32 #define SESSION_OUTPUT "output"
37 * OK - session is up and running
38 * RECONFIG - session is pending for reconfiguration,
39 * new values are already loaded in session object
40 * KILL - session is pending to be killed
42 * Session object life and its state is maintained by
43 * following functions:
46 * - reads config file and setup session objects
47 * with following states:
49 * OK - no change needed
50 * RECONFIG - session needs to be changed
51 * (run variable changed)
52 * KILL - session needs to be killed
53 * (session is no longer in config file)
56 * - scans session objects and does following actions
60 * RECONFIG - session is killed and re-run with new config
61 * KILL - session is killed
63 * - all sessions have OK state on the function exit
65 enum daemon_session_state {
71 struct daemon_session {
76 struct list_head list;
77 enum daemon_session_state state;
85 const char *base_user;
87 struct list_head sessions;
93 static struct daemon __daemon = {
94 .sessions = LIST_HEAD_INIT(__daemon.sessions),
97 static const char * const daemon_usage[] = {
98 "perf daemon start [<options>]",
99 "perf daemon [<options>]",
105 static void sig_handler(int sig __maybe_unused)
110 static struct daemon_session *daemon__add_session(struct daemon *config, char *name)
112 struct daemon_session *session = zalloc(sizeof(*session));
117 session->name = strdup(name);
118 if (!session->name) {
124 list_add_tail(&session->list, &config->sessions);
128 static struct daemon_session *daemon__find_session(struct daemon *daemon, char *name)
130 struct daemon_session *session;
132 list_for_each_entry(session, &daemon->sessions, list) {
133 if (!strcmp(session->name, name))
140 static int get_session_name(const char *var, char *session, int len)
142 const char *p = var + sizeof("session-") - 1;
144 while (*p != '.' && *p != 0x0 && len--)
148 return *p == '.' ? 0 : -EINVAL;
151 static int session_config(struct daemon *daemon, const char *var, const char *value)
153 struct daemon_session *session;
156 if (get_session_name(var, name, sizeof(name)))
159 var = strchr(var, '.');
165 session = daemon__find_session(daemon, name);
168 /* New session is defined. */
169 session = daemon__add_session(daemon, name);
173 pr_debug("reconfig: found new session %s\n", name);
175 /* Trigger reconfig to start it. */
176 session->state = RECONFIG;
177 } else if (session->state == KILL) {
178 /* Current session is defined, no action needed. */
179 pr_debug("reconfig: found current session %s\n", name);
183 if (!strcmp(var, "run")) {
187 same = !strcmp(session->run, value);
192 pr_debug("reconfig: session %s is changed\n", name);
195 session->run = strdup(value);
200 * Either new or changed run value is defined,
201 * trigger reconfig for the session.
203 session->state = RECONFIG;
210 static int server_config(const char *var, const char *value, void *cb)
212 struct daemon *daemon = cb;
214 if (strstarts(var, "session-")) {
215 return session_config(daemon, var, value);
216 } else if (!strcmp(var, "daemon.base") && !daemon->base_user) {
217 if (daemon->base && strcmp(daemon->base, value)) {
218 pr_err("failed: can't redefine base, bailing out\n");
221 daemon->base = strdup(value);
229 static int client_config(const char *var, const char *value, void *cb)
231 struct daemon *daemon = cb;
233 if (!strcmp(var, "daemon.base") && !daemon->base_user) {
234 daemon->base = strdup(value);
242 static int check_base(struct daemon *daemon)
247 pr_err("failed: base not defined\n");
251 if (stat(daemon->base, &st)) {
254 pr_err("failed: permission denied for '%s' base\n",
258 pr_err("failed: base '%s' does not exists\n",
262 pr_err("failed: can't access base '%s': %s\n",
263 daemon->base, strerror(errno));
268 if ((st.st_mode & S_IFMT) != S_IFDIR) {
269 pr_err("failed: base '%s' is not directory\n",
277 static int setup_client_config(struct daemon *daemon)
279 struct perf_config_set *set = perf_config_set__load_file(daemon->config_real);
283 err = perf_config_set(set, client_config, daemon);
284 perf_config_set__delete(set);
287 return err ?: check_base(daemon);
290 static int setup_server_config(struct daemon *daemon)
292 struct perf_config_set *set;
293 struct daemon_session *session;
296 pr_debug("reconfig: started\n");
299 * Mark all sessions for kill, the server config
300 * will set following states, see explanation at
301 * enum daemon_session_state declaration.
303 list_for_each_entry(session, &daemon->sessions, list)
304 session->state = KILL;
306 set = perf_config_set__load_file(daemon->config_real);
308 err = perf_config_set(set, server_config, daemon);
309 perf_config_set__delete(set);
312 return err ?: check_base(daemon);
315 static int daemon_session__run(struct daemon_session *session,
316 struct daemon *daemon)
322 if (asprintf(&session->base, "%s/session-%s",
323 daemon->base, session->name) < 0) {
324 perror("failed: asprintf");
328 if (mkdir(session->base, 0755) && errno != EEXIST) {
329 perror("failed: mkdir");
333 session->pid = fork();
334 if (session->pid < 0)
336 if (session->pid > 0) {
337 pr_info("reconfig: ruining session [%s:%d]: %s\n",
338 session->name, session->pid, session->run);
342 if (chdir(session->base)) {
343 perror("failed: chdir");
347 fd = open("/dev/null", O_RDONLY);
349 perror("failed: open /dev/null");
356 fd = open(SESSION_OUTPUT, O_RDWR|O_CREAT|O_TRUNC, 0644);
358 perror("failed: open session output");
366 scnprintf(buf, sizeof(buf), "%s record %s", daemon->perf, session->run);
368 argv = argv_split(buf, &argc);
372 exit(execve(daemon->perf, argv, NULL));
376 static pid_t handle_signalfd(struct daemon *daemon)
378 struct daemon_session *session;
379 struct signalfd_siginfo si;
384 err = read(daemon->signal_fd, &si, sizeof(struct signalfd_siginfo));
385 if (err != sizeof(struct signalfd_siginfo))
388 list_for_each_entry(session, &daemon->sessions, list) {
390 if (session->pid != (int) si.ssi_pid)
393 pid = waitpid(session->pid, &status, 0);
394 if (pid == session->pid) {
395 if (WIFEXITED(status)) {
396 pr_info("session '%s' exited, status=%d\n",
397 session->name, WEXITSTATUS(status));
398 } else if (WIFSIGNALED(status)) {
399 pr_info("session '%s' killed (signal %d)\n",
400 session->name, WTERMSIG(status));
401 } else if (WIFSTOPPED(status)) {
402 pr_info("session '%s' stopped (signal %d)\n",
403 session->name, WSTOPSIG(status));
405 pr_info("session '%s' Unexpected status (0x%x)\n",
406 session->name, status);
410 session->state = KILL;
418 static int daemon_session__wait(struct daemon_session *session, struct daemon *daemon,
421 struct pollfd pollfd = {
422 .fd = daemon->signal_fd,
425 pid_t wpid = 0, pid = session->pid;
431 int err = poll(&pollfd, 1, 1000);
434 wpid = handle_signalfd(daemon);
435 } else if (err < 0) {
436 perror("failed: poll\n");
440 if (start + secs < time(NULL))
442 } while (wpid != pid);
447 static bool daemon__has_alive_session(struct daemon *daemon)
449 struct daemon_session *session;
451 list_for_each_entry(session, &daemon->sessions, list) {
452 if (session->pid != -1)
459 static int daemon__wait(struct daemon *daemon, int secs)
461 struct pollfd pollfd = {
462 .fd = daemon->signal_fd,
470 int err = poll(&pollfd, 1, 1000);
473 handle_signalfd(daemon);
474 } else if (err < 0) {
475 perror("failed: poll\n");
479 if (start + secs < time(NULL))
481 } while (daemon__has_alive_session(daemon));
486 static int setup_server_socket(struct daemon *daemon)
488 struct sockaddr_un addr;
490 int fd = socket(AF_UNIX, SOCK_STREAM, 0);
493 fprintf(stderr, "socket: %s\n", strerror(errno));
497 if (fcntl(fd, F_SETFD, FD_CLOEXEC)) {
498 perror("failed: fcntl FD_CLOEXEC");
503 scnprintf(path, sizeof(path), "%s/control", daemon->base);
505 if (strlen(path) + 1 >= sizeof(addr.sun_path)) {
506 pr_err("failed: control path too long '%s'\n", path);
511 memset(&addr, 0, sizeof(addr));
512 addr.sun_family = AF_UNIX;
514 strlcpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);
517 if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
518 perror("failed: bind");
523 if (listen(fd, 1) == -1) {
524 perror("failed: listen");
538 #define SESSION_MAX 64
554 char name[SESSION_MAX];
558 static int cmd_session_list(struct daemon *daemon, union cmd *cmd, FILE *out)
560 char csv_sep = cmd->list.csv_sep;
561 struct daemon_session *session;
564 fprintf(out, "%d%c%s%c%s%c%s/%s",
566 getpid(), csv_sep, "daemon",
568 csv_sep, daemon->base,
570 csv_sep, daemon->base, SESSION_OUTPUT);
574 fprintf(out, "[%d:daemon] base: %s\n", getpid(), daemon->base);
575 if (cmd->list.verbose) {
576 fprintf(out, " output: %s/%s\n",
577 daemon->base, SESSION_OUTPUT);
581 list_for_each_entry(session, &daemon->sessions, list) {
583 fprintf(out, "%d%c%s%c%s",
587 csv_sep, session->name,
589 csv_sep, session->run);
591 fprintf(out, "%c%s%c%s/%s",
593 csv_sep, session->base,
595 csv_sep, session->base, SESSION_OUTPUT);
599 fprintf(out, "[%d:%s] perf record %s\n",
600 session->pid, session->name, session->run);
601 if (!cmd->list.verbose)
603 fprintf(out, " base: %s\n",
605 fprintf(out, " output: %s/%s\n",
606 session->base, SESSION_OUTPUT);
613 static int daemon_session__signal(struct daemon_session *session, int sig)
615 if (session->pid < 0)
617 return kill(session->pid, sig);
620 static int cmd_session_kill(struct daemon *daemon, union cmd *cmd, FILE *out)
622 struct daemon_session *session;
625 all = !strcmp(cmd->signal.name, "all");
627 list_for_each_entry(session, &daemon->sessions, list) {
628 if (all || !strcmp(cmd->signal.name, session->name)) {
629 daemon_session__signal(session, cmd->signal.sig);
630 fprintf(out, "signal %d sent to session '%s [%d]'\n",
631 cmd->signal.sig, session->name, session->pid);
638 static int handle_server_socket(struct daemon *daemon, int sock_fd)
644 fd = accept(sock_fd, NULL, NULL);
646 perror("failed: accept");
650 if (sizeof(cmd) != readn(fd, &cmd, sizeof(cmd))) {
651 perror("failed: read");
655 out = fdopen(fd, "w");
657 perror("failed: fdopen");
663 ret = cmd_session_list(daemon, &cmd, out);
666 ret = cmd_session_kill(daemon, &cmd, out);
674 /* If out is defined, then fd is closed via fclose. */
680 static int setup_client_socket(struct daemon *daemon)
682 struct sockaddr_un addr;
684 int fd = socket(AF_UNIX, SOCK_STREAM, 0);
687 perror("failed: socket");
691 scnprintf(path, sizeof(path), "%s/control", daemon->base);
693 if (strlen(path) + 1 >= sizeof(addr.sun_path)) {
694 pr_err("failed: control path too long '%s'\n", path);
699 memset(&addr, 0, sizeof(addr));
700 addr.sun_family = AF_UNIX;
701 strlcpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);
703 if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1) {
704 perror("failed: connect");
712 static void daemon_session__kill(struct daemon_session *session,
713 struct daemon *daemon)
715 daemon_session__signal(session, SIGTERM);
716 if (daemon_session__wait(session, daemon, 10)) {
717 daemon_session__signal(session, SIGKILL);
718 daemon_session__wait(session, daemon, 10);
722 static void daemon__signal(struct daemon *daemon, int sig)
724 struct daemon_session *session;
726 list_for_each_entry(session, &daemon->sessions, list)
727 daemon_session__signal(session, sig);
730 static void daemon_session__delete(struct daemon_session *session)
738 static void daemon_session__remove(struct daemon_session *session)
740 list_del(&session->list);
741 daemon_session__delete(session);
744 static void daemon__kill(struct daemon *daemon)
746 daemon__signal(daemon, SIGTERM);
747 if (daemon__wait(daemon, 10)) {
748 daemon__signal(daemon, SIGKILL);
749 daemon__wait(daemon, 10);
753 static void daemon__exit(struct daemon *daemon)
755 struct daemon_session *session, *h;
757 list_for_each_entry_safe(session, h, &daemon->sessions, list)
758 daemon_session__remove(session);
760 free(daemon->config_real);
761 free(daemon->config_base);
765 static int daemon__reconfig(struct daemon *daemon)
767 struct daemon_session *session, *n;
769 list_for_each_entry_safe(session, n, &daemon->sessions, list) {
771 if (session->state == OK)
774 /* Remove session. */
775 if (session->state == KILL) {
776 if (session->pid > 0) {
777 daemon_session__kill(session, daemon);
778 pr_info("reconfig: session '%s' killed\n", session->name);
780 daemon_session__remove(session);
784 /* Reconfig session. */
785 if (session->pid > 0) {
786 daemon_session__kill(session, daemon);
787 pr_info("reconfig: session '%s' killed\n", session->name);
789 if (daemon_session__run(session, daemon))
798 static int setup_config_changes(struct daemon *daemon)
800 char *basen = strdup(daemon->config_real);
801 char *dirn = strdup(daemon->config_real);
808 fd = inotify_init1(IN_NONBLOCK|O_CLOEXEC);
810 perror("failed: inotify_init");
815 base = basename(basen);
816 pr_debug("config file: %s, dir: %s\n", base, dir);
818 wd = inotify_add_watch(fd, dir, IN_CLOSE_WRITE);
820 daemon->config_base = strdup(base);
821 if (!daemon->config_base) {
826 perror("failed: inotify_add_watch");
832 return wd < 0 ? -1 : fd;
835 static bool process_inotify_event(struct daemon *daemon, char *buf, ssize_t len)
839 while (p < (buf + len)) {
840 struct inotify_event *event = (struct inotify_event *) p;
843 * We monitor config directory, check if our
844 * config file was changes.
846 if ((event->mask & IN_CLOSE_WRITE) &&
847 !(event->mask & IN_ISDIR)) {
848 if (!strcmp(event->name, daemon->config_base))
851 p += sizeof(*event) + event->len;
856 static int handle_config_changes(struct daemon *daemon, int conf_fd,
857 bool *config_changed)
862 while (!(*config_changed)) {
863 len = read(conf_fd, buf, sizeof(buf));
865 if (errno != EAGAIN) {
866 perror("failed: read");
871 *config_changed = process_inotify_event(daemon, buf, len);
876 static int setup_config(struct daemon *daemon)
878 if (daemon->base_user) {
879 daemon->base = strdup(daemon->base_user);
884 if (daemon->config) {
885 char *real = realpath(daemon->config, NULL);
888 perror("failed: realpath");
891 daemon->config_real = real;
895 if (perf_config_system() && !access(perf_etc_perfconfig(), R_OK))
896 daemon->config_real = strdup(perf_etc_perfconfig());
897 else if (perf_config_global() && perf_home_perfconfig())
898 daemon->config_real = strdup(perf_home_perfconfig());
900 return daemon->config_real ? 0 : -1;
903 static int go_background(struct daemon *daemon)
919 if (chdir(daemon->base)) {
920 perror("failed: chdir");
924 fd = open("output", O_RDWR|O_CREAT|O_TRUNC, 0644);
926 perror("failed: open");
930 if (fcntl(fd, F_SETFD, FD_CLOEXEC)) {
931 perror("failed: fcntl FD_CLOEXEC");
941 daemon->out = fdopen(1, "w");
948 setbuf(daemon->out, NULL);
952 static int setup_signalfd(struct daemon *daemon)
957 sigaddset(&mask, SIGCHLD);
959 if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
962 daemon->signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC);
963 return daemon->signal_fd;
966 static int __cmd_start(struct daemon *daemon, struct option parent_options[],
967 int argc, const char **argv)
969 bool foreground = false;
970 struct option start_options[] = {
971 OPT_BOOLEAN('f', "foreground", &foreground, "stay on console"),
972 OPT_PARENT(parent_options),
975 int sock_fd = -1, conf_fd = -1, signal_fd = -1;
976 int sock_pos, file_pos, signal_pos;
980 argc = parse_options(argc, argv, start_options, daemon_usage, 0);
982 usage_with_options(daemon_usage, start_options);
984 if (setup_config(daemon)) {
985 pr_err("failed: config not found\n");
989 if (setup_server_config(daemon))
993 err = go_background(daemon);
995 /* original process, exit normally */
998 daemon__exit(daemon);
1003 debug_set_file(daemon->out);
1004 debug_set_display_time(true);
1006 pr_info("daemon started (pid %d)\n", getpid());
1008 fdarray__init(&fda, 3);
1010 sock_fd = setup_server_socket(daemon);
1014 conf_fd = setup_config_changes(daemon);
1018 signal_fd = setup_signalfd(daemon);
1022 sock_pos = fdarray__add(&fda, sock_fd, POLLIN|POLLERR|POLLHUP, 0);
1026 file_pos = fdarray__add(&fda, conf_fd, POLLIN|POLLERR|POLLHUP, 0);
1030 signal_pos = fdarray__add(&fda, signal_fd, POLLIN|POLLERR|POLLHUP, 0);
1034 signal(SIGINT, sig_handler);
1035 signal(SIGTERM, sig_handler);
1037 while (!done && !err) {
1038 err = daemon__reconfig(daemon);
1040 if (!err && fdarray__poll(&fda, -1)) {
1041 bool reconfig = false;
1043 if (fda.entries[sock_pos].revents & POLLIN)
1044 err = handle_server_socket(daemon, sock_fd);
1045 if (fda.entries[file_pos].revents & POLLIN)
1046 err = handle_config_changes(daemon, conf_fd, &reconfig);
1047 if (fda.entries[signal_pos].revents & POLLIN)
1048 err = handle_signalfd(daemon) < 0;
1051 err = setup_server_config(daemon);
1056 fdarray__exit(&fda);
1058 daemon__kill(daemon);
1059 daemon__exit(daemon);
1068 pr_info("daemon exited\n");
1069 fclose(daemon->out);
1073 static int send_cmd(struct daemon *daemon, union cmd *cmd)
1081 if (setup_client_config(daemon))
1084 fd = setup_client_socket(daemon);
1088 if (sizeof(*cmd) != writen(fd, cmd, sizeof(*cmd))) {
1089 perror("failed: write");
1093 in = fdopen(fd, "r");
1095 perror("failed: fdopen");
1099 while ((nread = getline(&line, &len, in)) != -1) {
1100 if (fwrite(line, nread, 1, stdout) != 1)
1110 /* If in is defined, then fd is closed via fclose. */
1116 static int send_cmd_list(struct daemon *daemon)
1118 union cmd cmd = { .cmd = CMD_LIST, };
1120 cmd.list.verbose = verbose;
1121 cmd.list.csv_sep = daemon->csv_sep ? *daemon->csv_sep : 0;
1123 return send_cmd(daemon, &cmd);
1126 static int __cmd_signal(struct daemon *daemon, struct option parent_options[],
1127 int argc, const char **argv)
1129 const char *name = "all";
1130 struct option start_options[] = {
1131 OPT_STRING(0, "session", &name, "session",
1132 "Sent signal to specific session"),
1133 OPT_PARENT(parent_options),
1138 argc = parse_options(argc, argv, start_options, daemon_usage, 0);
1140 usage_with_options(daemon_usage, start_options);
1142 if (setup_config(daemon)) {
1143 pr_err("failed: config not found\n");
1147 cmd.signal.cmd = CMD_SIGNAL,
1148 cmd.signal.sig = SIGUSR2;
1149 strncpy(cmd.signal.name, name, sizeof(cmd.signal.name) - 1);
1151 return send_cmd(daemon, &cmd);
1154 int cmd_daemon(int argc, const char **argv)
1156 struct option daemon_options[] = {
1157 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
1158 OPT_STRING(0, "config", &__daemon.config,
1159 "config file", "config file path"),
1160 OPT_STRING(0, "base", &__daemon.base_user,
1161 "directory", "base directory"),
1162 OPT_STRING_OPTARG('x', "field-separator", &__daemon.csv_sep,
1163 "field separator", "print counts with custom separator", ","),
1167 perf_exe(__daemon.perf, sizeof(__daemon.perf));
1168 __daemon.out = stdout;
1170 argc = parse_options(argc, argv, daemon_options, daemon_usage,
1171 PARSE_OPT_STOP_AT_NON_OPTION);
1174 if (!strcmp(argv[0], "start"))
1175 return __cmd_start(&__daemon, daemon_options, argc, argv);
1176 if (!strcmp(argv[0], "signal"))
1177 return __cmd_signal(&__daemon, daemon_options, argc, argv);
1179 pr_err("failed: unknown command '%s'\n", argv[0]);
1183 if (setup_config(&__daemon)) {
1184 pr_err("failed: config not found\n");
1188 return send_cmd_list(&__daemon);