[libvirt PATCH v5 4/6] qemu: add monitor functions for handling file descriptors

Jonathon Jongsma jjongsma at redhat.com
Wed Oct 14 17:08:28 UTC 2020


add-fd, remove-fd, and query-fdsets provide functionality that can be
used for passing fds to qemu and closing fdsets that are no longer
necessary.

Signed-off-by: Jonathon Jongsma <jjongsma at redhat.com>
---
 src/qemu/qemu_monitor.c      |  93 +++++++++++++++++++
 src/qemu/qemu_monitor.h      |  41 +++++++++
 src/qemu/qemu_monitor_json.c | 173 +++++++++++++++++++++++++++++++++++
 src/qemu/qemu_monitor_json.h |  12 +++
 4 files changed, 319 insertions(+)

diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 8c991fefbb..594d701c48 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -2649,6 +2649,99 @@ qemuMonitorGraphicsRelocate(qemuMonitorPtr mon,
 }
 
 
+/**
+ * qemuMonitorAddFileHandleToSet:
+ * @mon: monitor object
+ * @fd: file descriptor to pass to qemu
+ * @fdset: the fdset to register this fd with, -1 to create a new fdset
+ * @opaque: opaque data to associated with this fd
+ * @info: structure that will be updated with the fd and fdset returned by qemu
+ *
+ * Attempts to register a file descriptor with qemu that can then be referenced
+ * via the file path /dev/fdset/$FDSETID
+ * Returns 0 if ok, and -1 on failure */
+int
+qemuMonitorAddFileHandleToSet(qemuMonitorPtr mon,
+                              int fd,
+                              int fdset,
+                              const char *opaque,
+                              qemuMonitorAddFdInfoPtr info)
+{
+    VIR_DEBUG("fd=%d,fdset=%i,opaque=%s", fd, fdset, opaque);
+
+    QEMU_CHECK_MONITOR(mon);
+
+    if (fd < 0) {
+        virReportError(VIR_ERR_INVALID_ARG, "%s",
+                       _("fd must be valid"));
+        return -1;
+    }
+
+    return qemuMonitorJSONAddFileHandleToSet(mon, fd, fdset, opaque, info);
+}
+
+
+/**
+ * qemuMonitorRemoveFdset:
+ * @mon: monitor object
+ * @fdset: the fdset to remove
+ *
+ * Attempts to remove a fdset from qemu and close associated file descriptors
+ * Returns 0 if ok, and -1 on failure */
+int
+qemuMonitorRemoveFdset(qemuMonitorPtr mon,
+                       int fdset)
+{
+    VIR_DEBUG("fdset=%d", fdset);
+
+    QEMU_CHECK_MONITOR(mon);
+
+    if (fdset < 0) {
+        virReportError(VIR_ERR_INVALID_ARG, "%s",
+                       _("fdset must be valid"));
+        return -1;
+    }
+
+    return qemuMonitorJSONRemoveFdset(mon, fdset);
+}
+
+
+void qemuMonitorFdsetsFree(qemuMonitorFdsetsPtr fdsets)
+{
+    size_t i;
+
+    for (i = 0; i < fdsets->nfdsets; i++) {
+        size_t j;
+        qemuMonitorFdsetInfoPtr set = &fdsets->fdsets[i];
+
+        for (j = 0; j < set->nfds; j++)
+            g_free(set->fds[j].opaque);
+    }
+    g_free(fdsets->fdsets);
+    g_free(fdsets);
+}
+
+
+/**
+ * qemuMonitorQueryFdsets:
+ * @mon: monitor object
+ * @fdsets: a pointer that is filled with a new qemuMonitorFdsets struct
+ *
+ * Queries qemu for the fdsets that are registered with that instance, and
+ * returns a structure describing those fdsets. The returned struct should be
+ * freed with qemuMonitorFdsetsFree();
+ *
+ * Returns 0 if ok, and -1 on failure */
+int
+qemuMonitorQueryFdsets(qemuMonitorPtr mon,
+                       qemuMonitorFdsetsPtr *fdsets)
+{
+    QEMU_CHECK_MONITOR(mon);
+
+    return qemuMonitorJSONQueryFdsets(mon, fdsets);
+}
+
+
 int
 qemuMonitorSendFileHandle(qemuMonitorPtr mon,
                           const char *fdname,
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index a744c8975b..a372ba1eda 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -880,6 +880,47 @@ int qemuMonitorGraphicsRelocate(qemuMonitorPtr mon,
                                 int tlsPort,
                                 const char *tlsSubject);
 
+typedef struct _qemuMonitorAddFdInfo qemuMonitorAddFdInfo;
+typedef qemuMonitorAddFdInfo *qemuMonitorAddFdInfoPtr;
+struct _qemuMonitorAddFdInfo {
+    int fd;
+    int fdset;
+};
+int
+qemuMonitorAddFileHandleToSet(qemuMonitorPtr mon,
+                              int fd,
+                              int fdset,
+                              const char *opaque,
+                              qemuMonitorAddFdInfoPtr info);
+
+int
+qemuMonitorRemoveFdset(qemuMonitorPtr mon,
+                       int fdset);
+
+typedef struct _qemuMonitorFdsetFdInfo qemuMonitorFdsetFdInfo;
+typedef qemuMonitorFdsetFdInfo *qemuMonitorFdsetFdInfoPtr;
+struct _qemuMonitorFdsetFdInfo {
+    int fd;
+    char *opaque;
+};
+typedef struct _qemuMonitorFdsetInfo qemuMonitorFdsetInfo;
+typedef qemuMonitorFdsetInfo *qemuMonitorFdsetInfoPtr;
+struct _qemuMonitorFdsetInfo {
+    int id;
+    qemuMonitorFdsetFdInfoPtr fds;
+    int nfds;
+};
+typedef struct _qemuMonitorFdsets qemuMonitorFdsets;
+typedef qemuMonitorFdsets *qemuMonitorFdsetsPtr;
+struct _qemuMonitorFdsets {
+    qemuMonitorFdsetInfoPtr fdsets;
+    int nfdsets;
+};
+void qemuMonitorFdsetsFree(qemuMonitorFdsetsPtr fdsets);
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(qemuMonitorFdsets, qemuMonitorFdsetsFree);
+int qemuMonitorQueryFdsets(qemuMonitorPtr mon,
+                           qemuMonitorFdsetsPtr *fdsets);
+
 int qemuMonitorSendFileHandle(qemuMonitorPtr mon,
                               const char *fdname,
                               int fd);
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 26ac499fc5..1b77adfbcd 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -3929,6 +3929,179 @@ int qemuMonitorJSONGraphicsRelocate(qemuMonitorPtr mon,
 }
 
 
+static int
+qemuAddfdInfoParse(virJSONValuePtr msg,
+                   qemuMonitorAddFdInfoPtr fdinfo)
+{
+    virJSONValuePtr returnObj;
+
+    if (!(returnObj = virJSONValueObjectGetObject(msg, "return"))) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Missing or invalid return data in add-fd response"));
+        return -1;
+    }
+
+    if (virJSONValueObjectGetNumberInt(returnObj, "fd", &fdinfo->fd) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Missing or invalid fd in add-fd response"));
+        return -1;
+    }
+
+    if (virJSONValueObjectGetNumberInt(returnObj, "fdset-id", &fdinfo->fdset) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Missing or invalid fdset-id in add-fd response"));
+        return -1;
+    }
+
+    return 0;
+}
+
+
+/* if fdset is negative, qemu will create a new fdset and add the fd to that */
+int qemuMonitorJSONAddFileHandleToSet(qemuMonitorPtr mon,
+                                      int fd,
+                                      int fdset,
+                                      const char *opaque,
+                                      qemuMonitorAddFdInfoPtr fdinfo)
+{
+    virJSONValuePtr args = NULL;
+    g_autoptr(virJSONValue) reply = NULL;
+    g_autoptr(virJSONValue) cmd = NULL;
+
+    if (virJSONValueObjectCreate(&args, "S:opaque", opaque, NULL) < 0)
+        return -1;
+
+    if (fdset >= 0)
+        if (virJSONValueObjectAdd(args, "j:fdset-id", fdset, NULL) < 0)
+            return -1;
+
+    if (!(cmd = qemuMonitorJSONMakeCommandInternal("add-fd", args)))
+        return -1;
+
+    if (qemuMonitorJSONCommandWithFd(mon, cmd, fd, &reply) < 0)
+        return -1;
+
+    if (qemuMonitorJSONCheckError(cmd, reply) < 0)
+        return -1;
+
+    if (qemuAddfdInfoParse(reply, fdinfo) < 0)
+        return -1;
+
+    return 0;
+}
+
+static int
+qemuMonitorJSONQueryFdsetsParse(virJSONValuePtr msg,
+                                qemuMonitorFdsetsPtr *fdsets)
+{
+    virJSONValuePtr returnArray, entry;
+    size_t i;
+    g_autoptr(qemuMonitorFdsets) sets = g_new0(qemuMonitorFdsets, 1);
+    int ninfo;
+
+    returnArray = virJSONValueObjectGetArray(msg, "return");
+
+    ninfo = virJSONValueArraySize(returnArray);
+    if (ninfo > 0)
+        sets->fdsets = g_new0(qemuMonitorFdsetInfo, ninfo);
+    sets->nfdsets = ninfo;
+
+    for (i = 0; i < ninfo; i++) {
+        size_t j;
+        const char *tmp;
+        virJSONValuePtr fdarray;
+        qemuMonitorFdsetInfoPtr fdsetinfo = &sets->fdsets[i];
+
+        if (!(entry = virJSONValueArrayGet(returnArray, i))) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("query-fdsets return data missing fdset array element"));
+            return -1;
+        }
+
+        if (virJSONValueObjectGetNumberInt(entry, "fdset-id", &fdsetinfo->id) < 0) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("query-fdsets reply was missing 'fdset-id'"));
+            return -1;
+
+        }
+
+        fdarray = virJSONValueObjectGetArray(entry, "fds");
+        fdsetinfo->nfds = virJSONValueArraySize(fdarray);
+        if (fdsetinfo->nfds > 0)
+            fdsetinfo->fds = g_new0(qemuMonitorFdsetFdInfo, fdsetinfo->nfds);
+
+        for (j = 0; j < fdsetinfo->nfds; j++) {
+            qemuMonitorFdsetFdInfoPtr fdinfo = &fdsetinfo->fds[j];
+            virJSONValuePtr fdentry;
+
+            if (!(fdentry = virJSONValueArrayGet(fdarray, j))) {
+                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                               _("query-fdsets return data missing fd array element"));
+                return -1;
+            }
+
+            if (virJSONValueObjectGetNumberInt(fdentry, "fd", &fdinfo->fd) < 0) {
+                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                               _("query-fdsets return data missing 'fd'"));
+                return -1;
+            }
+
+            /* opaque is optional and may be missing */
+            tmp = virJSONValueObjectGetString(fdentry, "opaque");
+            if (tmp)
+                fdinfo->opaque = g_strdup(tmp);
+        }
+    }
+
+    *fdsets = g_steal_pointer(&sets);
+    return 0;
+}
+
+
+int qemuMonitorJSONQueryFdsets(qemuMonitorPtr mon,
+                               qemuMonitorFdsetsPtr *fdsets)
+{
+    g_autoptr(virJSONValue) reply = NULL;
+    g_autoptr(virJSONValue) cmd = qemuMonitorJSONMakeCommand("query-fdsets",
+                                                             NULL);
+
+    if (!cmd)
+        return -1;
+
+    if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
+        return -1;
+
+    if (qemuMonitorJSONCheckError(cmd, reply) < 0)
+        return -1;
+
+    if (qemuMonitorJSONQueryFdsetsParse(reply, fdsets) < 0)
+        return -1;
+
+    return 0;
+}
+
+
+int qemuMonitorJSONRemoveFdset(qemuMonitorPtr mon,
+                               int fdset)
+{
+    g_autoptr(virJSONValue) reply = NULL;
+    g_autoptr(virJSONValue) cmd = qemuMonitorJSONMakeCommand("remove-fd",
+                                                             "i:fdset-id", fdset,
+                                                             NULL);
+
+    if (!cmd)
+        return -1;
+
+    if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
+        return -1;
+
+    if (qemuMonitorJSONCheckError(cmd, reply) < 0)
+        return -1;
+
+    return 0;
+}
+
+
 int qemuMonitorJSONSendFileHandle(qemuMonitorPtr mon,
                                   const char *fdname,
                                   int fd)
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index 098ab857be..2b9a42efe0 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -202,6 +202,18 @@ int qemuMonitorJSONAddPCINetwork(qemuMonitorPtr mon,
 int qemuMonitorJSONRemovePCIDevice(qemuMonitorPtr mon,
                                    virPCIDeviceAddress *guestAddr);
 
+int qemuMonitorJSONAddFileHandleToSet(qemuMonitorPtr mon,
+                                      int fd,
+                                      int fdset,
+                                      const char *opaque,
+                                      qemuMonitorAddFdInfoPtr info);
+
+int qemuMonitorJSONRemoveFdset(qemuMonitorPtr mon,
+                               int fdset);
+
+int qemuMonitorJSONQueryFdsets(qemuMonitorPtr mon,
+                               qemuMonitorFdsetsPtr *fdsets);
+
 int qemuMonitorJSONSendFileHandle(qemuMonitorPtr mon,
                                   const char *fdname,
                                   int fd);
-- 
2.26.2




More information about the libvir-list mailing list