Hi guys, As I mentioned, we are working in a project that introduces a hook for QEMU. And when someone installs the RPM/DEB package with this hook, we need to restart the libvirtd service everytime. It is really annoying for users. In my opinion, we can include an #if and #else to compile with inotify support. But, I don't see any good reason to add. Julio Cesar Faracco 2016-09-12 21:21 GMT-03:00 Julio Faracco <jcfaracco@xxxxxxxxx>: > Libvirtd only support hooks when the daemon is started. Hooks cannot be > loaded when the daemon is already running. So, to load a hook you need to > restart the service everytime. Now, the inotify support enables the option > of create a hook and run it even if libvirtd was started. > > Cc: Carlos Castilho <ccasti@xxxxxxxxxx> > Signed-off-by: Julio Faracco <jcfaracco@xxxxxxxxx> > --- > daemon/libvirtd.c | 1 + > src/libvirt_private.syms | 1 + > src/util/virhook.c | 165 ++++++++++++++++++++++++++++++++++++++++++++++- > src/util/virhook.h | 10 +++ > 4 files changed, 175 insertions(+), 2 deletions(-) > > diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c > index 95c1b1c..56175d1 100644 > --- a/daemon/libvirtd.c > +++ b/daemon/libvirtd.c > @@ -1622,6 +1622,7 @@ int main(int argc, char **argv) { > 0, "shutdown", NULL, NULL); > > cleanup: > + virHookCleanUp(); > virNetlinkEventServiceStopAll(); > virObjectUnref(remoteProgram); > virObjectUnref(lxcProgram); > diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms > index 6a77e46..c8ad816 100644 > --- a/src/libvirt_private.syms > +++ b/src/libvirt_private.syms > @@ -1648,6 +1648,7 @@ virHashValueFree; > virHookCall; > virHookInitialize; > virHookPresent; > +virHookCleanUp; > > > # util/virhostdev.h > diff --git a/src/util/virhook.c b/src/util/virhook.c > index facd74a..d5fc928 100644 > --- a/src/util/virhook.c > +++ b/src/util/virhook.c > @@ -26,6 +26,7 @@ > #include <sys/types.h> > #include <sys/wait.h> > #include <sys/stat.h> > +#include <sys/inotify.h> > #include <unistd.h> > #include <stdlib.h> > #include <stdio.h> > @@ -45,6 +46,10 @@ VIR_LOG_INIT("util.hook"); > > #define LIBVIRT_HOOK_DIR SYSCONFDIR "/libvirt/hooks" > > +#define virHookInstall(driver) virHooksFound |= (1 << driver); > + > +#define virHookUninstall(driver) virHooksFound ^= (1 << driver); > + > VIR_ENUM_DECL(virHookDriver) > VIR_ENUM_DECL(virHookDaemonOp) > VIR_ENUM_DECL(virHookSubop) > @@ -109,6 +114,8 @@ VIR_ENUM_IMPL(virHookLibxlOp, VIR_HOOK_LIBXL_OP_LAST, > > static int virHooksFound = -1; > > +static virHookInotifyPtr virHooksInotify = NULL; > + > /** > * virHookCheck: > * @driver: the driver name "daemon", "qemu", "lxc"... > @@ -153,6 +160,121 @@ virHookCheck(int no, const char *driver) > return ret; > } > > +/** > + * virHookInotifyEvent: > + * @fd: inotify file descriptor. > + * > + * Identifies file events at libvirt's hook directory. > + * Install or uninstall hooks on demand. Acording file manipulation. > + */ > +static void > +virHookInotifyEvent(int watch ATTRIBUTE_UNUSED, > + int fd, > + int events ATTRIBUTE_UNUSED, > + void *data ATTRIBUTE_UNUSED) > +{ > + char buf[1024]; > + struct inotify_event *e; > + int got; > + int driver; > + char *tmp, *name; > + > + VIR_DEBUG("inotify event in virHookInotify()"); > + > +reread: > + got = read(fd, buf, sizeof(buf)); > + if (got == -1) { > + if (errno == EINTR) > + goto reread; > + return; > + } > + > + tmp = buf; > + while (got) { > + if (got < sizeof(struct inotify_event)) > + return; > + > + 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) > + return; > + > + tmp += e->len; > + got -= e->len; > + > + name = (char *)&(e->name); > + > + /* Removing hook file. */ > + if (e->mask & (IN_DELETE | IN_MOVED_FROM)) { > + if ((driver = virHookDriverTypeFromString(name)) < 0) { > + VIR_DEBUG("Invalid hook name for %s", name); > + return; > + } > + > + virHookUninstall(driver); > + } > + > + /* Creating hook file. */ > + if (e->mask & (IN_CREATE | IN_CLOSE_WRITE | IN_MOVED_TO)) { > + if ((driver = virHookDriverTypeFromString(name)) < 0) { > + VIR_DEBUG("Invalid hook name for %s", name); > + return; > + } > + > + virHookInstall(driver); > + } > + } > +} > + > +/** > + * virHookInotifyInit: > + * > + * Initialize inotify hooks support. > + * Enable hooks installation on demand. > + * > + * Returns 0 if inotify was successfully installed, -1 in case of failure. > + */ > +static int > +virHookInotifyInit(void) { > + > + if (VIR_ALLOC(virHooksInotify) < 0) > + goto error; > + > + if ((virHooksInotify->inotifyFD = inotify_init()) < 0) { > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("cannot initialize inotify")); > + goto error; > + } > + > + if ((virHooksInotify->inotifyWatch = > + inotify_add_watch(virHooksInotify->inotifyFD, > + LIBVIRT_HOOK_DIR, > + IN_CREATE | IN_MODIFY | IN_DELETE)) < 0) { > + virReportSystemError(errno, _("Failed to create inotify watch on %s"), > + LIBVIRT_HOOK_DIR); > + goto error; > + } > + > + if ((virHooksInotify->inotifyHandler = > + virEventAddHandle(virHooksInotify->inotifyFD, > + VIR_EVENT_HANDLE_READABLE, > + virHookInotifyEvent, NULL, NULL)) < 0) { > + VIR_DEBUG("Failed to add inotify handle in virHook."); > + goto error; > + } > + > + return 0; > + > +error: > + virHookCleanUp(); > + return -1; > +} > + > + > /* > * virHookInitialize: > * > @@ -174,10 +296,14 @@ virHookInitialize(void) > return -1; > > if (res == 1) { > - virHooksFound |= (1 << i); > + virHookInstall(i); > ret++; > } > } > + > + if (virHookInotifyInit() < 0) > + VIR_INFO("Disabling hooks inotify support."); > + > return ret; > } > > @@ -309,7 +435,12 @@ virHookCall(int driver, > if (output) > virCommandSetOutputBuffer(cmd, output); > > - ret = virCommandRun(cmd, NULL); > + ret = virHookCheck(driver, virHookDriverTypeToString(driver)); > + > + if (ret > 0) { > + ret = virCommandRun(cmd, NULL); > + } > + > if (ret < 0) { > /* Convert INTERNAL_ERROR into known error. */ > virReportError(VIR_ERR_HOOK_SCRIPT_FAILED, "%s", > @@ -322,3 +453,33 @@ virHookCall(int driver, > > return ret; > } > + > +/** > + * virHookCall: > + * > + * Release all structures and data used in virhooks. > + * > + * Returns: 0 if the execution succeeded > + */ > +int > +virHookCleanUp(void) > +{ > + if (!virHooksInotify) > + return -1; > + > + if ((virHooksInotify->inotifyFD >= 0) && > + (virHooksInotify->inotifyWatch >= 0)) > + if (inotify_rm_watch(virHooksInotify->inotifyFD, > + virHooksInotify->inotifyWatch) < 0) > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Cannot remove inotify watcher.")); > + > + if (virHooksInotify->inotifyHandler >= 0) > + virEventRemoveHandle(virHooksInotify->inotifyHandler); > + > + VIR_FORCE_CLOSE(virHooksInotify->inotifyFD); > + VIR_FREE(virHooksInotify); > + > + virHooksFound = -1; > + > + return 0; > +} > diff --git a/src/util/virhook.h b/src/util/virhook.h > index 205249c..47a32c7 100644 > --- a/src/util/virhook.h > +++ b/src/util/virhook.h > @@ -100,6 +100,14 @@ typedef enum { > VIR_HOOK_LIBXL_OP_LAST, > } virHookLibxlOpType; > > +struct _virHookInotify { > + int inotifyFD; > + int inotifyWatch; > + int inotifyHandler; > +}; > + > +typedef struct _virHookInotify *virHookInotifyPtr; > + > int virHookInitialize(void); > > int virHookPresent(int driver); > @@ -107,4 +115,6 @@ int virHookPresent(int driver); > int virHookCall(int driver, const char *id, int op, int sub_op, > const char *extra, const char *input, char **output); > > +int virHookCleanUp(void); > + > #endif /* __VIR_HOOKS_H__ */ > -- > 2.7.4 > -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list