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: Mark McLoughlin <markmc@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
parent
7d1740590b
commit
f07918fdff
69
monitor.c
69
monitor.c
@ -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, },
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user