Add entry points for calling the qemu 'add-fd' and 'remove-fd'
monitor commands. There is no entry point for 'query-fdsets';
the assumption is that a developer can use
virsh qemu-monitor-command domain
'{"execute":"query-fdsets"}'
when debugging issues, and that meanwhile, libvirt is responsible
enough to remember what fds it associated with what fdsets.
Likewise, on the 'add-fd' command, it is assumed that libvirt
will always pass a set id, rather than letting qemu autogenerate
the next available id number.
* src/qemu/qemu_monitor.c (qemuMonitorAddFd, qemuMonitorRemoveFd):
New functions.
* src/qemu/qemu_monitor.h (qemuMonitorAddFd, qemuMonitorRemoveFd):
New prototypes.
* src/qemu/qemu_monitor_json.c (qemuMonitorJSONAddFd)
(qemuMonitorJSONRemoveFd): New functions.
* src/qemu/qemu_monitor_json.h (qemuMonitorJSONAddFd)
(qemuMonitorJSONRemoveFd): New prototypes.
---
src/qemu/qemu_monitor.c | 74 +++++++++++++++++++++++++++++++++++++++++++-
src/qemu/qemu_monitor.h | 9 +++---
src/qemu/qemu_monitor_json.c | 73 ++++++++++++++++++++++++++++++++++++++++++-
src/qemu/qemu_monitor_json.h | 5 ++-
4 files changed, 154 insertions(+), 7 deletions(-)
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index a160c9a..3f1aed8 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -1,7 +1,7 @@
/*
* qemu_monitor.c: interaction with QEMU monitor console
*
- * Copyright (C) 2006-2012 Red Hat, Inc.
+ * Copyright (C) 2006-2013 Red Hat, Inc.
* Copyright (C) 2006 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
@@ -2353,6 +2353,78 @@ cleanup:
}
+/* Add the open file descriptor FD into the non-negative set FDSET.
+ * If NAME is present, it will be passed along for logging purposes.
+ * Returns the counterpart fd that qemu received, or -1 on error. */
+int
+qemuMonitorAddFd(qemuMonitorPtr mon, int fdset, int fd, const char *name)
+{
+ int ret = -1;
+ VIR_DEBUG("mon=%p, fdset=%d, fd=%d, name=%s",
+ mon, fdset, fd, NULLSTR(name));
+
+ if (!mon) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("monitor must not be NULL"));
+ return -1;
+ }
+
+ if (fd < 0 || fdset < 0) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("fd and fdset must be valid"));
+ return -1;
+ }
+
+ if (!mon->hasSendFD) {
+ virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
+ _("qemu is not using a unix socket monitor, "
+ "cannot send fd %s"), NULLSTR(name));
+ return -1;
+ }
+
+ if (mon->json)
+ ret = qemuMonitorJSONAddFd(mon, fdset, fd, name);
+ else
+ virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+ _("add fd requires JSON monitor"));
+ return ret;
+}
+
+
+/* Remove one of qemu's fds from the given FDSET, or if FD is
+ * negative, remove the entire set. Preserve any previous error on
+ * entry. Returns 0 on success, -1 on error. */
+int
+qemuMonitorRemoveFd(qemuMonitorPtr mon, int fdset, int fd)
+{
+ int ret = -1;
+ virErrorPtr error;
+
+ VIR_DEBUG("mon=%p, fdset=%d, fd=%d", mon, fdset, fd);
+
+ error = virSaveLastError();
+
+ if (!mon) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("monitor must not be NULL"));
+ goto cleanup;
+ }
+
+ if (mon->json)
+ ret = qemuMonitorJSONRemoveFd(mon, fdset, fd);
+ else
+ virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+ _("remove fd requires JSON monitor"));
+
+cleanup:
+ if (error) {
+ virSetError(error);
+ virFreeError(error);
+ }
+ return ret;
+}
+
+
int qemuMonitorAddHostNetwork(qemuMonitorPtr mon,
const char *netstr,
int tapfd, const char *tapfd_name,
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 7953b82..ac77158 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -1,7 +1,7 @@
/*
* qemu_monitor.h: interaction with QEMU monitor console
*
- * Copyright (C) 2006-2012 Red Hat, Inc.
+ * Copyright (C) 2006-2013 Red Hat, Inc.
* Copyright (C) 2006 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
@@ -439,13 +439,14 @@ int qemuMonitorRemovePCIDevice(qemuMonitorPtr mon,
int qemuMonitorSendFileHandle(qemuMonitorPtr mon,
const char *fdname,
int fd);
+int qemuMonitorAddFd(qemuMonitorPtr mon, int fdset, int fd, const char *name);
-/* The function preserves previous error and only sets it's own error if no
- * error was set before.
+/* These two functions preserve previous error and only set their own
+ * error if no error was set before.
*/
int qemuMonitorCloseFileHandle(qemuMonitorPtr mon,
const char *fdname);
-
+int qemuMonitorRemoveFd(qemuMonitorPtr mon, int fdset, int fd);
/* XXX do we really want to hardcode 'netstr' as the
* sendable item here
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 2d2a5d0..686cee9 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -1,7 +1,7 @@
/*
* qemu_monitor_json.c: interaction with QEMU monitor console
*
- * Copyright (C) 2006-2012 Red Hat, Inc.
+ * Copyright (C) 2006-2013 Red Hat, Inc.
* Copyright (C) 2006 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
@@ -2646,6 +2646,77 @@ int qemuMonitorJSONCloseFileHandle(qemuMonitorPtr mon,
}
+int
+qemuMonitorJSONAddFd(qemuMonitorPtr mon, int fdset, int fd, const char *name)
+{
+ int ret;
+ virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("add-fd",
+ "i:fdset-id", fdset,
+ name ? "s:opaque" : NULL,
+ name, NULL);
+ virJSONValuePtr reply = NULL;
+ if (!cmd)
+ return -1;
+
+ ret = qemuMonitorJSONCommandWithFd(mon, cmd, fd, &reply);
+
+ if (ret == 0)
+ ret = qemuMonitorJSONCheckError(cmd, reply);
+ if (ret == 0) {
+ virJSONValuePtr data = virJSONValueObjectGet(reply, "return");
+
+ if (!data || data->type != VIR_JSON_TYPE_OBJECT) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("missing return information"));
+ goto error;
+ }
+ data = virJSONValueObjectGet(data, "fd");
+ if (!data || data->type != VIR_JSON_TYPE_NUMBER ||
+ virJSONValueGetNumberInt(data, &ret) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("incomplete return information"));
+ goto error;
+ }
+ }
+
+cleanup:
+ virJSONValueFree(cmd);
+ virJSONValueFree(reply);
+ return ret;
+
+error:
+ /* Best effort cleanup - kill the entire fdset (even if it has
+ * earlier successful fd registrations), since we don't know which
+ * fd qemu got, and don't want to leave the fd leaked in qemu. */
+ qemuMonitorJSONRemoveFd(mon, fdset, -1);
+ ret = -1;
+ goto cleanup;
+}
+
+
+int
+qemuMonitorJSONRemoveFd(qemuMonitorPtr mon, int fdset, int fd)
+{
+ int ret;
+ virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("remove-fd",
+ "i:fdset-id", fdset,
+ fd < 0 ? NULL :
"i:fd",
+ fd, NULL);
+ virJSONValuePtr reply = NULL;
+ if (!cmd)
+ return -1;
+
+ ret = qemuMonitorJSONCommand(mon, cmd, &reply);
+
+ if (ret == 0)
+ ret = qemuMonitorJSONCheckError(cmd, reply);
+
+ virJSONValueFree(cmd);
+ virJSONValueFree(reply);
+ return ret;
+}
+
+
int qemuMonitorJSONAddNetdev(qemuMonitorPtr mon,
const char *netdevstr)
{
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index 2b09a8f..925d937 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -1,7 +1,7 @@
/*
* qemu_monitor_json.h: interaction with QEMU monitor console
*
- * Copyright (C) 2006-2009, 2011-2012 Red Hat, Inc.
+ * Copyright (C) 2006-2009, 2011-2013 Red Hat, Inc.
* Copyright (C) 2006 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
@@ -175,9 +175,12 @@ int qemuMonitorJSONRemovePCIDevice(qemuMonitorPtr mon,
int qemuMonitorJSONSendFileHandle(qemuMonitorPtr mon,
const char *fdname,
int fd);
+int qemuMonitorJSONAddFd(qemuMonitorPtr mon, int fdset, int fd,
+ const char *name);
int qemuMonitorJSONCloseFileHandle(qemuMonitorPtr mon,
const char *fdname);
+int qemuMonitorJSONRemoveFd(qemuMonitorPtr mon, int fdset, int fd);
int qemuMonitorJSONAddNetdev(qemuMonitorPtr mon,
const char *netdevstr);
--
1.8.1