From patchwork Fri Jun 8 17:09:26 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= X-Patchwork-Id: 926920 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 412TWf5jZ1z9s1B for ; Sat, 9 Jun 2018 03:13:18 +1000 (AEST) Received: from localhost ([::1]:37168 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fRKwu-0001CJ-CI for incoming@patchwork.ozlabs.org; Fri, 08 Jun 2018 13:13:16 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:39257) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fRKtT-000787-Li for qemu-devel@nongnu.org; Fri, 08 Jun 2018 13:09:45 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fRKtQ-0008Iy-Lx for qemu-devel@nongnu.org; Fri, 08 Jun 2018 13:09:43 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:48094 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fRKtQ-0008IY-GN; Fri, 08 Jun 2018 13:09:40 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 07002402315E; Fri, 8 Jun 2018 17:09:40 +0000 (UTC) Received: from t460.redhat.com (unknown [10.33.36.81]) by smtp.corp.redhat.com (Postfix) with ESMTP id 407332166BB2; Fri, 8 Jun 2018 17:09:38 +0000 (UTC) From: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= To: qemu-devel@nongnu.org Date: Fri, 8 Jun 2018 18:09:26 +0100 Message-Id: <20180608170933.9137-2-berrange@redhat.com> In-Reply-To: <20180608170933.9137-1-berrange@redhat.com> References: <20180608170933.9137-1-berrange@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Fri, 08 Jun 2018 17:09:40 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Fri, 08 Jun 2018 17:09:40 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'berrange@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH 1/8] util: add helper APIs for dealing with inotify X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: qemu-trivial@nongnu.org, Michael Tokarev , Laurent Vivier , Markus Armbruster , Gerd Hoffmann , =?utf-8?q?Andreas_F=C3=A4rber?= , "Dr. David Alan Gilbert" Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" 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é Reviewed-by: Gerd Hoffmann --- 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 +S: Odd fixes +F: util/inotify.c +F: include/qemu/inotify.h + Throttling infrastructure M: Alberto Garcia 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 . + * + */ + +#ifndef QEMU_INOTIFY_H +#define QEMU_INOTIFY_H + +#include "qemu-common.h" +#ifdef CONFIG_INOTIFY1 +#include +#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 . + * + */ + +#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 +}