This patch provides support for the getfd_file monitor command.
This command will allow passing of a filename and its corresponding
file descriptor to a guest via the monitor. This command could be
followed, for example, by a drive_add command to hot attach a disk
drive.
Signed-off-by: Corey Bryant <coreyb(a)linux.vnet.ibm.com>
---
hmp-commands.hx | 17 +++++++++++++
monitor.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
monitor.h | 3 ++
qemu-tool.c | 5 ++++
qmp-commands.hx | 30 +++++++++++++++++++++++
5 files changed, 125 insertions(+), 0 deletions(-)
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 18cb415..9cd5ed1 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1240,6 +1240,23 @@ used by another monitor command.
ETEXI
{
+ .name = "getfd_file",
+ .args_type = "filename:s",
+ .params = "getfd_file filename",
+ .help = "receive a file descriptor via SCM rights and assign it a
filename",
+ .user_print = monitor_user_noop,
+ .mhandler.cmd_new = do_getfd_file,
+ },
+
+STEXI
+@item getfd_file @var{filename}
+@findex getfd_file
+If a file descriptor is passed alongside this command using the SCM_RIGHTS
+mechanism on unix sockets, it is stored using the name @var{filename} for
+later use by other monitor commands.
+ETEXI
+
+ {
.name = "block_passwd",
.args_type = "device:B,password:s",
.params = "block_passwd device password",
diff --git a/monitor.c b/monitor.c
index 12a6fe2..bdf4dd8 100644
--- a/monitor.c
+++ b/monitor.c
@@ -163,6 +163,7 @@ struct Monitor {
#endif
QError *error;
QLIST_HEAD(,mon_fd_t) fds;
+ QLIST_HEAD(,mon_fd_t) file_fds;
QLIST_ENTRY(Monitor) entry;
};
@@ -2256,6 +2257,42 @@ static int do_closefd(Monitor *mon, const QDict *qdict, QObject
**ret_data)
return -1;
}
+static int do_getfd_file(Monitor *mon, const QDict *qdict, QObject **ret_data)
+{
+ const char *filename = qdict_get_str(qdict, "filename");
+ mon_fd_t *monfd;
+ int fd;
+
+ fd = qemu_chr_fe_get_msgfd(mon->chr);
+ if (fd == -1) {
+ qerror_report(QERR_FD_NOT_SUPPLIED);
+ return -1;
+ }
+
+ if (qemu_isdigit(filename[0])) {
+ qerror_report(QERR_INVALID_PARAMETER_VALUE, "filename",
+ "a name not starting with a digit");
+ return -1;
+ }
+
+ QLIST_FOREACH(monfd, &mon->file_fds, next) {
+ if (strcmp(monfd->name, filename) != 0) {
+ continue;
+ }
+
+ close(monfd->fd);
+ monfd->fd = fd;
+ return 0;
+ }
+
+ monfd = g_malloc0(sizeof(mon_fd_t));
+ monfd->name = g_strdup(filename);
+ monfd->fd = fd;
+
+ QLIST_INSERT_HEAD(&mon->file_fds, monfd, next);
+ return 0;
+}
+
static void do_loadvm(Monitor *mon, const QDict *qdict)
{
int saved_vm_running = runstate_is_running();
@@ -2292,6 +2329,39 @@ int monitor_get_fd(Monitor *mon, const char *fdname)
return -1;
}
+int monitor_get_fd_file(Monitor *mon, const char *filename,
+ bool take_ownership)
+{
+ mon_fd_t *monfd;
+
+ QLIST_FOREACH(monfd, &mon->file_fds, next) {
+ int fd;
+
+ if (strcmp(monfd->name, filename) != 0) {
+ continue;
+ }
+
+ fd = monfd->fd;
+
+ if (take_ownership) {
+ /* caller takes ownership of fd */
+ QLIST_REMOVE(monfd, next);
+ g_free(monfd->name);
+ g_free(monfd);
+ }
+
+ return fd;
+ }
+
+ return -1;
+}
+
+int qemu_get_fd_file(const char *filename, bool take_ownership)
+{
+ return cur_mon ?
+ monitor_get_fd_file(cur_mon, filename, take_ownership) : -1;
+}
+
/* mon_cmds and info_cmds would be sorted at runtime */
static mon_cmd_t mon_cmds[] = {
#include "hmp-commands.h"
diff --git a/monitor.h b/monitor.h
index 0d49800..529d8a7 100644
--- a/monitor.h
+++ b/monitor.h
@@ -60,6 +60,9 @@ int monitor_read_block_device_key(Monitor *mon, const char *device,
void *opaque);
int monitor_get_fd(Monitor *mon, const char *fdname);
+int monitor_get_fd_file(Monitor *mon, const char *filename,
+ bool take_ownership);
+int qemu_get_fd_file(const char *filename, bool take_ownership);
void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
GCC_FMT_ATTR(2, 0);
diff --git a/qemu-tool.c b/qemu-tool.c
index 07fc4f2..d3d86bf 100644
--- a/qemu-tool.c
+++ b/qemu-tool.c
@@ -111,3 +111,8 @@ void migrate_add_blocker(Error *reason)
void migrate_del_blocker(Error *reason)
{
}
+
+int qemu_get_fd_file(const char *fdname, bool take_ownership)
+{
+ return -1;
+}
diff --git a/qmp-commands.hx b/qmp-commands.hx
index db980fa..1825a91 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -891,6 +891,36 @@ Example:
EQMP
{
+ .name = "getfd_file",
+ .args_type = "filename:s",
+ .params = "getfd_file filename",
+ .help = "receive a file descriptor via SCM rights and assign it a
filename",
+ .user_print = monitor_user_noop,
+ .mhandler.cmd_new = do_getfd_file,
+ },
+
+
+SQMP
+
+getfd_file
+--------------
+
+Receive a file descriptor via SCM rights and assign it a filename.
+
+Arguments:
+
+- "filename": filename (json-string)
+
+Example:
+
+-> { "execute": "getfd_file",
+ "arguments": { "filename":
"/var/lib/libvirt/images/tst.img" } }
+<- { "return": {} }
+
+
+EQMP
+
+ {
.name = "block_passwd",
.args_type = "device:B,password:s",
.mhandler.cmd_new = qmp_marshal_input_block_passwd,
--
1.7.7.6