From: "Denis V. Lunev" <den@openvz.org>
To: svt-core@virtuozzo.com
Cc: andrey.drobyshev@virtuozzo.com, den@openvz.org
Subject: [PATCH hci-8.0 v2 2/3] chardev: preserve the logfile fd across cpr-exec #VSTOR-148304
Date: Mon, 5 Oct 2026 11:26:34 +0200 [thread overview]
Message-ID: <20261005092635.3564485-3-den@openvz.org> (raw)
In-Reply-To: <20261005092635.3564485-1-den@openvz.org>
From: Denis V. Lunev <den@openvz.org>
A chardev with logfile= opens the log in qemu_char_open() on every
start, including the start of the new QEMU after cpr-exec. The backend
fds are taken from the cpr fd registry there, the log fd is not, so the
new process reopens the path itself.
libvirt normally opens the log through virtlogd and passes a pipe in an
fdset. The qemu-update command line cannot carry that fdset, so it
names the log file path. The exec'd QEMU, running as the qemu user,
then fails to create a log it has no write access to, e.g. a nova
console.log on node-local storage:
qemu-kvm: -chardev pty,id=charserial0,logfile=.../console.log,
logappend=on: Could not create '.../console.log': Permission denied
and the VM is destroyed. Where the open succeeds, the new QEMU writes
the file directly, behind virtlogd's back.
Save the log fd in the cpr registry under the chardev label and take it
from there on cpr-exec incoming, as the backends do. The logfile path
is not opened at all then. If the source did not save it, run without
a log rather than reopen the path. A failed chardev-change re-claims
the log through the base class cpr_claim_fds(), since the replacement's
log has displaced the entry.
Signed-off-by: Denis V. Lunev <den@openvz.org>
Reviewed-by: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
---
chardev/char.c | 30 +++++++++++++++++++++++++-----
include/migration/cpr.h | 1 +
2 files changed, 26 insertions(+), 5 deletions(-)
diff --git a/chardev/char.c b/chardev/char.c
index b64767f574e..c037d2e7730 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -40,6 +40,7 @@
#include "qemu/id.h"
#include "qemu/coroutine.h"
#include "qemu/yank.h"
+#include "migration/cpr.h"
#include "chardev-internal.h"
@@ -261,9 +262,21 @@ static void qemu_char_open(Chardev *chr, ChardevBackend *backend,
} else {
flags |= O_TRUNC;
}
- chr->logfd = qemu_create(common->logfile, flags, 0666, errp);
- if (chr->logfd < 0) {
- return;
+ if (cpr_exec_is_incoming()) {
+ chr->logfd = cpr_find_fd(chr->label, CPR_CHARDEV_LOG_ID);
+ if (chr->logfd < 0) {
+ warn_report("chardev '%s': log file was not preserved, "
+ "continuing without it", chr->label);
+ }
+ } else {
+ chr->logfd = qemu_create(common->logfile, flags, 0666, errp);
+ if (chr->logfd < 0) {
+ return;
+ }
+ if (!cpr_is_incoming()) {
+ cpr_delete_fd(chr->label, CPR_CHARDEV_LOG_ID);
+ cpr_save_fd(chr->label, CPR_CHARDEV_LOG_ID, chr->logfd);
+ }
}
}
@@ -297,6 +310,10 @@ static int null_chr_write(Chardev *chr, const uint8_t *buf, int len)
static void char_cpr_claim_fds(Chardev *chr)
{
+ if (chr->logfd >= 0) {
+ cpr_delete_fd(chr->label, CPR_CHARDEV_LOG_ID);
+ cpr_save_fd(chr->label, CPR_CHARDEV_LOG_ID, chr->logfd);
+ }
}
static void char_class_init(ObjectClass *oc, const void *data)
@@ -315,11 +332,14 @@ static void char_finalize(Object *obj)
if (chr->be) {
chr->be->chr = NULL;
}
- g_free(chr->filename);
- g_free(chr->label);
if (chr->logfd != -1) {
+ if (cpr_find_fd(chr->label, CPR_CHARDEV_LOG_ID) == chr->logfd) {
+ cpr_delete_fd(chr->label, CPR_CHARDEV_LOG_ID);
+ }
close(chr->logfd);
}
+ g_free(chr->filename);
+ g_free(chr->label);
qemu_mutex_destroy(&chr->chr_write_lock);
}
diff --git a/include/migration/cpr.h b/include/migration/cpr.h
index d74ff1ea602..8fb79eb0a28 100644
--- a/include/migration/cpr.h
+++ b/include/migration/cpr.h
@@ -15,6 +15,7 @@
#define CPR_LISTENSOCK_ID 0
#define CPR_CONNSOCK_ID 1
+#define CPR_CHARDEV_LOG_ID 2
#define QEMU_CPR_FILE_MAGIC 0x51435052
#define QEMU_CPR_FILE_VERSION 0x00000001
--
2.53.0
next prev parent reply other threads:[~2026-10-05 9:26 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-05 9:26 [PATCH hci-8.0 v2 0/3] chardev: fix qemu-update destroying VMs with a console log #VSTOR-148304 Denis V. Lunev
2026-10-05 9:26 ` [PATCH hci-8.0 v2 1/3] chardev: implement cpr_claim_fds() in the base class #VSTOR-148304 Denis V. Lunev
2026-10-05 9:28 ` no-reply
2026-10-05 9:26 ` Denis V. Lunev [this message]
2026-10-05 9:30 ` [PATCH hci-8.0 v2 2/3] chardev: preserve the logfile fd across cpr-exec #VSTOR-148304 no-reply
2026-10-05 9:26 ` [PATCH hci-8.0 v2 3/3] iotests/migrate-cpr-exec: cover chardevs with logfile= #VSTOR-148304 Denis V. Lunev
2026-10-05 9:35 ` no-reply
2026-10-05 9:47 ` [PATCH hci-8.0 v2 0/3] chardev: fix qemu-update destroying VMs with a console log #VSTOR-148304 Andrey Drobyshev
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261005092635.3564485-3-den@openvz.org \
--to=den@openvz.org \
--cc=andrey.drobyshev@virtuozzo.com \
--cc=svt-core@virtuozzo.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox