|
|
0a7476 |
From c90c82df8b2ce989e628338a6f43b75acdd5a868 Mon Sep 17 00:00:00 2001
|
|
|
0a7476 |
Message-Id: <c90c82df8b2ce989e628338a6f43b75acdd5a868@dist-git>
|
|
|
0a7476 |
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
|
|
|
0a7476 |
Date: Wed, 3 Apr 2019 17:03:46 +0200
|
|
|
0a7476 |
Subject: [PATCH] logging: ensure pending I/O is drained before reading
|
|
|
0a7476 |
position
|
|
|
0a7476 |
MIME-Version: 1.0
|
|
|
0a7476 |
Content-Type: text/plain; charset=UTF-8
|
|
|
0a7476 |
Content-Transfer-Encoding: 8bit
|
|
|
0a7476 |
|
|
|
0a7476 |
The virtualization driver has two connections to the virtlogd daemon,
|
|
|
0a7476 |
one pipe fd for writing to the log file, and one socket fd for making
|
|
|
0a7476 |
RPC calls. The typical sequence is to write some data to the pipe fd and
|
|
|
0a7476 |
then make an RPC call to determine the current log file offset.
|
|
|
0a7476 |
|
|
|
0a7476 |
Unfortunately these two operations are not guaranteed to be handling in
|
|
|
0a7476 |
order by virtlogd. The event loop for virtlogd may identify an incoming
|
|
|
0a7476 |
event on both the pipe fd and socket fd in the same iteration of the
|
|
|
0a7476 |
event loop. It is then entirely possible that it will process the socket
|
|
|
0a7476 |
fd RPC call before reading the pending log data from the pipe fd.
|
|
|
0a7476 |
|
|
|
0a7476 |
As a result the virtualization driver will get an outdated log file
|
|
|
0a7476 |
offset reported back.
|
|
|
0a7476 |
|
|
|
0a7476 |
This can be seen with the QEMU driver where, when a guest fails to
|
|
|
0a7476 |
start, it will randomly include too much data in the error message it
|
|
|
0a7476 |
has fetched from the log file.
|
|
|
0a7476 |
|
|
|
0a7476 |
The solution is to ensure we have drained all pending data from the pipe
|
|
|
0a7476 |
fd before reporting the log file offset. The pipe fd is always in
|
|
|
0a7476 |
blocking mode, so cares needs to be taken to avoid blocking. When
|
|
|
0a7476 |
draining this is taken care of by using poll(). The extra complication
|
|
|
0a7476 |
is that they might already be an event loop dispatch pending on the pipe
|
|
|
0a7476 |
fd. If we have just drained the pipe this pending event will be invalid
|
|
|
0a7476 |
so must be discarded.
|
|
|
0a7476 |
|
|
|
0a7476 |
See also https://bugzilla.redhat.com/show_bug.cgi?id=1356108
|
|
|
0a7476 |
|
|
|
0a7476 |
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
|
|
|
0a7476 |
|
|
|
0a7476 |
(cherry picked from commit cc9e80c59368478d179ee3eb7bf8106664c56870)
|
|
|
0a7476 |
|
|
|
0a7476 |
https://bugzilla.redhat.com/show_bug.cgi?id=1660531
|
|
|
0a7476 |
|
|
|
0a7476 |
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
|
|
|
0a7476 |
Message-Id: <20190403150346.20086-1-abologna@redhat.com>
|
|
|
0a7476 |
Reviewed-by: Erik Skultety <eskultet@redhat.com>
|
|
|
0a7476 |
---
|
|
|
0a7476 |
src/logging/log_handler.c | 48 +++++++++++++++++++++++++++++++++++++++
|
|
|
0a7476 |
1 file changed, 48 insertions(+)
|
|
|
0a7476 |
|
|
|
0a7476 |
diff --git a/src/logging/log_handler.c b/src/logging/log_handler.c
|
|
|
0a7476 |
index 5364e06dff..25065ed177 100644
|
|
|
0a7476 |
--- a/src/logging/log_handler.c
|
|
|
0a7476 |
+++ b/src/logging/log_handler.c
|
|
|
0a7476 |
@@ -34,6 +34,7 @@
|
|
|
0a7476 |
|
|
|
0a7476 |
#include <unistd.h>
|
|
|
0a7476 |
#include <fcntl.h>
|
|
|
0a7476 |
+#include <poll.h>
|
|
|
0a7476 |
|
|
|
0a7476 |
#include "configmake.h"
|
|
|
0a7476 |
|
|
|
0a7476 |
@@ -50,6 +51,7 @@ struct _virLogHandlerLogFile {
|
|
|
0a7476 |
virRotatingFileWriterPtr file;
|
|
|
0a7476 |
int watch;
|
|
|
0a7476 |
int pipefd; /* Read from QEMU via this */
|
|
|
0a7476 |
+ bool drained;
|
|
|
0a7476 |
|
|
|
0a7476 |
char *driver;
|
|
|
0a7476 |
unsigned char domuuid[VIR_UUID_BUFLEN];
|
|
|
0a7476 |
@@ -153,6 +155,11 @@ virLogHandlerDomainLogFileEvent(int watch,
|
|
|
0a7476 |
return;
|
|
|
0a7476 |
}
|
|
|
0a7476 |
|
|
|
0a7476 |
+ if (logfile->drained) {
|
|
|
0a7476 |
+ logfile->drained = false;
|
|
|
0a7476 |
+ goto cleanup;
|
|
|
0a7476 |
+ }
|
|
|
0a7476 |
+
|
|
|
0a7476 |
reread:
|
|
|
0a7476 |
len = read(fd, buf, sizeof(buf));
|
|
|
0a7476 |
if (len < 0) {
|
|
|
0a7476 |
@@ -170,6 +177,7 @@ virLogHandlerDomainLogFileEvent(int watch,
|
|
|
0a7476 |
if (events & VIR_EVENT_HANDLE_HANGUP)
|
|
|
0a7476 |
goto error;
|
|
|
0a7476 |
|
|
|
0a7476 |
+ cleanup:
|
|
|
0a7476 |
virObjectUnlock(handler);
|
|
|
0a7476 |
return;
|
|
|
0a7476 |
|
|
|
0a7476 |
@@ -435,6 +443,44 @@ virLogHandlerDomainOpenLogFile(virLogHandlerPtr handler,
|
|
|
0a7476 |
}
|
|
|
0a7476 |
|
|
|
0a7476 |
|
|
|
0a7476 |
+static void
|
|
|
0a7476 |
+virLogHandlerDomainLogFileDrain(virLogHandlerLogFilePtr file)
|
|
|
0a7476 |
+{
|
|
|
0a7476 |
+ char buf[1024];
|
|
|
0a7476 |
+ ssize_t len;
|
|
|
0a7476 |
+ struct pollfd pfd;
|
|
|
0a7476 |
+ int ret;
|
|
|
0a7476 |
+
|
|
|
0a7476 |
+ for (;;) {
|
|
|
0a7476 |
+ pfd.fd = file->pipefd;
|
|
|
0a7476 |
+ pfd.events = POLLIN;
|
|
|
0a7476 |
+ pfd.revents = 0;
|
|
|
0a7476 |
+
|
|
|
0a7476 |
+ ret = poll(&pfd, 1, 0);
|
|
|
0a7476 |
+ if (ret < 0) {
|
|
|
0a7476 |
+ if (errno == EINTR)
|
|
|
0a7476 |
+ continue;
|
|
|
0a7476 |
+
|
|
|
0a7476 |
+ return;
|
|
|
0a7476 |
+ }
|
|
|
0a7476 |
+
|
|
|
0a7476 |
+ if (ret == 0)
|
|
|
0a7476 |
+ return;
|
|
|
0a7476 |
+
|
|
|
0a7476 |
+ len = read(file->pipefd, buf, sizeof(buf));
|
|
|
0a7476 |
+ file->drained = true;
|
|
|
0a7476 |
+ if (len < 0) {
|
|
|
0a7476 |
+ if (errno == EINTR)
|
|
|
0a7476 |
+ continue;
|
|
|
0a7476 |
+ return;
|
|
|
0a7476 |
+ }
|
|
|
0a7476 |
+
|
|
|
0a7476 |
+ if (virRotatingFileWriterAppend(file->file, buf, len) != len)
|
|
|
0a7476 |
+ return;
|
|
|
0a7476 |
+ }
|
|
|
0a7476 |
+}
|
|
|
0a7476 |
+
|
|
|
0a7476 |
+
|
|
|
0a7476 |
int
|
|
|
0a7476 |
virLogHandlerDomainGetLogFilePosition(virLogHandlerPtr handler,
|
|
|
0a7476 |
const char *path,
|
|
|
0a7476 |
@@ -465,6 +511,8 @@ virLogHandlerDomainGetLogFilePosition(virLogHandlerPtr handler,
|
|
|
0a7476 |
goto cleanup;
|
|
|
0a7476 |
}
|
|
|
0a7476 |
|
|
|
0a7476 |
+ virLogHandlerDomainLogFileDrain(file);
|
|
|
0a7476 |
+
|
|
|
0a7476 |
*inode = virRotatingFileWriterGetINode(file->file);
|
|
|
0a7476 |
*offset = virRotatingFileWriterGetOffset(file->file);
|
|
|
0a7476 |
|
|
|
0a7476 |
--
|
|
|
0a7476 |
2.21.0
|
|
|
0a7476 |
|