perf tools: Add FIFO file names as alternative options to --control

Enable the --control option to accept file names as an alternative to
file descriptors.

Example:

  $ mkfifo perf.control
  $ mkfifo perf.ack
  $ cat perf.ack &
  [1] 6808
  $ perf record --control fifo:perf.control,perf.ack -- sleep 300 &
  [2] 6810
  $ echo disable > perf.control
  $ Events disabled
  ack

  $ echo enable > perf.control
  $ Events enabled
  ack

  $ echo disable > perf.control
  $ Events disabled
  ack

  $ kill %2
  [ perf record: Woken up 4 times to write data ]
  $ [ perf record: Captured and wrote 0.018 MB perf.data (7 samples) ]

  [1]-  Done                    cat perf.ack
  [2]+  Terminated              perf record --control fifo:perf.control,perf.ack -- sleep 300
  $

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Acked-by: Alexey Budankov <alexey.budankov@linux.intel.com>
Acked-by: Jiri Olsa <jolsa@redhat.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Link: http://lore.kernel.org/lkml/20200902105707.11491-1-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Adrian Hunter
2020-09-02 13:57:07 +03:00
committed by Arnaldo Carvalho de Melo
parent 1f4390d825
commit a8fcbd269b
8 changed files with 101 additions and 14 deletions

View File

@@ -1727,12 +1727,63 @@ struct evsel *perf_evlist__reset_weak_group(struct evlist *evsel_list,
return leader;
}
int evlist__parse_control(const char *str, int *ctl_fd, int *ctl_fd_ack)
static int evlist__parse_control_fifo(const char *str, int *ctl_fd, int *ctl_fd_ack, bool *ctl_fd_close)
{
char *s, *p;
int ret = 0, fd;
if (strncmp(str, "fifo:", 5))
return -EINVAL;
str += 5;
if (!*str || *str == ',')
return -EINVAL;
s = strdup(str);
if (!s)
return -ENOMEM;
p = strchr(s, ',');
if (p)
*p = '\0';
/*
* O_RDWR avoids POLLHUPs which is necessary to allow the other
* end of a FIFO to be repeatedly opened and closed.
*/
fd = open(s, O_RDWR | O_NONBLOCK | O_CLOEXEC);
if (fd < 0) {
pr_err("Failed to open '%s'\n", s);
ret = -errno;
goto out_free;
}
*ctl_fd = fd;
*ctl_fd_close = true;
if (p && *++p) {
/* O_RDWR | O_NONBLOCK means the other end need not be open */
fd = open(p, O_RDWR | O_NONBLOCK | O_CLOEXEC);
if (fd < 0) {
pr_err("Failed to open '%s'\n", p);
ret = -errno;
goto out_free;
}
*ctl_fd_ack = fd;
}
out_free:
free(s);
return ret;
}
int evlist__parse_control(const char *str, int *ctl_fd, int *ctl_fd_ack, bool *ctl_fd_close)
{
char *comma = NULL, *endptr = NULL;
*ctl_fd_close = false;
if (strncmp(str, "fd:", 3))
return -EINVAL;
return evlist__parse_control_fifo(str, ctl_fd, ctl_fd_ack, ctl_fd_close);
*ctl_fd = strtoul(&str[3], &endptr, 0);
if (endptr == &str[3])