From nobody Fri May 16 05:39:06 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1501227874598366.35932476536016; Fri, 28 Jul 2017 00:44:34 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 60123F2948; Fri, 28 Jul 2017 07:44:32 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 245065E264; Fri, 28 Jul 2017 07:44:32 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id AC9E71805977; Fri, 28 Jul 2017 07:44:31 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id v6S7iFih017004 for ; Fri, 28 Jul 2017 03:44:15 -0400 Received: by smtp.corp.redhat.com (Postfix) id 282655C898; Fri, 28 Jul 2017 07:44:15 +0000 (UTC) Received: from beluga.usersys.redhat.com (unknown [10.43.2.36]) by smtp.corp.redhat.com (Postfix) with ESMTP id 433FF5C88A; Fri, 28 Jul 2017 07:44:14 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 60123F2948 Authentication-Results: ext-mx10.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx10.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=libvir-list-bounces@redhat.com From: Erik Skultety To: libvir-list@redhat.com Date: Fri, 28 Jul 2017 09:44:00 +0200 Message-Id: <5e8537c13d3a6f37ba906434bf7eb0085bfbef08.1501226969.git.eskultet@redhat.com> In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-loop: libvir-list@redhat.com Cc: Erik Skultety Subject: [libvirt] [PATCH v2 3/5] udev: Convert udevEventHandleThread to an actual thread routine X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Fri, 28 Jul 2017 07:44:33 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Adjust udevEventHandleThread to be a proper thread routine running in an infinite loop handling devices. Also introduce udevEventThreadData private structure. Every time there's and incoming event from udev, udevEventHandleCallback only increments the number of events queuing on the monitor and signals the worker thread to handle them. Signed-off-by: Erik Skultety --- src/node_device/node_device_udev.c | 131 ++++++++++++++++++++++++++++++---= ---- 1 file changed, 108 insertions(+), 23 deletions(-) diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_devi= ce_udev.c index 9e3a0f9d7..e05819fe2 100644 --- a/src/node_device/node_device_udev.c +++ b/src/node_device/node_device_udev.c @@ -59,6 +59,54 @@ struct _udevPrivate { bool privileged; }; =20 +typedef struct _udevEventThreadData udevEventThreadData; +typedef udevEventThreadData *udevEventThreadDataPtr; + +struct _udevEventThreadData { + virMutex lock; + virCond threadCond; + + bool threadQuit; + int monitor_fd; + unsigned long long nevents; /* number of udev events queuing on monito= r */ +}; + + +static udevEventThreadDataPtr +udevEventThreadDataNew(int fd) +{ + udevEventThreadDataPtr ret =3D NULL; + + if (VIR_ALLOC_QUIET(ret) < 0) + return NULL; + + if (virMutexInit(&ret->lock) < 0) + goto cleanup; + + if (virCondInit(&ret->threadCond) < 0) + goto cleanup_mutex; + + ret->monitor_fd =3D fd; + + return ret; + + cleanup_mutex: + virMutexDestroy(&ret->lock); + + cleanup: + VIR_FREE(ret); + return NULL; +} + + +static void +udevEventThreadDataFree(udevEventThreadDataPtr data) +{ + virMutexDestroy(&data->lock); + virCondDestroy(&data->threadCond); + VIR_FREE(data); +} + =20 static bool udevHasDeviceProperty(struct udev_device *dev, @@ -1646,34 +1694,53 @@ udevCheckMonitorFD(struct udev_monitor *udev_monito= r, int fd) =20 =20 static void -udevEventHandleThread(void *opaque ATTRIBUTE_UNUSED) +udevEventHandleThread(void *opaque) { + udevEventThreadDataPtr privateData =3D opaque; struct udev_device *device =3D NULL; struct udev_monitor *udev_monitor =3D NULL; - int fd =3D (intptr_t) opaque; =20 - nodeDeviceLock(); - udev_monitor =3D DRV_STATE_UDEV_MONITOR(driver); + /* continue rather than break from the loop on non-fatal errors */ + while (1) { + virMutexLock(&privateData->lock); + while (privateData->nevents =3D=3D 0 && !privateData->threadQuit) { + if (virCondWait(&privateData->threadCond, &privateData->lock))= { + virReportSystemError(errno, "%s", + _("failed to wait on condition")); + goto cleanup; + } + } =20 - if (!udevCheckMonitorFD(udev_monitor, fd)) - goto unlock; + privateData->nevents--; + virMutexUnlock(&privateData->lock); =20 - device =3D udev_monitor_receive_device(udev_monitor); - if (device =3D=3D NULL) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("udev_monitor_receive_device returned NULL")); - goto unlock; + nodeDeviceLock(); + udev_monitor =3D DRV_STATE_UDEV_MONITOR(driver); + + if (!udevCheckMonitorFD(udev_monitor, privateData->monitor_fd)) { + nodeDeviceUnlock(); + goto cleanup; + } + + device =3D udev_monitor_receive_device(udev_monitor); + nodeDeviceUnlock(); + + if (!device) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("udev_monitor_receive_device returned NULL")); + goto next; + } + + udevHandleOneDevice(device); + + next: + udev_device_unref(device); } - nodeDeviceUnlock(); - udevHandleOneDevice(device); =20 cleanup: udev_device_unref(device); + udevEventThreadDataFree(privateData); return; - - unlock: - nodeDeviceUnlock(); - goto cleanup; } =20 =20 @@ -1681,20 +1748,28 @@ static void udevEventHandleCallback(int watch ATTRIBUTE_UNUSED, int fd, int events ATTRIBUTE_UNUSED, - void *data ATTRIBUTE_UNUSED) + void *opaque) { struct udev_monitor *udev_monitor =3D NULL; + udevEventThreadDataPtr threadData =3D opaque; =20 nodeDeviceLock(); udev_monitor =3D DRV_STATE_UDEV_MONITOR(driver); - if (!udevCheckMonitorFD(udev_monitor, fd)) { + virMutexLock(&threadData->lock); + threadData->threadQuit =3D true; + virCondSignal(&threadData->threadCond); + virMutexUnlock(&threadData->lock); + nodeDeviceUnlock(); return; } nodeDeviceUnlock(); =20 - udevEventHandleThread((void *)(intptr_t) fd); + virMutexLock(&threadData->lock); + threadData->nevents++; + virCondSignal(&threadData->threadCond); + virMutexUnlock(&threadData->lock); } =20 =20 @@ -1821,6 +1896,9 @@ nodeStateInitialize(bool privileged, { udevPrivate *priv =3D NULL; struct udev *udev =3D NULL; + int monitor_fd =3D -1; + virThread th; + udevEventThreadDataPtr threadData =3D NULL; =20 if (VIR_ALLOC(priv) < 0) return -1; @@ -1881,6 +1959,14 @@ nodeStateInitialize(bool privileged, 128 * 1024 * 1024); #endif =20 + monitor_fd =3D udev_monitor_get_fd(priv->udev_monitor); + if (!(threadData =3D udevEventThreadDataNew(monitor_fd)) || + virThreadCreate(&th, false, udevEventHandleThread, threadData) < 0= ) { + virReportSystemError(errno, "%s", + _("failed to create udev handling thread")); + goto cleanup; + } + /* We register the monitor with the event callback so we are * notified by udev of device changes before we enumerate existing * devices because libvirt will simply recreate the device if we @@ -1889,9 +1975,8 @@ nodeStateInitialize(bool privileged, * enumeration. The alternative is to register the callback after * we enumerate, in which case we will fail to create any devices * that appear while the enumeration is taking place. */ - priv->watch =3D virEventAddHandle(udev_monitor_get_fd(priv->udev_monit= or), - VIR_EVENT_HANDLE_READABLE, - udevEventHandleCallback, NULL, NULL); + priv->watch =3D virEventAddHandle(monitor_fd, VIR_EVENT_HANDLE_READABL= E, + udevEventHandleCallback, threadData, N= ULL); if (priv->watch =3D=3D -1) goto unlock; =20 --=20 2.13.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list