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@xxxxxxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list