On 05.12.25 18:33, Marc-André Lureau wrote:
Hi
On Thu, Dec 4, 2025 at 7:42 PM Vladimir Sementsov-Ogievskiy <[email protected]
<mailto:[email protected]>> wrote:
We have the following flaws with it:
1. Layring violation by modifying generic state directly in backends
Well, it's a parent field that can be modified, I am not sure it qualifies as
such
2. Tricky generic logic: we should check, did backend set the
generic state field, and fill it when not.
Let's fix them all by making filename a private field with getter
and setter. And move the "default logic" into getter.
The tradeoff is that your implementation will do more allocation/free, but I
don't think we care much here.
I am not sure we gain much overall.
My actual goal is to "open the doors" for further movement of qemu_char_open()
call
to the later point (I came to this idea instead of trying to split .open() into
.open() and .init())..
So I should do something with the logic in chardev_new(), done after
qemu_char_open()
call. Alternative is to put it into qemu_char_open(). But I decided, that being
here,
it's better to generalize it somehow.
Agree, that setter/getter for filename seems a bit cumbersome here.
Hmm. I think, I have a clearer idea:
add .chr_get_filename() handler and drop the .filename field and
qemu_chr_set_filename()
function.
So, qemu_chr_get_filename() will realize the default logic or call
.chr_get_filename() if
it exist.
We'll need implementations only for char-socket and char-pty.
Signed-off-by: Vladimir Sementsov-Ogievskiy <[email protected] <mailto:[email protected]>>
---
chardev/char-pty.c | 4 +++-
chardev/char-socket.c | 17 ++++++++---------
chardev/char.c | 8 ++------
hw/misc/ivshmem-pci.c | 4 ++--
include/chardev/char.h | 21 ++++++++++++++++++++-
5 files changed, 35 insertions(+), 19 deletions(-)
diff --git a/chardev/char-pty.c b/chardev/char-pty.c
index 047aade09e..f4294679be 100644
--- a/chardev/char-pty.c
+++ b/chardev/char-pty.c
@@ -336,6 +336,7 @@ static bool pty_chr_open(Chardev *chr, ChardevBackend
*backend, Error **errp)
int master_fd, slave_fd;
char *name;
char *path = backend->u.pty.data->path;
+ g_autofree char *filename = NULL;
s = PTY_CHARDEV(chr);
@@ -351,7 +352,8 @@ static bool pty_chr_open(Chardev *chr, ChardevBackend
*backend, Error **errp)
return false;
}
- chr->filename = g_strdup_printf("pty:%s", s->pty_name);
+ filename = g_strdup_printf("pty:%s", s->pty_name);
+ qemu_chr_set_filename(chr, filename);
qemu_printf("char device redirected to %s (label %s)\n",
s->pty_name, chr->label);
diff --git a/chardev/char-socket.c b/chardev/char-socket.c
index 31c9acd164..9387760009 100644
--- a/chardev/char-socket.c
+++ b/chardev/char-socket.c
@@ -384,8 +384,7 @@ static void tcp_chr_free_connection(Chardev *chr)
s->sioc = NULL;
object_unref(OBJECT(s->ioc));
s->ioc = NULL;
- g_free(chr->filename);
- chr->filename = NULL;
+ qemu_chr_set_filename(chr, NULL);
tcp_chr_change_state(s, TCP_CHARDEV_STATE_DISCONNECTED);
}
@@ -443,11 +442,11 @@ static void
update_disconnected_filename(SocketChardev *s)
{
Chardev *chr = CHARDEV(s);
- g_free(chr->filename);
if (s->addr) {
- chr->filename = qemu_chr_socket_address(s, "disconnected:");
+ g_autofree char *filename = qemu_chr_socket_address(s,
"disconnected:");
+ qemu_chr_set_filename(chr, filename);
} else {
- chr->filename = g_strdup("disconnected:socket");
+ qemu_chr_set_filename(chr, "disconnected:socket");
}
}
@@ -638,9 +637,9 @@ static void tcp_chr_connect(void *opaque)
{
Chardev *chr = CHARDEV(opaque);
SocketChardev *s = SOCKET_CHARDEV(opaque);
+ g_autofree char *filename = qemu_chr_compute_filename(s);
- g_free(chr->filename);
- chr->filename = qemu_chr_compute_filename(s);
+ qemu_chr_set_filename(chr, filename);
tcp_chr_change_state(s, TCP_CHARDEV_STATE_CONNECTED);
update_ioc_handlers(s);
@@ -1000,8 +999,8 @@ static void tcp_chr_accept_server_sync(Chardev *chr)
{
SocketChardev *s = SOCKET_CHARDEV(chr);
QIOChannelSocket *sioc;
- info_report("QEMU waiting for connection on: %s",
- chr->filename);
+ g_autofree char *filename = qemu_chr_get_filename(chr);
+ info_report("QEMU waiting for connection on: %s", filename);
tcp_chr_change_state(s, TCP_CHARDEV_STATE_CONNECTING);
sioc = qio_net_listener_wait_client(s->listener);
tcp_chr_set_client_ioc_name(chr, sioc);
diff --git a/chardev/char.c b/chardev/char.c
index 0dc792b88f..bdd907f015 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -309,7 +309,7 @@ static void char_finalize(Object *obj)
if (chr->fe) {
chr->fe->chr = NULL;
}
- g_free(chr->filename);
+ qemu_chr_set_filename(chr, NULL);
g_free(chr->label);
if (chr->logfd != -1) {
close(chr->logfd);
@@ -796,7 +796,7 @@ static int qmp_query_chardev_foreach(Object *obj, void
*data)
ChardevInfo *value = g_malloc0(sizeof(*value));
value->label = g_strdup(chr->label);
- value->filename = g_strdup(chr->filename);
+ value->filename = qemu_chr_get_filename(chr);
value->frontend_open = chr->fe && chr->fe->fe_is_open;
QAPI_LIST_PREPEND(*list, value);
@@ -1025,10 +1025,6 @@ static Chardev *chardev_new(const char *id, const
char *typename,
return NULL;
}
- if (!chr->filename) {
- chr->filename = g_strdup(typename + 8);
- }
-
return chr;
}
diff --git a/hw/misc/ivshmem-pci.c b/hw/misc/ivshmem-pci.c
index 636d0b83de..2c7b987241 100644
--- a/hw/misc/ivshmem-pci.c
+++ b/hw/misc/ivshmem-pci.c
@@ -873,10 +873,10 @@ static void ivshmem_common_realize(PCIDevice *dev,
Error **errp)
host_memory_backend_set_mapped(s->hostmem, true);
} else {
Chardev *chr = qemu_chr_fe_get_driver(&s->server_chr);
+ char *filename = qemu_chr_get_filename(chr);
Should be auto-free, since returned allocated
assert(chr);
- IVSHMEM_DPRINTF("using shared memory server (socket = %s)\n",
- chr->filename);
+ IVSHMEM_DPRINTF("using shared memory server (socket = %s)\n",
filename);
/* we allocate enough space for 16 peers and grow as needed */
resize_peers(s, 16);
diff --git a/include/chardev/char.h b/include/chardev/char.h
index d36e50b99e..ffeb4a4e3b 100644
--- a/include/chardev/char.h
+++ b/include/chardev/char.h
@@ -62,7 +62,7 @@ struct Chardev {
QemuMutex chr_write_lock;
CharFrontend *fe;
char *label;
- char *filename;
+ char *_filename;
Why rename the field? we don't have a convention to have "private" fields with
_ prefix afaik.
int logfd;
int be_open;
/* used to coordinate the chardev-change special-case: */
@@ -72,6 +72,25 @@ struct Chardev {
DECLARE_BITMAP(features, QEMU_CHAR_FEATURE_LAST);
};
+static inline char *qemu_chr_get_filename(Chardev *chr)
Let's avoid code in headers.
+{
+ const char *typename;
+
+ if (chr->_filename) {
+ return g_strdup(chr->_filename);
+ }
+
+ typename = object_get_typename(OBJECT(chr));
+ assert(g_str_has_prefix(typename, "chardev-"));
+ return g_strdup(typename + 8);
+}
+
+static inline void qemu_chr_set_filename(Chardev *chr, const char
*filename)
+{
+ g_free(chr->_filename);
+ chr->_filename = g_strdup(filename);
+}
+
/**
* qemu_chr_new_from_opts:
* @opts: see qemu-config.c for a list of valid options
--
2.48.1
--
Best regards,
Vladimir