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