lkml.org 
[lkml]   [2021]   [Feb]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 13/24] perf daemon: Allow only one daemon over base directory
    Date
    Add 'lock' file under daemon base and flock it, so only one
    perf daemon can run on top of it.

    Each daemon tries to create and lock BASE/lock file, if it's
    successful we are sure we're the only daemon running over
    the BASE.

    Once daemon is finished, file descriptor to lock file is
    closed and lock is released.

    Example:

    # cat ~/.perfconfig
    [daemon]
    base=/opt/perfdata

    [session-cycles]
    run = -m 10M -e cycles --overwrite --switch-output -a

    [session-sched]
    run = -m 20M -e sched:* --overwrite --switch-output -a

    Starting the daemon:

    # perf daemon start

    And try once more:

    # perf daemon start
    failed: another perf daemon (pid 775594) owns /opt/perfdata

    will end up with an error, because there's already one running
    on top of /opt/perfdata.

    Signed-off-by: Jiri Olsa <jolsa@kernel.org>
    ---
    tools/perf/Documentation/perf-daemon.txt | 3 +-
    tools/perf/builtin-daemon.c | 61 ++++++++++++++++++++++++
    2 files changed, 63 insertions(+), 1 deletion(-)

    diff --git a/tools/perf/Documentation/perf-daemon.txt b/tools/perf/Documentation/perf-daemon.txt
    index 94d5e09a1e17..3c9e265858b2 100644
    --- a/tools/perf/Documentation/perf-daemon.txt
    +++ b/tools/perf/Documentation/perf-daemon.txt
    @@ -49,7 +49,8 @@ OPTIONS

    --base=<PATH>::
    Base directory path. Each daemon instance is running on top
    - of base directory.
    + of base directory. Only one instance of server can run on
    + top of one directory at the time.

    All generic options are available also under commands.

    diff --git a/tools/perf/builtin-daemon.c b/tools/perf/builtin-daemon.c
    index 2ef7fe9200f3..22b2ec18b01b 100644
    --- a/tools/perf/builtin-daemon.c
    +++ b/tools/perf/builtin-daemon.c
    @@ -2,11 +2,13 @@
    #include <internal/lib.h>
    #include <subcmd/parse-options.h>
    #include <api/fd/array.h>
    +#include <api/fs/fs.h>
    #include <linux/zalloc.h>
    #include <linux/string.h>
    #include <linux/limits.h>
    #include <linux/string.h>
    #include <string.h>
    +#include <sys/file.h>
    #include <signal.h>
    #include <stdlib.h>
    #include <time.h>
    @@ -570,12 +572,18 @@ static int cmd_session_list(struct daemon *daemon, union cmd *cmd, FILE *out)
    /* output */
    csv_sep, daemon->base, SESSION_OUTPUT);

    + fprintf(out, "%c%s/%s",
    + /* lock */
    + csv_sep, daemon->base, "lock");
    +
    fprintf(out, "\n");
    } else {
    fprintf(out, "[%d:daemon] base: %s\n", getpid(), daemon->base);
    if (cmd->list.verbose) {
    fprintf(out, " output: %s/%s\n",
    daemon->base, SESSION_OUTPUT);
    + fprintf(out, " lock: %s/lock\n",
    + daemon->base);
    }
    }

    @@ -906,6 +914,53 @@ static int setup_config(struct daemon *daemon)
    return daemon->config_real ? 0 : -1;
    }

    +/*
    + * Each daemon tries to create and lock BASE/lock file,
    + * if it's successful we are sure we're the only daemon
    + * running over the BASE.
    + *
    + * Once daemon is finished, file descriptor to lock file
    + * is closed and lock is released.
    + */
    +static int check_lock(struct daemon *daemon)
    +{
    + char path[PATH_MAX];
    + char buf[20];
    + int fd, pid;
    + ssize_t len;
    +
    + scnprintf(path, sizeof(path), "%s/lock", daemon->base);
    +
    + fd = open(path, O_RDWR|O_CREAT|O_CLOEXEC, 0640);
    + if (fd < 0)
    + return -1;
    +
    + if (lockf(fd, F_TLOCK, 0) < 0) {
    + filename__read_int(path, &pid);
    + fprintf(stderr, "failed: another perf daemon (pid %d) owns %s\n",
    + pid, daemon->base);
    + close(fd);
    + return -1;
    + }
    +
    + scnprintf(buf, sizeof(buf), "%d", getpid());
    + len = strlen(buf);
    +
    + if (write(fd, buf, len) != len) {
    + perror("failed: write");
    + close(fd);
    + return -1;
    + }
    +
    + if (ftruncate(fd, len)) {
    + perror("failed: ftruncate");
    + close(fd);
    + return -1;
    + }
    +
    + return 0;
    +}
    +
    static int go_background(struct daemon *daemon)
    {
    int pid, fd;
    @@ -920,6 +975,9 @@ static int go_background(struct daemon *daemon)
    if (setsid() < 0)
    return -1;

    + if (check_lock(daemon))
    + return -1;
    +
    umask(0);

    if (chdir(daemon->base)) {
    @@ -995,6 +1053,9 @@ static int __cmd_start(struct daemon *daemon, struct option parent_options[],
    if (setup_server_config(daemon))
    return -1;

    + if (foreground && check_lock(daemon))
    + return -1;
    +
    if (!foreground) {
    err = go_background(daemon);
    if (err) {
    --
    2.29.2
    \
     
     \ /
      Last update: 2021-02-08 22:16    [W:3.311 / U:0.556 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site