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(a)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