From nobody Sun May 5 15:28:06 2024 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; dmarc=pass(p=none dis=none) header.from=redhat.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1544792679902840.4044035048639; Fri, 14 Dec 2018 05:04:39 -0800 (PST) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D076A2D7F8; Fri, 14 Dec 2018 13:04:36 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 687085C1A1; Fri, 14 Dec 2018 13:04:34 +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 468A04EA45; Fri, 14 Dec 2018 13:04:30 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id wBED4TEK030166 for ; Fri, 14 Dec 2018 08:04:29 -0500 Received: by smtp.corp.redhat.com (Postfix) id 695C567141; Fri, 14 Dec 2018 13:04:29 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-112-19.ams2.redhat.com [10.36.112.19]) by smtp.corp.redhat.com (Postfix) with ESMTP id 88E3566D46; Fri, 14 Dec 2018 13:04:22 +0000 (UTC) From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= To: libvir-list@redhat.com Date: Fri, 14 Dec 2018 13:04:19 +0000 Message-Id: <20181214130419.16019-1-berrange@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH] logging: ensure pending I/O is drained before reading position 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: , Content-Type: text/plain; charset="utf-8" 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.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Fri, 14 Dec 2018 13:04:38 +0000 (UTC) The virtualization driver has two connections to the virtlogd daemon, one pipe fd for writing to the log file, and one socket fd for making RPC calls. The typical sequence is to write some data to the pipe fd and then make an RPC call to determine the current log file offset. Unfortunately these two operations are not guaranteed to be handling in order by virtlogd. The event loop for virtlogd may identify an incoming event on both the pipe fd and socket fd in the same iteration of the event loop. It is then entirely possible that it will process the socket fd RPC call before reading the pending log data from the pipe fd. As a result the virtualization driver will get an outdated log file offset reported back. This can be seen with the QEMU driver where, when a guest fails to start, it will randomly include too much data in the error message it has fetched from the log file. The solution is to ensure we have drained all pending data from the pipe fd before reporting the log file offset. The pipe fd is always in blocking mode, so cares needs to be taken to avoid blocking. When draining this is taken care of by using poll(). The extra complication is that they might already be an event loop dispatch pending on the pipe fd. If we have just drained the pipe this pending event will be invalid so must be discarded. Signed-off-by: Daniel P. Berrang=C3=A9 --- src/logging/log_handler.c | 48 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/logging/log_handler.c b/src/logging/log_handler.c index 9e1f1f1577..272bb719ca 100644 --- a/src/logging/log_handler.c +++ b/src/logging/log_handler.c @@ -32,6 +32,7 @@ =20 #include #include +#include =20 #include "configmake.h" =20 @@ -48,6 +49,7 @@ struct _virLogHandlerLogFile { virRotatingFileWriterPtr file; int watch; int pipefd; /* Read from QEMU via this */ + bool drained; =20 char *driver; unsigned char domuuid[VIR_UUID_BUFLEN]; @@ -151,6 +153,11 @@ virLogHandlerDomainLogFileEvent(int watch, return; } =20 + if (logfile->drained) { + logfile->drained =3D false; + goto cleanup; + } + reread: len =3D read(fd, buf, sizeof(buf)); if (len < 0) { @@ -168,6 +175,7 @@ virLogHandlerDomainLogFileEvent(int watch, if (events & VIR_EVENT_HANDLE_HANGUP) goto error; =20 + cleanup: virObjectUnlock(handler); return; =20 @@ -433,6 +441,44 @@ virLogHandlerDomainOpenLogFile(virLogHandlerPtr handle= r, } =20 =20 +static void +virLogHandlerDomainLogFileDrain(virLogHandlerLogFilePtr file) +{ + char buf[1024]; + ssize_t len; + struct pollfd pfd; + int ret; + + for (;;) { + pfd.fd =3D file->pipefd; + pfd.events =3D POLLIN; + pfd.revents =3D 0; + + ret =3D poll(&pfd, 1, 0); + if (ret < 0) { + if (errno =3D=3D EINTR) + continue; + + return; + } + + if (ret =3D=3D 0) + return; + + len =3D read(file->pipefd, buf, sizeof(buf)); + file->drained =3D true; + if (len < 0) { + if (errno =3D=3D EINTR) + continue; + return; + } + + if (virRotatingFileWriterAppend(file->file, buf, len) !=3D len) + return; + } +} + + int virLogHandlerDomainGetLogFilePosition(virLogHandlerPtr handler, const char *path, @@ -463,6 +509,8 @@ virLogHandlerDomainGetLogFilePosition(virLogHandlerPtr = handler, goto cleanup; } =20 + virLogHandlerDomainLogFileDrain(file); + *inode =3D virRotatingFileWriterGetINode(file->file); *offset =3D virRotatingFileWriterGetOffset(file->file); =20 --=20 2.19.2 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list