qemu-trivial
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-trivial] [PATCH 1/8] util: add helper APIs for dealing with inotif


From: Daniel P . Berrangé
Subject: [Qemu-trivial] [PATCH 1/8] util: add helper APIs for dealing with inotify
Date: Fri, 8 Jun 2018 18:09:26 +0100

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é <address@hidden>
---
 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

diff --git a/MAINTAINERS b/MAINTAINERS
index 41cd3736a9..3610479af7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1766,6 +1766,12 @@ F: include/qemu/sockets.h
 F: util/qemu-sockets.c
 F: qapi/sockets.json
 
+Inotify
+M: Daniel P. Berrange <address@hidden>
+S: Odd fixes
+F: util/inotify.c
+F: include/qemu/inotify.h
+
 Throttling infrastructure
 M: Alberto Garcia <address@hidden>
 S: Supported
diff --git a/include/qemu/inotify.h b/include/qemu/inotify.h
new file mode 100644
index 0000000000..d78d04c5bb
--- /dev/null
+++ b/include/qemu/inotify.h
@@ -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 */
diff --git a/util/Makefile.objs b/util/Makefile.objs
index e1c3fed4dc..4c1b44d019 100644
--- a/util/Makefile.objs
+++ b/util/Makefile.objs
@@ -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
diff --git a/util/inotify.c b/util/inotify.c
new file mode 100644
index 0000000000..dd9c194bea
--- /dev/null
+++ b/util/inotify.c
@@ -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
+}
-- 
2.17.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]