@@ -1766,6 +1766,12 @@ F: include/qemu/sockets.h
F: util/qemu-sockets.c
F: qapi/sockets.json
+Inotify
+M: Daniel P. Berrange <berrange@redhat.com>
+S: Odd fixes
+F: util/inotify.c
+F: include/qemu/inotify.h
+
Throttling infrastructure
M: Alberto Garcia <berto@igalia.com>
S: Supported
new file mode 100644
@@ -0,0 +1,49 @@
+/*
+ * QEMU inotify helper
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef QEMU_INOTIFY_H
+#define QEMU_INOTIFY_H
+
+#include "qemu-common.h"
+#ifdef CONFIG_INOTIFY1
+#include <sys/inotify.h>
+#endif
+
+
+typedef struct QInotify QInotify;
+
+typedef void (*QInotifyHandler)(int wd,
+ uint32_t mask,
+ const char *name,
+ void *opaque);
+
+QInotify *qemu_inotify_new(QInotifyHandler cb,
+ void *opaque,
+ GDestroyNotify ffcb,
+ Error **errp);
+
+void qemu_inotify_free(QInotify *in);
+
+int qemu_inotify_add_watch(QInotify *in,
+ const char *path,
+ uint32_t mask,
+ Error **errp);
+
+#endif /* QEMU_INOTIFY_H */
@@ -48,4 +48,5 @@ util-obj-y += range.o
util-obj-y += stats64.o
util-obj-y += systemd.o
util-obj-y += iova-tree.o
+util-obj-y += inotify.o
util-obj-$(CONFIG_LINUX) += vfio-helpers.o
new file mode 100644
@@ -0,0 +1,138 @@
+/*
+ * QEMU inotify helper
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/inotify.h"
+#include "qemu/main-loop.h"
+#include "qemu/error-report.h"
+#include "qapi/error.h"
+
+struct QInotify {
+ int fd;
+ QInotifyHandler cb;
+ void *opaque;
+ GDestroyNotify ffcb;
+};
+
+#ifdef CONFIG_INOTIFY1
+static void qemu_inotify_watch(void *arg)
+{
+ QInotify *in = arg;
+ char buf[4096]
+ __attribute__ ((aligned(__alignof__(struct inotify_event))));
+ int used = 0;
+ int len = read(in->fd, buf, sizeof(buf));
+
+ if (len < 0) {
+ if (errno != EAGAIN) {
+ error_report("Failure monitoring inotify FD, disabling events");
+ goto error;
+ }
+
+ /* no more events right now */
+ return;
+ }
+
+ /* Loop over all events in the buffer */
+ while (used < len) {
+ struct inotify_event *ev =
+ (struct inotify_event *)buf + used;
+
+ in->cb(ev->wd, ev->mask, ev->name, in->opaque);
+
+ used += sizeof(struct inotify_event) + ev->len;
+ }
+
+ return;
+
+ error:
+ qemu_set_fd_handler(in->fd, NULL, NULL, NULL);
+ close(in->fd);
+ in->fd = -1;
+}
+#endif
+
+QInotify *qemu_inotify_new(QInotifyHandler cb,
+ void *opaque,
+ GDestroyNotify ffcb,
+ Error **errp)
+{
+#ifdef CONFIG_INOTIFY1
+ QInotify *in = g_new0(QInotify, 1);
+
+ in->fd = inotify_init1(IN_NONBLOCK);
+ if (in->fd == -1) {
+ error_setg_errno(errp, errno,
+ "Unable to initialize inotify");
+ g_free(in);
+ return NULL;
+ }
+ in->cb = cb;
+ in->opaque = opaque;
+ in->ffcb = ffcb;
+
+ qemu_set_fd_handler(in->fd, qemu_inotify_watch, NULL, in);
+
+ return in;
+#else
+ error_setg(errp, "Inotify not available on this platform");
+ return NULL;
+#endif
+
+}
+
+
+void qemu_inotify_free(QInotify *in)
+{
+ if (!in) {
+ return;
+ }
+
+ if (in->ffcb) {
+ in->ffcb(in->opaque);
+ }
+
+ if (in->fd != -1) {
+ qemu_set_fd_handler(in->fd, NULL, NULL, NULL);
+ close(in->fd);
+ g_free(in);
+ }
+}
+
+
+int qemu_inotify_add_watch(QInotify *in,
+ const char *path,
+ uint32_t mask,
+ Error **errp)
+{
+#ifdef CONFIG_INOTIFY1
+ int rv;
+ rv = inotify_add_watch(in->fd, path, mask);
+ if (rv < 0) {
+ error_setg_errno(errp, errno, "Unable to watch '%s'", path);
+ return -1;
+ }
+
+ return rv;
+#else
+ error_setg(errp, "Inotify not available on this platform");
+ return -1;
+#endif
+}
The inotify userspace API for reading events is quite horrible, so it is useful to wrap it in a more friendly API to avoid duplicating code across many users in QEMU. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- MAINTAINERS | 6 ++ include/qemu/inotify.h | 49 +++++++++++++++ util/Makefile.objs | 1 + util/inotify.c | 138 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 194 insertions(+) create mode 100644 include/qemu/inotify.h create mode 100644 util/inotify.c