[libvirt] [patch v3 2/2] add inotify handler to qemu driver

Chen Fan chen.fan.fnst at cn.fujitsu.com
Wed May 7 10:11:50 UTC 2014


we don't expect to reload 'migrate_uri' with restarting libvirtd everytime while
updating the URI, so adding inotify handler to reload 'migrate_uri' configuration
without restarting libvirtd, it will be also helpful for virt-manager to get
'migrate_uri'.

Signed-off-by: Chen Fan <chen.fan.fnst at cn.fujitsu.com>
---
 src/qemu/qemu_conf.c   | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_conf.h   |  9 +++++-
 src/qemu/qemu_driver.c | 25 ++++++++++++++-
 3 files changed, 119 insertions(+), 2 deletions(-)

diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 0bd943d..e50fdb8 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -33,6 +33,7 @@
 #include <fcntl.h>
 #include <sys/wait.h>
 #include <arpa/inet.h>
+#include <sys/inotify.h>
 
 #include "virerror.h"
 #include "qemu_conf.h"
@@ -1431,3 +1432,89 @@ qemuTranslateSnapshotDiskSourcePool(virConnectPtr conn ATTRIBUTE_UNUSED,
                    _("Snapshots are not yet supported with 'pool' volumes"));
     return -1;
 }
+
+void
+qemuInotifyEvent(int watch,
+                 int fd,
+                 int events ATTRIBUTE_UNUSED,
+                 void *data)
+{
+    char buf[1024];
+    char filename[1024];
+    struct inotify_event *e;
+    int got;
+    char *tmp, *name;
+    virQEMUDriverPtr driver = data;
+    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
+    virConfPtr conf;
+    virConfValuePtr p;
+
+    qemuDriverLock(driver);
+    if (watch != driver->inotifyWatch)
+        goto cleanup;
+
+ reread:
+    got = read(fd, buf, sizeof(buf));
+    if (got == -1) {
+        if (errno == EINTR)
+            goto reread;
+        goto cleanup;
+    }
+
+    tmp = buf;
+    while (got) {
+        if (got < sizeof(struct inotify_event))
+            goto cleanup; /* bad */
+
+        VIR_WARNINGS_NO_CAST_ALIGN
+        e = (struct inotify_event *)tmp;
+        VIR_WARNINGS_RESET
+
+        tmp += sizeof(struct inotify_event);
+        got -= sizeof(struct inotify_event);
+
+        if (got < e->len)
+            goto cleanup;
+
+        tmp += e->len;
+        got -= e->len;
+
+        name = (char *)&(e->name);
+
+        if (STRNEQ(name, "qemu.conf")) {
+            continue;
+        }
+
+        snprintf(filename, 1024, "%s/qemu.conf",
+                 cfg->configBaseDir);
+
+        if (e->mask & (IN_CREATE | IN_CLOSE_WRITE | IN_MOVED_TO)) {
+            char *str;
+            VIR_DEBUG("Got inotify '%s' modified", filename);
+            if (!(conf = virConfReadFile(filename, 0)))
+                goto cleanup;
+
+            p = virConfGetValue(conf, "migrate_uri");
+            if (p && p->type != VIR_CONF_STRING) {
+                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                               _("Expected a string for 'migrate_uri' config parameter"));
+                virConfFree(conf);
+                goto cleanup;
+            }
+
+            if (p) {
+               str = p->str;
+            } else {
+               str = NULL;
+            }
+
+            VIR_FREE(cfg->migrateUri);
+            if (VIR_STRDUP(cfg->migrateUri, str) < 0)
+                virConfFree(conf);
+                goto cleanup;
+        }
+    }
+
+ cleanup:
+    qemuDriverUnlock(driver);
+}
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index 2e45421..2cc62f9 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -240,6 +240,10 @@ struct _virQEMUDriver {
 
     /* Immutable pointer, self-clocking APIs */
     virCloseCallbacksPtr closeCallbacks;
+
+    /* The inotify fd */
+    int inotifyFD;
+    int inotifyWatch;
 };
 
 typedef struct _qemuDomainCmdlineDef qemuDomainCmdlineDef;
@@ -309,5 +313,8 @@ int qemuTranslateDiskSourcePool(virConnectPtr conn,
 
 int qemuTranslateSnapshotDiskSourcePool(virConnectPtr conn,
                                         virDomainSnapshotDiskDefPtr def);
-
+void qemuInotifyEvent(int watch,
+                      int fd,
+                      int events ATTRIBUTE_UNUSED,
+                      void *data);
 #endif /* __QEMUD_CONF_H */
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index fca1a91..83122d8 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -42,7 +42,7 @@
 #include <sys/ioctl.h>
 #include <sys/un.h>
 #include <byteswap.h>
-
+#include <sys/inotify.h>
 
 #include "qemu_driver.h"
 #include "qemu_agent.h"
@@ -596,6 +596,7 @@ qemuStateInitialize(bool privileged,
 
     /* Don't have a dom0 so start from 1 */
     qemu_driver->nextvmid = 1;
+    qemu_driver->inotifyWatch = -1;
 
     if (!(qemu_driver->domains = virDomainObjListNew()))
         goto error;
@@ -750,6 +751,28 @@ qemuStateInitialize(bool privileged,
     if (!(qemu_driver->xmlopt = virQEMUDriverCreateXMLConf(qemu_driver)))
         goto error;
 
+    if ((qemu_driver->inotifyFD = inotify_init()) < 0) {
+        VIR_ERROR(_("cannot initialize inotify"));
+        goto error;
+    }
+
+    VIR_INFO("Adding inotify watch on %s", cfg->configBaseDir);
+    if (inotify_add_watch(qemu_driver->inotifyFD,
+                          cfg->configBaseDir,
+                          IN_CREATE |
+                          IN_CLOSE_WRITE | IN_DELETE |
+                          IN_MOVED_TO | IN_MOVED_FROM) < 0) {
+        VIR_ERROR(_("Failed to create inotify watch on %s: %s"),
+                  cfg->configBaseDir,
+                  virStrerror(errno, ebuf, sizeof(ebuf)));
+        goto error;
+    }
+
+    if ((qemu_driver->inotifyWatch =
+         virEventAddHandle(qemu_driver->inotifyFD, VIR_EVENT_HANDLE_READABLE,
+                           qemuInotifyEvent, qemu_driver, NULL)) < 0)
+        goto error;
+
     /* If hugetlbfs is present, then we need to create a sub-directory within
      * it, since we can't assume the root mount point has permissions that
      * will let our spawned QEMU instances use it.
-- 
1.8.1.4




More information about the libvir-list mailing list