~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/perf/builtin-daemon.c

Version: ~ [ linux-6.4-rc3 ] ~ [ linux-6.3.4 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.30 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.113 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.180 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.243 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.283 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.315 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 <api/fs/fs.h>
  6 #include <linux/zalloc.h>
  7 #include <linux/string.h>
  8 #include <linux/limits.h>
  9 #include <string.h>
 10 #include <sys/file.h>
 11 #include <signal.h>
 12 #include <stdlib.h>
 13 #include <time.h>
 14 #include <stdio.h>
 15 #include <unistd.h>
 16 #include <errno.h>
 17 #include <sys/inotify.h>
 18 #include <libgen.h>
 19 #include <sys/types.h>
 20 #include <sys/socket.h>
 21 #include <sys/un.h>
 22 #include <sys/stat.h>
 23 #include <sys/signalfd.h>
 24 #include <sys/wait.h>
 25 #include <poll.h>
 26 #include "builtin.h"
 27 #include "perf.h"
 28 #include "debug.h"
 29 #include "config.h"
 30 #include "util.h"
 31 
 32 #define SESSION_OUTPUT  "output"
 33 #define SESSION_CONTROL "control"
 34 #define SESSION_ACK     "ack"
 35 
 36 /*
 37  * Session states:
 38  *
 39  *   OK       - session is up and running
 40  *   RECONFIG - session is pending for reconfiguration,
 41  *              new values are already loaded in session object
 42  *   KILL     - session is pending to be killed
 43  *
 44  * Session object life and its state is maintained by
 45  * following functions:
 46  *
 47  *  setup_server_config
 48  *    - reads config file and setup session objects
 49  *      with following states:
 50  *
 51  *      OK       - no change needed
 52  *      RECONFIG - session needs to be changed
 53  *                 (run variable changed)
 54  *      KILL     - session needs to be killed
 55  *                 (session is no longer in config file)
 56  *
 57  *  daemon__reconfig
 58  *    - scans session objects and does following actions
 59  *      for states:
 60  *
 61  *      OK       - skip
 62  *      RECONFIG - session is killed and re-run with new config
 63  *      KILL     - session is killed
 64  *
 65  *    - all sessions have OK state on the function exit
 66  */
 67 enum daemon_session_state {
 68         OK,
 69         RECONFIG,
 70         KILL,
 71 };
 72 
 73 struct daemon_session {
 74         char                            *base;
 75         char                            *name;
 76         char                            *run;
 77         char                            *control;
 78         int                              pid;
 79         struct list_head                 list;
 80         enum daemon_session_state        state;
 81         time_t                           start;
 82 };
 83 
 84 struct daemon {
 85         const char              *config;
 86         char                    *config_real;
 87         char                    *config_base;
 88         const char              *csv_sep;
 89         const char              *base_user;
 90         char                    *base;
 91         struct list_head         sessions;
 92         FILE                    *out;
 93         char                     perf[PATH_MAX];
 94         int                      signal_fd;
 95         time_t                   start;
 96 };
 97 
 98 static struct daemon __daemon = {
 99         .sessions = LIST_HEAD_INIT(__daemon.sessions),
100 };
101 
102 static const char * const daemon_usage[] = {
103         "perf daemon start [<options>]",
104         "perf daemon [<options>]",
105         NULL
106 };
107 
108 static bool done;
109 
110 static void sig_handler(int sig __maybe_unused)
111 {
112         done = true;
113 }
114 
115 static struct daemon_session *daemon__add_session(struct daemon *config, char *name)
116 {
117         struct daemon_session *session = zalloc(sizeof(*session));
118 
119         if (!session)
120                 return NULL;
121 
122         session->name = strdup(name);
123         if (!session->name) {
124                 free(session);
125                 return NULL;
126         }
127 
128         session->pid = -1;
129         list_add_tail(&session->list, &config->sessions);
130         return session;
131 }
132 
133 static struct daemon_session *daemon__find_session(struct daemon *daemon, char *name)
134 {
135         struct daemon_session *session;
136 
137         list_for_each_entry(session, &daemon->sessions, list) {
138                 if (!strcmp(session->name, name))
139                         return session;
140         }
141 
142         return NULL;
143 }
144 
145 static int get_session_name(const char *var, char *session, int len)
146 {
147         const char *p = var + sizeof("session-") - 1;
148 
149         while (*p != '.' && *p != 0x0 && len--)
150                 *session++ = *p++;
151 
152         *session = 0;
153         return *p == '.' ? 0 : -EINVAL;
154 }
155 
156 static int session_config(struct daemon *daemon, const char *var, const char *value)
157 {
158         struct daemon_session *session;
159         char name[100];
160 
161         if (get_session_name(var, name, sizeof(name) - 1))
162                 return -EINVAL;
163 
164         var = strchr(var, '.');
165         if (!var)
166                 return -EINVAL;
167 
168         var++;
169 
170         session = daemon__find_session(daemon, name);
171 
172         if (!session) {
173                 /* New session is defined. */
174                 session = daemon__add_session(daemon, name);
175                 if (!session)
176                         return -ENOMEM;
177 
178                 pr_debug("reconfig: found new session %s\n", name);
179 
180                 /* Trigger reconfig to start it. */
181                 session->state = RECONFIG;
182         } else if (session->state == KILL) {
183                 /* Current session is defined, no action needed. */
184                 pr_debug("reconfig: found current session %s\n", name);
185                 session->state = OK;
186         }
187 
188         if (!strcmp(var, "run")) {
189                 bool same = false;
190 
191                 if (session->run)
192                         same = !strcmp(session->run, value);
193 
194                 if (!same) {
195                         if (session->run) {
196                                 free(session->run);
197                                 pr_debug("reconfig: session %s is changed\n", name);
198                         }
199 
200                         session->run = strdup(value);
201                         if (!session->run)
202                                 return -ENOMEM;
203 
204                         /*
205                          * Either new or changed run value is defined,
206                          * trigger reconfig for the session.
207                          */
208                         session->state = RECONFIG;
209                 }
210         }
211 
212         return 0;
213 }
214 
215 static int server_config(const char *var, const char *value, void *cb)
216 {
217         struct daemon *daemon = cb;
218 
219         if (strstarts(var, "session-")) {
220                 return session_config(daemon, var, value);
221         } else if (!strcmp(var, "daemon.base") && !daemon->base_user) {
222                 if (daemon->base && strcmp(daemon->base, value)) {
223                         pr_err("failed: can't redefine base, bailing out\n");
224                         return -EINVAL;
225                 }
226                 daemon->base = strdup(value);
227                 if (!daemon->base)
228                         return -ENOMEM;
229         }
230 
231         return 0;
232 }
233 
234 static int client_config(const char *var, const char *value, void *cb)
235 {
236         struct daemon *daemon = cb;
237 
238         if (!strcmp(var, "daemon.base") && !daemon->base_user) {
239                 daemon->base = strdup(value);
240                 if (!daemon->base)
241                         return -ENOMEM;
242         }
243 
244         return 0;
245 }
246 
247 static int check_base(struct daemon *daemon)
248 {
249         struct stat st;
250 
251         if (!daemon->base) {
252                 pr_err("failed: base not defined\n");
253                 return -EINVAL;
254         }
255 
256         if (stat(daemon->base, &st)) {
257                 switch (errno) {
258                 case EACCES:
259                         pr_err("failed: permission denied for '%s' base\n",
260                                daemon->base);
261                         return -EACCES;
262                 case ENOENT:
263                         pr_err("failed: base '%s' does not exists\n",
264                                daemon->base);
265                         return -EACCES;
266                 default:
267                         pr_err("failed: can't access base '%s': %s\n",
268                                daemon->base, strerror(errno));
269                         return -errno;
270                 }
271         }
272 
273         if ((st.st_mode & S_IFMT) != S_IFDIR) {
274                 pr_err("failed: base '%s' is not directory\n",
275                        daemon->base);
276                 return -EINVAL;
277         }
278 
279         return 0;
280 }
281 
282 static int setup_client_config(struct daemon *daemon)
283 {
284         struct perf_config_set *set = perf_config_set__load_file(daemon->config_real);
285         int err = -ENOMEM;
286 
287         if (set) {
288                 err = perf_config_set(set, client_config, daemon);
289                 perf_config_set__delete(set);
290         }
291 
292         return err ?: check_base(daemon);
293 }
294 
295 static int setup_server_config(struct daemon *daemon)
296 {
297         struct perf_config_set *set;
298         struct daemon_session *session;
299         int err = -ENOMEM;
300 
301         pr_debug("reconfig: started\n");
302 
303         /*
304          * Mark all sessions for kill, the server config
305          * will set following states, see explanation at
306          * enum daemon_session_state declaration.
307          */
308         list_for_each_entry(session, &daemon->sessions, list)
309                 session->state = KILL;
310 
311         set = perf_config_set__load_file(daemon->config_real);
312         if (set) {
313                 err = perf_config_set(set, server_config, daemon);
314                 perf_config_set__delete(set);
315         }
316 
317         return err ?: check_base(daemon);
318 }
319 
320 static int daemon_session__run(struct daemon_session *session,
321                                struct daemon *daemon)
322 {
323         char buf[PATH_MAX];
324         char **argv;
325         int argc, fd;
326 
327         if (asprintf(&session->base, "%s/session-%s",
328                      daemon->base, session->name) < 0) {
329                 perror("failed: asprintf");
330                 return -1;
331         }
332 
333         if (mkdir(session->base, 0755) && errno != EEXIST) {
334                 perror("failed: mkdir");
335                 return -1;
336         }
337 
338         session->start = time(NULL);
339 
340         session->pid = fork();
341         if (session->pid < 0)
342                 return -1;
343         if (session->pid > 0) {
344                 pr_info("reconfig: ruining session [%s:%d]: %s\n",
345                         session->name, session->pid, session->run);
346                 return 0;
347         }
348 
349         if (chdir(session->base)) {
350                 perror("failed: chdir");
351                 return -1;
352         }
353 
354         fd = open("/dev/null", O_RDONLY);
355         if (fd < 0) {
356                 perror("failed: open /dev/null");
357                 return -1;
358         }
359 
360         dup2(fd, 0);
361         close(fd);
362 
363         fd = open(SESSION_OUTPUT, O_RDWR|O_CREAT|O_TRUNC, 0644);
364         if (fd < 0) {
365                 perror("failed: open session output");
366                 return -1;
367         }
368 
369         dup2(fd, 1);
370         dup2(fd, 2);
371         close(fd);
372 
373         if (mkfifo(SESSION_CONTROL, 0600) && errno != EEXIST) {
374                 perror("failed: create control fifo");
375                 return -1;
376         }
377 
378         if (mkfifo(SESSION_ACK, 0600) && errno != EEXIST) {
379                 perror("failed: create ack fifo");
380                 return -1;
381         }
382 
383         scnprintf(buf, sizeof(buf), "%s record --control=fifo:%s,%s %s",
384                   daemon->perf, SESSION_CONTROL, SESSION_ACK, session->run);
385 
386         argv = argv_split(buf, &argc);
387         if (!argv)
388                 exit(-1);
389 
390         exit(execve(daemon->perf, argv, NULL));
391         return -1;
392 }
393 
394 static pid_t handle_signalfd(struct daemon *daemon)
395 {
396         struct daemon_session *session;
397         struct signalfd_siginfo si;
398         ssize_t err;
399         int status;
400         pid_t pid;
401 
402         /*
403          * Take signal fd data as pure signal notification and check all
404          * the sessions state. The reason is that multiple signals can get
405          * coalesced in kernel and we can receive only single signal even
406          * if multiple SIGCHLD were generated.
407          */
408         err = read(daemon->signal_fd, &si, sizeof(struct signalfd_siginfo));
409         if (err != sizeof(struct signalfd_siginfo)) {
410                 pr_err("failed to read signal fd\n");
411                 return -1;
412         }
413 
414         list_for_each_entry(session, &daemon->sessions, list) {
415                 if (session->pid == -1)
416                         continue;
417 
418                 pid = waitpid(session->pid, &status, WNOHANG);
419                 if (pid <= 0)
420                         continue;
421 
422                 if (WIFEXITED(status)) {
423                         pr_info("session '%s' exited, status=%d\n",
424                                 session->name, WEXITSTATUS(status));
425                 } else if (WIFSIGNALED(status)) {
426                         pr_info("session '%s' killed (signal %d)\n",
427                                 session->name, WTERMSIG(status));
428                 } else if (WIFSTOPPED(status)) {
429                         pr_info("session '%s' stopped (signal %d)\n",
430                                 session->name, WSTOPSIG(status));
431                 } else {
432                         pr_info("session '%s' Unexpected status (0x%x)\n",
433                                 session->name, status);
434                 }
435 
436                 session->state = KILL;
437                 session->pid = -1;
438         }
439 
440         return 0;
441 }
442 
443 static int daemon_session__wait(struct daemon_session *session, struct daemon *daemon,
444                                 int secs)
445 {
446         struct pollfd pollfd = {
447                 .fd     = daemon->signal_fd,
448                 .events = POLLIN,
449         };
450         time_t start;
451 
452         start = time(NULL);
453 
454         do {
455                 int err = poll(&pollfd, 1, 1000);
456 
457                 if (err > 0) {
458                         handle_signalfd(daemon);
459                 } else if (err < 0) {
460                         perror("failed: poll\n");
461                         return -1;
462                 }
463 
464                 if (start + secs < time(NULL))
465                         return -1;
466         } while (session->pid != -1);
467 
468         return 0;
469 }
470 
471 static bool daemon__has_alive_session(struct daemon *daemon)
472 {
473         struct daemon_session *session;
474 
475         list_for_each_entry(session, &daemon->sessions, list) {
476                 if (session->pid != -1)
477                         return true;
478         }
479 
480         return false;
481 }
482 
483 static int daemon__wait(struct daemon *daemon, int secs)
484 {
485         struct pollfd pollfd = {
486                 .fd     = daemon->signal_fd,
487                 .events = POLLIN,
488         };
489         time_t start;
490 
491         start = time(NULL);
492 
493         do {
494                 int err = poll(&pollfd, 1, 1000);
495 
496                 if (err > 0) {
497                         handle_signalfd(daemon);
498                 } else if (err < 0) {
499                         perror("failed: poll\n");
500                         return -1;
501                 }
502 
503                 if (start + secs < time(NULL))
504                         return -1;
505         } while (daemon__has_alive_session(daemon));
506 
507         return 0;
508 }
509 
510 static int daemon_session__control(struct daemon_session *session,
511                                    const char *msg, bool do_ack)
512 {
513         struct pollfd pollfd = { .events = POLLIN, };
514         char control_path[PATH_MAX];
515         char ack_path[PATH_MAX];
516         int control, ack = -1, len;
517         char buf[20];
518         int ret = -1;
519         ssize_t err;
520 
521         /* open the control file */
522         scnprintf(control_path, sizeof(control_path), "%s/%s",
523                   session->base, SESSION_CONTROL);
524 
525         control = open(control_path, O_WRONLY|O_NONBLOCK);
526         if (!control)
527                 return -1;
528 
529         if (do_ack) {
530                 /* open the ack file */
531                 scnprintf(ack_path, sizeof(ack_path), "%s/%s",
532                           session->base, SESSION_ACK);
533 
534                 ack = open(ack_path, O_RDONLY, O_NONBLOCK);
535                 if (!ack) {
536                         close(control);
537                         return -1;
538                 }
539         }
540 
541         /* write the command */
542         len = strlen(msg);
543 
544         err = writen(control, msg, len);
545         if (err != len) {
546                 pr_err("failed: write to control pipe: %d (%s)\n",
547                        errno, control_path);
548                 goto out;
549         }
550 
551         if (!do_ack)
552                 goto out;
553 
554         /* wait for an ack */
555         pollfd.fd = ack;
556 
557         if (!poll(&pollfd, 1, 2000)) {
558                 pr_err("failed: control ack timeout\n");
559                 goto out;
560         }
561 
562         if (!(pollfd.revents & POLLIN)) {
563                 pr_err("failed: did not received an ack\n");
564                 goto out;
565         }
566 
567         err = read(ack, buf, sizeof(buf));
568         if (err > 0)
569                 ret = strcmp(buf, "ack\n");
570         else
571                 perror("failed: read ack %d\n");
572 
573 out:
574         if (ack != -1)
575                 close(ack);
576 
577         close(control);
578         return ret;
579 }
580 
581 static int setup_server_socket(struct daemon *daemon)
582 {
583         struct sockaddr_un addr;
584         char path[PATH_MAX];
585         int fd = socket(AF_UNIX, SOCK_STREAM, 0);
586 
587         if (fd < 0) {
588                 fprintf(stderr, "socket: %s\n", strerror(errno));
589                 return -1;
590         }
591 
592         if (fcntl(fd, F_SETFD, FD_CLOEXEC)) {
593                 perror("failed: fcntl FD_CLOEXEC");
594                 close(fd);
595                 return -1;
596         }
597 
598         scnprintf(path, sizeof(path), "%s/control", daemon->base);
599 
600         if (strlen(path) + 1 >= sizeof(addr.sun_path)) {
601                 pr_err("failed: control path too long '%s'\n", path);
602                 close(fd);
603                 return -1;
604         }
605 
606         memset(&addr, 0, sizeof(addr));
607         addr.sun_family = AF_UNIX;
608 
609         strlcpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);
610         unlink(path);
611 
612         if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
613                 perror("failed: bind");
614                 close(fd);
615                 return -1;
616         }
617 
618         if (listen(fd, 1) == -1) {
619                 perror("failed: listen");
620                 close(fd);
621                 return -1;
622         }
623 
624         return fd;
625 }
626 
627 enum {
628         CMD_LIST   = 0,
629         CMD_SIGNAL = 1,
630         CMD_STOP   = 2,
631         CMD_PING   = 3,
632         CMD_MAX,
633 };
634 
635 #define SESSION_MAX 64
636 
637 union cmd {
638         int cmd;
639 
640         /* CMD_LIST */
641         struct {
642                 int     cmd;
643                 int     verbose;
644                 char    csv_sep;
645         } list;
646 
647         /* CMD_SIGNAL */
648         struct {
649                 int     cmd;
650                 int     sig;
651                 char    name[SESSION_MAX];
652         } signal;
653 
654         /* CMD_PING */
655         struct {
656                 int     cmd;
657                 char    name[SESSION_MAX];
658         } ping;
659 };
660 
661 enum {
662         PING_OK   = 0,
663         PING_FAIL = 1,
664         PING_MAX,
665 };
666 
667 static int daemon_session__ping(struct daemon_session *session)
668 {
669         return daemon_session__control(session, "ping", true) ?  PING_FAIL : PING_OK;
670 }
671 
672 static int cmd_session_list(struct daemon *daemon, union cmd *cmd, FILE *out)
673 {
674         char csv_sep = cmd->list.csv_sep;
675         struct daemon_session *session;
676         time_t curr = time(NULL);
677 
678         if (csv_sep) {
679                 fprintf(out, "%d%c%s%c%s%c%s/%s",
680                         /* pid daemon  */
681                         getpid(), csv_sep, "daemon",
682                         /* base */
683                         csv_sep, daemon->base,
684                         /* output */
685                         csv_sep, daemon->base, SESSION_OUTPUT);
686 
687                 fprintf(out, "%c%s/%s",
688                         /* lock */
689                         csv_sep, daemon->base, "lock");
690 
691                 fprintf(out, "%c%lu",
692                         /* session up time */
693                         csv_sep, (curr - daemon->start) / 60);
694 
695                 fprintf(out, "\n");
696         } else {
697                 fprintf(out, "[%d:daemon] base: %s\n", getpid(), daemon->base);
698                 if (cmd->list.verbose) {
699                         fprintf(out, "  output:  %s/%s\n",
700                                 daemon->base, SESSION_OUTPUT);
701                         fprintf(out, "  lock:    %s/lock\n",
702                                 daemon->base);
703                         fprintf(out, "  up:      %lu minutes\n",
704                                 (curr - daemon->start) / 60);
705                 }
706         }
707 
708         list_for_each_entry(session, &daemon->sessions, list) {
709                 if (csv_sep) {
710                         fprintf(out, "%d%c%s%c%s",
711                                 /* pid */
712                                 session->pid,
713                                 /* name */
714                                 csv_sep, session->name,
715                                 /* base */
716                                 csv_sep, session->run);
717 
718                         fprintf(out, "%c%s%c%s/%s",
719                                 /* session dir */
720                                 csv_sep, session->base,
721                                 /* session output */
722                                 csv_sep, session->base, SESSION_OUTPUT);
723 
724                         fprintf(out, "%c%s/%s%c%s/%s",
725                                 /* session control */
726                                 csv_sep, session->base, SESSION_CONTROL,
727                                 /* session ack */
728                                 csv_sep, session->base, SESSION_ACK);
729 
730                         fprintf(out, "%c%lu",
731                                 /* session up time */
732                                 csv_sep, (curr - session->start) / 60);
733 
734                         fprintf(out, "\n");
735                 } else {
736                         fprintf(out, "[%d:%s] perf record %s\n",
737                                 session->pid, session->name, session->run);
738                         if (!cmd->list.verbose)
739                                 continue;
740                         fprintf(out, "  base:    %s\n",
741                                 session->base);
742                         fprintf(out, "  output:  %s/%s\n",
743                                 session->base, SESSION_OUTPUT);
744                         fprintf(out, "  control: %s/%s\n",
745                                 session->base, SESSION_CONTROL);
746                         fprintf(out, "  ack:     %s/%s\n",
747                                 session->base, SESSION_ACK);
748                         fprintf(out, "  up:      %lu minutes\n",
749                                 (curr - session->start) / 60);
750                 }
751         }
752 
753         return 0;
754 }
755 
756 static int daemon_session__signal(struct daemon_session *session, int sig)
757 {
758         if (session->pid < 0)
759                 return -1;
760         return kill(session->pid, sig);
761 }
762 
763 static int cmd_session_kill(struct daemon *daemon, union cmd *cmd, FILE *out)
764 {
765         struct daemon_session *session;
766         bool all = false;
767 
768         all = !strcmp(cmd->signal.name, "all");
769 
770         list_for_each_entry(session, &daemon->sessions, list) {
771                 if (all || !strcmp(cmd->signal.name, session->name)) {
772                         daemon_session__signal(session, cmd->signal.sig);
773                         fprintf(out, "signal %d sent to session '%s [%d]'\n",
774                                 cmd->signal.sig, session->name, session->pid);
775                 }
776         }
777 
778         return 0;
779 }
780 
781 static const char *ping_str[PING_MAX] = {
782         [PING_OK]   = "OK",
783         [PING_FAIL] = "FAIL",
784 };
785 
786 static int cmd_session_ping(struct daemon *daemon, union cmd *cmd, FILE *out)
787 {
788         struct daemon_session *session;
789         bool all = false, found = false;
790 
791         all = !strcmp(cmd->ping.name, "all");
792 
793         list_for_each_entry(session, &daemon->sessions, list) {
794                 if (all || !strcmp(cmd->ping.name, session->name)) {
795                         int state = daemon_session__ping(session);
796 
797                         fprintf(out, "%-4s %s\n", ping_str[state], session->name);
798                         found = true;
799                 }
800         }
801 
802         if (!found && !all) {
803                 fprintf(out, "%-4s %s (not found)\n",
804                         ping_str[PING_FAIL], cmd->ping.name);
805         }
806         return 0;
807 }
808 
809 static int handle_server_socket(struct daemon *daemon, int sock_fd)
810 {
811         int ret = -1, fd;
812         FILE *out = NULL;
813         union cmd cmd;
814 
815         fd = accept(sock_fd, NULL, NULL);
816         if (fd < 0) {
817                 perror("failed: accept");
818                 return -1;
819         }
820 
821         if (sizeof(cmd) != readn(fd, &cmd, sizeof(cmd))) {
822                 perror("failed: read");
823                 goto out;
824         }
825 
826         out = fdopen(fd, "w");
827         if (!out) {
828                 perror("failed: fdopen");
829                 goto out;
830         }
831 
832         switch (cmd.cmd) {
833         case CMD_LIST:
834                 ret = cmd_session_list(daemon, &cmd, out);
835                 break;
836         case CMD_SIGNAL:
837                 ret = cmd_session_kill(daemon, &cmd, out);
838                 break;
839         case CMD_STOP:
840                 done = 1;
841                 ret = 0;
842                 pr_debug("perf daemon is exciting\n");
843                 break;
844         case CMD_PING:
845                 ret = cmd_session_ping(daemon, &cmd, out);
846                 break;
847         default:
848                 break;
849         }
850 
851         fclose(out);
852 out:
853         /* If out is defined, then fd is closed via fclose. */
854         if (!out)
855                 close(fd);
856         return ret;
857 }
858 
859 static int setup_client_socket(struct daemon *daemon)
860 {
861         struct sockaddr_un addr;
862         char path[PATH_MAX];
863         int fd = socket(AF_UNIX, SOCK_STREAM, 0);
864 
865         if (fd == -1) {
866                 perror("failed: socket");
867                 return -1;
868         }
869 
870         scnprintf(path, sizeof(path), "%s/control", daemon->base);
871 
872         if (strlen(path) + 1 >= sizeof(addr.sun_path)) {
873                 pr_err("failed: control path too long '%s'\n", path);
874                 close(fd);
875                 return -1;
876         }
877 
878         memset(&addr, 0, sizeof(addr));
879         addr.sun_family = AF_UNIX;
880         strlcpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);
881 
882         if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1) {
883                 perror("failed: connect");
884                 close(fd);
885                 return -1;
886         }
887 
888         return fd;
889 }
890 
891 static void daemon_session__kill(struct daemon_session *session,
892                                  struct daemon *daemon)
893 {
894         int how = 0;
895 
896         do {
897                 switch (how) {
898                 case 0:
899                         daemon_session__control(session, "stop", false);
900                         break;
901                 case 1:
902                         daemon_session__signal(session, SIGTERM);
903                         break;
904                 case 2:
905                         daemon_session__signal(session, SIGKILL);
906                         break;
907                 default:
908                         pr_err("failed to wait for session %s\n",
909                                session->name);
910                         return;
911                 }
912                 how++;
913 
914         } while (daemon_session__wait(session, daemon, 10));
915 }
916 
917 static void daemon__signal(struct daemon *daemon, int sig)
918 {
919         struct daemon_session *session;
920 
921         list_for_each_entry(session, &daemon->sessions, list)
922                 daemon_session__signal(session, sig);
923 }
924 
925 static void daemon_session__delete(struct daemon_session *session)
926 {
927         free(session->base);
928         free(session->name);
929         free(session->run);
930         free(session);
931 }
932 
933 static void daemon_session__remove(struct daemon_session *session)
934 {
935         list_del(&session->list);
936         daemon_session__delete(session);
937 }
938 
939 static void daemon__stop(struct daemon *daemon)
940 {
941         struct daemon_session *session;
942 
943         list_for_each_entry(session, &daemon->sessions, list)
944                 daemon_session__control(session, "stop", false);
945 }
946 
947 static void daemon__kill(struct daemon *daemon)
948 {
949         int how = 0;
950 
951         do {
952                 switch (how) {
953                 case 0:
954                         daemon__stop(daemon);
955                         break;
956                 case 1:
957                         daemon__signal(daemon, SIGTERM);
958                         break;
959                 case 2:
960                         daemon__signal(daemon, SIGKILL);
961                         break;
962                 default:
963                         pr_err("failed to wait for sessions\n");
964                         return;
965                 }
966                 how++;
967 
968         } while (daemon__wait(daemon, 10));
969 }
970 
971 static void daemon__exit(struct daemon *daemon)
972 {
973         struct daemon_session *session, *h;
974 
975         list_for_each_entry_safe(session, h, &daemon->sessions, list)
976                 daemon_session__remove(session);
977 
978         free(daemon->config_real);
979         free(daemon->config_base);
980         free(daemon->base);
981 }
982 
983 static int daemon__reconfig(struct daemon *daemon)
984 {
985         struct daemon_session *session, *n;
986 
987         list_for_each_entry_safe(session, n, &daemon->sessions, list) {
988                 /* No change. */
989                 if (session->state == OK)
990                         continue;
991 
992                 /* Remove session. */
993                 if (session->state == KILL) {
994                         if (session->pid > 0) {
995                                 daemon_session__kill(session, daemon);
996                                 pr_info("reconfig: session '%s' killed\n", session->name);
997                         }
998                         daemon_session__remove(session);
999                         continue;
1000                 }
1001 
1002                 /* Reconfig session. */
1003                 if (session->pid > 0) {
1004                         daemon_session__kill(session, daemon);
1005                         pr_info("reconfig: session '%s' killed\n", session->name);
1006                 }
1007                 if (daemon_session__run(session, daemon))
1008                         return -1;
1009 
1010                 session->state = OK;
1011         }
1012 
1013         return 0;
1014 }
1015 
1016 static int setup_config_changes(struct daemon *daemon)
1017 {
1018         char *basen = strdup(daemon->config_real);
1019         char *dirn  = strdup(daemon->config_real);
1020         char *base, *dir;
1021         int fd, wd = -1;
1022 
1023         if (!dirn || !basen)
1024                 goto out;
1025 
1026         fd = inotify_init1(IN_NONBLOCK|O_CLOEXEC);
1027         if (fd < 0) {
1028                 perror("failed: inotify_init");
1029                 goto out;
1030         }
1031 
1032         dir = dirname(dirn);
1033         base = basename(basen);
1034         pr_debug("config file: %s, dir: %s\n", base, dir);
1035 
1036         wd = inotify_add_watch(fd, dir, IN_CLOSE_WRITE);
1037         if (wd >= 0) {
1038                 daemon->config_base = strdup(base);
1039                 if (!daemon->config_base) {
1040                         close(fd);
1041                         wd = -1;
1042                 }
1043         } else {
1044                 perror("failed: inotify_add_watch");
1045         }
1046 
1047 out:
1048         free(basen);
1049         free(dirn);
1050         return wd < 0 ? -1 : fd;
1051 }
1052 
1053 static bool process_inotify_event(struct daemon *daemon, char *buf, ssize_t len)
1054 {
1055         char *p = buf;
1056 
1057         while (p < (buf + len)) {
1058                 struct inotify_event *event = (struct inotify_event *) p;
1059 
1060                 /*
1061                  * We monitor config directory, check if our
1062                  * config file was changes.
1063                  */
1064                 if ((event->mask & IN_CLOSE_WRITE) &&
1065                     !(event->mask & IN_ISDIR)) {
1066                         if (!strcmp(event->name, daemon->config_base))
1067                                 return true;
1068                 }
1069                 p += sizeof(*event) + event->len;
1070         }
1071         return false;
1072 }
1073 
1074 static int handle_config_changes(struct daemon *daemon, int conf_fd,
1075                                  bool *config_changed)
1076 {
1077         char buf[4096];
1078         ssize_t len;
1079 
1080         while (!(*config_changed)) {
1081                 len = read(conf_fd, buf, sizeof(buf));
1082                 if (len == -1) {
1083                         if (errno != EAGAIN) {
1084                                 perror("failed: read");
1085                                 return -1;
1086                         }
1087                         return 0;
1088                 }
1089                 *config_changed = process_inotify_event(daemon, buf, len);
1090         }
1091         return 0;
1092 }
1093 
1094 static int setup_config(struct daemon *daemon)
1095 {
1096         if (daemon->base_user) {
1097                 daemon->base = strdup(daemon->base_user);
1098                 if (!daemon->base)
1099                         return -ENOMEM;
1100         }
1101 
1102         if (daemon->config) {
1103                 char *real = realpath(daemon->config, NULL);
1104 
1105                 if (!real) {
1106                         perror("failed: realpath");
1107                         return -1;
1108                 }
1109                 daemon->config_real = real;
1110                 return 0;
1111         }
1112 
1113         if (perf_config_system() && !access(perf_etc_perfconfig(), R_OK))
1114                 daemon->config_real = strdup(perf_etc_perfconfig());
1115         else if (perf_config_global() && perf_home_perfconfig())
1116                 daemon->config_real = strdup(perf_home_perfconfig());
1117 
1118         return daemon->config_real ? 0 : -1;
1119 }
1120 
1121 #ifndef F_TLOCK
1122 #define F_TLOCK 2
1123 
1124 static int lockf(int fd, int cmd, off_t len)
1125 {
1126         if (cmd != F_TLOCK || len != 0)
1127                 return -1;
1128 
1129         return flock(fd, LOCK_EX | LOCK_NB);
1130 }
1131 #endif // F_TLOCK
1132 
1133 /*
1134  * Each daemon tries to create and lock BASE/lock file,
1135  * if it's successful we are sure we're the only daemon
1136  * running over the BASE.
1137  *
1138  * Once daemon is finished, file descriptor to lock file
1139  * is closed and lock is released.
1140  */
1141 static int check_lock(struct daemon *daemon)
1142 {
1143         char path[PATH_MAX];
1144         char buf[20];
1145         int fd, pid;
1146         ssize_t len;
1147 
1148         scnprintf(path, sizeof(path), "%s/lock", daemon->base);
1149 
1150         fd = open(path, O_RDWR|O_CREAT|O_CLOEXEC, 0640);
1151         if (fd < 0)
1152                 return -1;
1153 
1154         if (lockf(fd, F_TLOCK, 0) < 0) {
1155                 filename__read_int(path, &pid);
1156                 fprintf(stderr, "failed: another perf daemon (pid %d) owns %s\n",
1157                         pid, daemon->base);
1158                 close(fd);
1159                 return -1;
1160         }
1161 
1162         scnprintf(buf, sizeof(buf), "%d", getpid());
1163         len = strlen(buf);
1164 
1165         if (write(fd, buf, len) != len) {
1166                 perror("failed: write");
1167                 close(fd);
1168                 return -1;
1169         }
1170 
1171         if (ftruncate(fd, len)) {
1172                 perror("failed: ftruncate");
1173                 close(fd);
1174                 return -1;
1175         }
1176 
1177         return 0;
1178 }
1179 
1180 static int go_background(struct daemon *daemon)
1181 {
1182         int pid, fd;
1183 
1184         pid = fork();
1185         if (pid < 0)
1186                 return -1;
1187 
1188         if (pid > 0)
1189                 return 1;
1190 
1191         if (setsid() < 0)
1192                 return -1;
1193 
1194         if (check_lock(daemon))
1195                 return -1;
1196 
1197         umask(0);
1198 
1199         if (chdir(daemon->base)) {
1200                 perror("failed: chdir");
1201                 return -1;
1202         }
1203 
1204         fd = open("output", O_RDWR|O_CREAT|O_TRUNC, 0644);
1205         if (fd < 0) {
1206                 perror("failed: open");
1207                 return -1;
1208         }
1209 
1210         if (fcntl(fd, F_SETFD, FD_CLOEXEC)) {
1211                 perror("failed: fcntl FD_CLOEXEC");
1212                 close(fd);
1213                 return -1;
1214         }
1215 
1216         close(0);
1217         dup2(fd, 1);
1218         dup2(fd, 2);
1219         close(fd);
1220 
1221         daemon->out = fdopen(1, "w");
1222         if (!daemon->out) {
1223                 close(1);
1224                 close(2);
1225                 return -1;
1226         }
1227 
1228         setbuf(daemon->out, NULL);
1229         return 0;
1230 }
1231 
1232 static int setup_signalfd(struct daemon *daemon)
1233 {
1234         sigset_t mask;
1235 
1236         sigemptyset(&mask);
1237         sigaddset(&mask, SIGCHLD);
1238 
1239         if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
1240                 return -1;
1241 
1242         daemon->signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC);
1243         return daemon->signal_fd;
1244 }
1245 
1246 static int __cmd_start(struct daemon *daemon, struct option parent_options[],
1247                        int argc, const char **argv)
1248 {
1249         bool foreground = false;
1250         struct option start_options[] = {
1251                 OPT_BOOLEAN('f', "foreground", &foreground, "stay on console"),
1252                 OPT_PARENT(parent_options),
1253                 OPT_END()
1254         };
1255         int sock_fd = -1, conf_fd = -1, signal_fd = -1;
1256         int sock_pos, file_pos, signal_pos;
1257         struct fdarray fda;
1258         int err = 0;
1259 
1260         argc = parse_options(argc, argv, start_options, daemon_usage, 0);
1261         if (argc)
1262                 usage_with_options(daemon_usage, start_options);
1263 
1264         daemon->start = time(NULL);
1265 
1266         if (setup_config(daemon)) {
1267                 pr_err("failed: config not found\n");
1268                 return -1;
1269         }
1270 
1271         if (setup_server_config(daemon))
1272                 return -1;
1273 
1274         if (foreground && check_lock(daemon))
1275                 return -1;
1276 
1277         if (!foreground) {
1278                 err = go_background(daemon);
1279                 if (err) {
1280                         /* original process, exit normally */
1281                         if (err == 1)
1282                                 err = 0;
1283                         daemon__exit(daemon);
1284                         return err;
1285                 }
1286         }
1287 
1288         debug_set_file(daemon->out);
1289         debug_set_display_time(true);
1290 
1291         pr_info("daemon started (pid %d)\n", getpid());
1292 
1293         fdarray__init(&fda, 3);
1294 
1295         sock_fd = setup_server_socket(daemon);
1296         if (sock_fd < 0)
1297                 goto out;
1298 
1299         conf_fd = setup_config_changes(daemon);
1300         if (conf_fd < 0)
1301                 goto out;
1302 
1303         signal_fd = setup_signalfd(daemon);
1304         if (signal_fd < 0)
1305                 goto out;
1306 
1307         sock_pos = fdarray__add(&fda, sock_fd, POLLIN|POLLERR|POLLHUP, 0);
1308         if (sock_pos < 0)
1309                 goto out;
1310 
1311         file_pos = fdarray__add(&fda, conf_fd, POLLIN|POLLERR|POLLHUP, 0);
1312         if (file_pos < 0)
1313                 goto out;
1314 
1315         signal_pos = fdarray__add(&fda, signal_fd, POLLIN|POLLERR|POLLHUP, 0);
1316         if (signal_pos < 0)
1317                 goto out;
1318 
1319         signal(SIGINT, sig_handler);
1320         signal(SIGTERM, sig_handler);
1321         signal(SIGPIPE, SIG_IGN);
1322 
1323         while (!done && !err) {
1324                 err = daemon__reconfig(daemon);
1325 
1326                 if (!err && fdarray__poll(&fda, -1)) {
1327                         bool reconfig = false;
1328 
1329                         if (fda.entries[sock_pos].revents & POLLIN)
1330                                 err = handle_server_socket(daemon, sock_fd);
1331                         if (fda.entries[file_pos].revents & POLLIN)
1332                                 err = handle_config_changes(daemon, conf_fd, &reconfig);
1333                         if (fda.entries[signal_pos].revents & POLLIN)
1334                                 err = handle_signalfd(daemon) < 0;
1335 
1336                         if (reconfig)
1337                                 err = setup_server_config(daemon);
1338                 }
1339         }
1340 
1341 out:
1342         fdarray__exit(&fda);
1343 
1344         daemon__kill(daemon);
1345         daemon__exit(daemon);
1346 
1347         if (sock_fd != -1)
1348                 close(sock_fd);
1349         if (conf_fd != -1)
1350                 close(conf_fd);
1351         if (signal_fd != -1)
1352                 close(signal_fd);
1353 
1354         pr_info("daemon exited\n");
1355         fclose(daemon->out);
1356         return err;
1357 }
1358 
1359 static int send_cmd(struct daemon *daemon, union cmd *cmd)
1360 {
1361         int ret = -1, fd;
1362         char *line = NULL;
1363         size_t len = 0;
1364         ssize_t nread;
1365         FILE *in = NULL;
1366 
1367         if (setup_client_config(daemon))
1368                 return -1;
1369 
1370         fd = setup_client_socket(daemon);
1371         if (fd < 0)
1372                 return -1;
1373 
1374         if (sizeof(*cmd) != writen(fd, cmd, sizeof(*cmd))) {
1375                 perror("failed: write");
1376                 goto out;
1377         }
1378 
1379         in = fdopen(fd, "r");
1380         if (!in) {
1381                 perror("failed: fdopen");
1382                 goto out;
1383         }
1384 
1385         while ((nread = getline(&line, &len, in)) != -1) {
1386                 if (fwrite(line, nread, 1, stdout) != 1)
1387                         goto out_fclose;
1388                 fflush(stdout);
1389         }
1390 
1391         ret = 0;
1392 out_fclose:
1393         fclose(in);
1394         free(line);
1395 out:
1396         /* If in is defined, then fd is closed via fclose. */
1397         if (!in)
1398                 close(fd);
1399         return ret;
1400 }
1401 
1402 static int send_cmd_list(struct daemon *daemon)
1403 {
1404         union cmd cmd;
1405 
1406         memset(&cmd, 0, sizeof(cmd));
1407         cmd.list.cmd = CMD_LIST;
1408         cmd.list.verbose = verbose;
1409         cmd.list.csv_sep = daemon->csv_sep ? *daemon->csv_sep : 0;
1410 
1411         return send_cmd(daemon, &cmd);
1412 }
1413 
1414 static int __cmd_signal(struct daemon *daemon, struct option parent_options[],
1415                         int argc, const char **argv)
1416 {
1417         const char *name = "all";
1418         struct option start_options[] = {
1419                 OPT_STRING(0, "session", &name, "session",
1420                         "Sent signal to specific session"),
1421                 OPT_PARENT(parent_options),
1422                 OPT_END()
1423         };
1424         union cmd cmd;
1425 
1426         argc = parse_options(argc, argv, start_options, daemon_usage, 0);
1427         if (argc)
1428                 usage_with_options(daemon_usage, start_options);
1429 
1430         if (setup_config(daemon)) {
1431                 pr_err("failed: config not found\n");
1432                 return -1;
1433         }
1434 
1435         memset(&cmd, 0, sizeof(cmd));
1436         cmd.signal.cmd = CMD_SIGNAL,
1437         cmd.signal.sig = SIGUSR2;
1438         strncpy(cmd.signal.name, name, sizeof(cmd.signal.name) - 1);
1439 
1440         return send_cmd(daemon, &cmd);
1441 }
1442 
1443 static int __cmd_stop(struct daemon *daemon, struct option parent_options[],
1444                         int argc, const char **argv)
1445 {
1446         struct option start_options[] = {
1447                 OPT_PARENT(parent_options),
1448                 OPT_END()
1449         };
1450         union cmd cmd;
1451 
1452         argc = parse_options(argc, argv, start_options, daemon_usage, 0);
1453         if (argc)
1454                 usage_with_options(daemon_usage, start_options);
1455 
1456         if (setup_config(daemon)) {
1457                 pr_err("failed: config not found\n");
1458                 return -1;
1459         }
1460 
1461         memset(&cmd, 0, sizeof(cmd));
1462         cmd.cmd = CMD_STOP;
1463         return send_cmd(daemon, &cmd);
1464 }
1465 
1466 static int __cmd_ping(struct daemon *daemon, struct option parent_options[],
1467                       int argc, const char **argv)
1468 {
1469         const char *name = "all";
1470         struct option ping_options[] = {
1471                 OPT_STRING(0, "session", &name, "session",
1472                         "Ping to specific session"),
1473                 OPT_PARENT(parent_options),
1474                 OPT_END()
1475         };
1476         union cmd cmd;
1477 
1478         argc = parse_options(argc, argv, ping_options, daemon_usage, 0);
1479         if (argc)
1480                 usage_with_options(daemon_usage, ping_options);
1481 
1482         if (setup_config(daemon)) {
1483                 pr_err("failed: config not found\n");
1484                 return -1;
1485         }
1486 
1487         memset(&cmd, 0, sizeof(cmd));
1488         cmd.cmd = CMD_PING;
1489         scnprintf(cmd.ping.name, sizeof(cmd.ping.name), "%s", name);
1490         return send_cmd(daemon, &cmd);
1491 }
1492 
1493 int cmd_daemon(int argc, const char **argv)
1494 {
1495         struct option daemon_options[] = {
1496                 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
1497                 OPT_STRING(0, "config", &__daemon.config,
1498                         "config file", "config file path"),
1499                 OPT_STRING(0, "base", &__daemon.base_user,
1500                         "directory", "base directory"),
1501                 OPT_STRING_OPTARG('x', "field-separator", &__daemon.csv_sep,
1502                         "field separator", "print counts with custom separator", ","),
1503                 OPT_END()
1504         };
1505 
1506         perf_exe(__daemon.perf, sizeof(__daemon.perf));
1507         __daemon.out = stdout;
1508 
1509         argc = parse_options(argc, argv, daemon_options, daemon_usage,
1510                              PARSE_OPT_STOP_AT_NON_OPTION);
1511 
1512         if (argc) {
1513                 if (!strcmp(argv[0], "start"))
1514                         return __cmd_start(&__daemon, daemon_options, argc, argv);
1515                 if (!strcmp(argv[0], "signal"))
1516                         return __cmd_signal(&__daemon, daemon_options, argc, argv);
1517                 else if (!strcmp(argv[0], "stop"))
1518                         return __cmd_stop(&__daemon, daemon_options, argc, argv);
1519                 else if (!strcmp(argv[0], "ping"))
1520                         return __cmd_ping(&__daemon, daemon_options, argc, argv);
1521 
1522                 pr_err("failed: unknown command '%s'\n", argv[0]);
1523                 return -1;
1524         }
1525 
1526         if (setup_config(&__daemon)) {
1527                 pr_err("failed: config not found\n");
1528                 return -1;
1529         }
1530 
1531         return send_cmd_list(&__daemon);
1532 }
1533 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp