Commit f07918fd authored by Mark McLoughlin's avatar Mark McLoughlin Committed by Anthony Liguori
Browse files

Add getfd and closefd monitor commands



Add monitor commands to support passing file descriptors via
SCM_RIGHTS.

getfd assigns the passed file descriptor a name for use with other
monitor commands.

closefd allows passed file descriptors to be closed. If a monitor
command actually uses a named file descriptor, closefd will not be
required.

Signed-off-by: default avatarMark McLoughlin <markmc@redhat.com>
Signed-off-by: default avatarAnthony Liguori <aliguori@us.ibm.com>
parent 7d174059
Loading
Loading
Loading
Loading
+69 −0
Original line number Diff line number Diff line
@@ -70,6 +70,14 @@ typedef struct mon_cmd_t {
    const char *help;
} mon_cmd_t;

/* file descriptors passed via SCM_RIGHTS */
typedef struct mon_fd_t mon_fd_t;
struct mon_fd_t {
    char *name;
    int fd;
    LIST_ENTRY(mon_fd_t) next;
};

struct Monitor {
    CharDriverState *chr;
    int flags;
@@ -80,6 +88,7 @@ struct Monitor {
    CPUState *mon_cpu;
    BlockDriverCompletionFunc *password_completion_cb;
    void *password_opaque;
    LIST_HEAD(,mon_fd_t) fds;
    LIST_ENTRY(Monitor) entry;
};

@@ -1705,6 +1714,66 @@ static void do_inject_mce(Monitor *mon,
}
#endif

static void do_getfd(Monitor *mon, const char *fdname)
{
    mon_fd_t *monfd;
    int fd;

    fd = qemu_chr_get_msgfd(mon->chr);
    if (fd == -1) {
        monitor_printf(mon, "getfd: no file descriptor supplied via SCM_RIGHTS\n");
        return;
    }

    if (qemu_isdigit(fdname[0])) {
        monitor_printf(mon, "getfd: monitor names may not begin with a number\n");
        return;
    }

    fd = dup(fd);
    if (fd == -1) {
        monitor_printf(mon, "Failed to dup() file descriptor: %s\n",
                       strerror(errno));
        return;
    }

    LIST_FOREACH(monfd, &mon->fds, next) {
        if (strcmp(monfd->name, fdname) != 0) {
            continue;
        }

        close(monfd->fd);
        monfd->fd = fd;
        return;
    }

    monfd = qemu_mallocz(sizeof(mon_fd_t));
    monfd->name = qemu_strdup(fdname);
    monfd->fd = fd;

    LIST_INSERT_HEAD(&mon->fds, monfd, next);
}

static void do_closefd(Monitor *mon, const char *fdname)
{
    mon_fd_t *monfd;

    LIST_FOREACH(monfd, &mon->fds, next) {
        if (strcmp(monfd->name, fdname) != 0) {
            continue;
        }

        LIST_REMOVE(monfd, next);
        close(monfd->fd);
        qemu_free(monfd->name);
        qemu_free(monfd);
        return;
    }

    monitor_printf(mon, "Failed to find file descriptor named %s\n",
                   fdname);
}

static const mon_cmd_t mon_cmds[] = {
#include "qemu-monitor.h"
    { NULL, NULL, },
+18 −0
Original line number Diff line number Diff line
@@ -626,6 +626,24 @@ ETEXI
STEXI
@item mce @var{cpu} @var{bank} @var{status} @var{mcgstatus} @var{addr} @var{misc}
Inject an MCE on the given CPU (x86 only).
ETEXI

    { "getfd", "s", do_getfd, "getfd name",
      "receive a file descriptor via SCM rights and assign it a name" },
STEXI
@item getfd @var{fdname}
If a file descriptor is passed alongside this command using the SCM_RIGHTS
mechanism on unix sockets, it is stored using the name @var{fdname} for
later use by other monitor commands.
ETEXI

    { "closefd", "s", do_closefd, "closefd name",
      "close a file descriptor previously passed via SCM rights" },
STEXI
@item closefd @var{fdname}
Close the file descriptor previously assigned to @var{fdname} using the
@code{getfd} command. This is only needed if the file descriptor was never
used by another monitor command.
ETEXI

STEXI