Chardev-related fixes

Hi
 
 Here are some bug fixes worthy for 6.1.
 
 thanks
 -----BEGIN PGP SIGNATURE-----
 
 iQJQBAABCAA6FiEEh6m9kz+HxgbSdvYt2ujhCXWWnOUFAmEL3vMcHG1hcmNhbmRy
 ZS5sdXJlYXVAcmVkaGF0LmNvbQAKCRDa6OEJdZac5fe7D/0U6k36kb02MePc2OIW
 OVYijYm4/LiJQ0Tae5yKhvcaG81+sXyjJa3MvU2lscHrLxFsT0Li2N8cDx8Tozfy
 ob2URg/Wd8sBllze4QSqLlMqpX5Fh7GsKjx+3d+RzFzKW3BE8ZUoxTsRH0f1imd3
 lZJmVbhvl5Bo65U0J5xp+VI4BZnEc9R/JHQOiUT+wnmwAbv4knjCz1LiW51LQvNP
 2A8cHhftN58ogm3yptSfD/5OHfFsn+16uhhTRtjuiro+9+zuVgBqxJSXENsDhzDU
 IuL5J9MHhnhSv6/QB4zuVCYZfBlMLB1CXo3bFLalSN5wCAkCxrFEozPVjj2f9gR+
 TrM1JxYK0CoAJZosHAlk1J+KGXZ4zs4Y3TyutFdLlhz9KYi4Xve3UYNQc8uK4jD8
 7eXbaxTS0b9T1LYZd7YNbyKYuUeZJSt9dwGEXdudZPhp2lRjJ/Bhhkx0RLdR8LTX
 qcpemc14AwMUh0zaUcXPuxCeWEJO8ffJyVzXY5j36tSIt5LMecDqJHEqv4ZjWgyz
 mc9AMHRDtzRx0WPV3vNHEEIioXKOqARmWuuUaW5hUDdWue3f1wuU81xoMEN92DKs
 LftUgetgdqD9vbobtoiYFI7qIjb4IaKKK5TCn6glq4Poyd2tErl/fcjkO60/IZPR
 bzDygkxX8thipWkxQhTVBaaHVA==
 =KDK+
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/marcandre/tags/chr-fix-pull-request' into staging

Chardev-related fixes

Hi

Here are some bug fixes worthy for 6.1.

thanks

# gpg: Signature made Thu 05 Aug 2021 13:52:03 BST
# gpg:                using RSA key 87A9BD933F87C606D276F62DDAE8E10975969CE5
# gpg:                issuer "marcandre.lureau@redhat.com"
# gpg: Good signature from "Marc-André Lureau <marcandre.lureau@redhat.com>" [full]
# gpg:                 aka "Marc-André Lureau <marcandre.lureau@gmail.com>" [full]
# Primary key fingerprint: 87A9 BD93 3F87 C606 D276  F62D DAE8 E109 7596 9CE5

* remotes/marcandre/tags/chr-fix-pull-request:
  chardev: report a simpler error about duplicated id
  chardev: give some context on chardev-add error
  chardev: fix qemu_chr_open_fd() with fd_in==fd_out
  chardev: fix qemu_chr_open_fd() being called with fd=-1
  chardev: fix fd_chr_add_watch() when in != out
  chardev: mark explicitly first argument as poisoned
  chardev/socket: print a more correct command-line address
  util: fix abstract socket path copy

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2021-08-05 16:25:44 +01:00
commit 287d53398a
16 changed files with 145 additions and 33 deletions

View File

@ -28,6 +28,7 @@
#include "qemu/sockets.h"
#include "qapi/error.h"
#include "chardev/char.h"
#include "chardev/char-fe.h"
#include "io/channel-file.h"
#include "chardev/char-fd.h"
@ -38,6 +39,10 @@ static int fd_chr_write(Chardev *chr, const uint8_t *buf, int len)
{
FDChardev *s = FD_CHARDEV(chr);
if (!s->ioc_out) {
return -1;
}
return io_channel_send(s->ioc_out, buf, len);
}
@ -80,10 +85,85 @@ static int fd_chr_read_poll(void *opaque)
return s->max_size;
}
typedef struct FDSource {
GSource parent;
GIOCondition cond;
} FDSource;
static gboolean
fd_source_prepare(GSource *source,
gint *timeout_)
{
FDSource *src = (FDSource *)source;
return src->cond != 0;
}
static gboolean
fd_source_check(GSource *source)
{
FDSource *src = (FDSource *)source;
return src->cond != 0;
}
static gboolean
fd_source_dispatch(GSource *source, GSourceFunc callback,
gpointer user_data)
{
FDSource *src = (FDSource *)source;
FEWatchFunc func = (FEWatchFunc)callback;
gboolean ret = G_SOURCE_CONTINUE;
if (src->cond) {
ret = func(NULL, src->cond, user_data);
src->cond = 0;
}
return ret;
}
static GSourceFuncs fd_source_funcs = {
fd_source_prepare,
fd_source_check,
fd_source_dispatch,
NULL, NULL, NULL
};
static GSource *fd_source_new(FDChardev *chr)
{
return g_source_new(&fd_source_funcs, sizeof(FDSource));
}
static gboolean child_func(GIOChannel *source,
GIOCondition condition,
gpointer data)
{
FDSource *parent = data;
parent->cond |= condition;
return G_SOURCE_CONTINUE;
}
static GSource *fd_chr_add_watch(Chardev *chr, GIOCondition cond)
{
FDChardev *s = FD_CHARDEV(chr);
return qio_channel_create_watch(s->ioc_out, cond);
g_autoptr(GSource) source = fd_source_new(s);
if (s->ioc_out) {
g_autoptr(GSource) child = qio_channel_create_watch(s->ioc_out, cond & ~G_IO_IN);
g_source_set_callback(child, (GSourceFunc)child_func, source, NULL);
g_source_add_child_source(source, child);
}
if (s->ioc_in) {
g_autoptr(GSource) child = qio_channel_create_watch(s->ioc_in, cond & ~G_IO_OUT);
g_source_set_callback(child, (GSourceFunc)child_func, source, NULL);
g_source_add_child_source(source, child);
}
return g_steal_pointer(&source);
}
static void fd_chr_update_read_handler(Chardev *chr)
@ -131,17 +211,32 @@ void qemu_chr_open_fd(Chardev *chr,
int fd_in, int fd_out)
{
FDChardev *s = FD_CHARDEV(chr);
char *name;
g_autofree char *name = NULL;
s->ioc_in = QIO_CHANNEL(qio_channel_file_new_fd(fd_in));
name = g_strdup_printf("chardev-file-in-%s", chr->label);
qio_channel_set_name(QIO_CHANNEL(s->ioc_in), name);
g_free(name);
s->ioc_out = QIO_CHANNEL(qio_channel_file_new_fd(fd_out));
name = g_strdup_printf("chardev-file-out-%s", chr->label);
qio_channel_set_name(QIO_CHANNEL(s->ioc_out), name);
g_free(name);
qemu_set_nonblock(fd_out);
if (fd_out >= 0) {
qemu_set_nonblock(fd_out);
}
if (fd_out == fd_in && fd_in >= 0) {
s->ioc_in = QIO_CHANNEL(qio_channel_file_new_fd(fd_in));
name = g_strdup_printf("chardev-file-%s", chr->label);
qio_channel_set_name(QIO_CHANNEL(s->ioc_in), name);
s->ioc_out = QIO_CHANNEL(object_ref(s->ioc_in));
return;
}
if (fd_in >= 0) {
s->ioc_in = QIO_CHANNEL(qio_channel_file_new_fd(fd_in));
name = g_strdup_printf("chardev-file-in-%s", chr->label);
qio_channel_set_name(QIO_CHANNEL(s->ioc_in), name);
}
if (fd_out >= 0) {
s->ioc_out = QIO_CHANNEL(qio_channel_file_new_fd(fd_out));
g_free(name);
name = g_strdup_printf("chardev-file-out-%s", chr->label);
qio_channel_set_name(QIO_CHANNEL(s->ioc_out), name);
}
}
static void char_fd_class_init(ObjectClass *oc, void *data)

View File

@ -354,7 +354,7 @@ void qemu_chr_fe_set_open(CharBackend *be, int fe_open)
}
guint qemu_chr_fe_add_watch(CharBackend *be, GIOCondition cond,
GIOFunc func, void *user_data)
FEWatchFunc func, void *user_data)
{
Chardev *s = be->chr;
GSource *src;

View File

@ -468,9 +468,9 @@ static char *qemu_chr_socket_address(SocketChardev *s, const char *prefix)
#ifdef CONFIG_LINUX
if (sa->has_abstract && sa->abstract) {
abstract = ",abstract";
abstract = ",abstract=on";
if (sa->has_tight && sa->tight) {
tight = ",tight";
tight = ",tight=on";
}
}
#endif

View File

@ -1031,27 +1031,31 @@ Chardev *qemu_chardev_new(const char *id, const char *typename,
ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
Error **errp)
{
ERRP_GUARD();
const ChardevClass *cc;
ChardevReturn *ret;
Chardev *chr;
g_autoptr(Chardev) chr = NULL;
if (qemu_chr_find(id)) {
error_setg(errp, "Chardev with id '%s' already exists", id);
return NULL;
}
cc = char_get_class(ChardevBackendKind_str(backend->type), errp);
if (!cc) {
return NULL;
goto err;
}
chr = chardev_new(id, object_class_get_name(OBJECT_CLASS(cc)),
backend, NULL, false, errp);
if (!chr) {
return NULL;
goto err;
}
if (!object_property_try_add_child(get_chardevs_root(), id, OBJECT(chr),
errp)) {
object_unref(OBJECT(chr));
return NULL;
goto err;
}
object_unref(OBJECT(chr));
ret = g_new0(ChardevReturn, 1);
if (CHARDEV_IS_PTY(chr)) {
@ -1060,6 +1064,10 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
}
return ret;
err:
error_prepend(errp, "Failed to add chardev '%s': ", id);
return NULL;
}
ChardevReturn *qmp_chardev_change(const char *id, ChardevBackend *backend,

View File

@ -288,7 +288,7 @@ static void uart_write_rx_fifo(void *opaque, const uint8_t *buf, int size)
uart_update_status(s);
}
static gboolean cadence_uart_xmit(GIOChannel *chan, GIOCondition cond,
static gboolean cadence_uart_xmit(void *do_not_use, GIOCondition cond,
void *opaque)
{
CadenceUARTState *s = opaque;

View File

@ -191,7 +191,7 @@ static uint64_t uart_read(void *opaque, hwaddr offset, unsigned size)
/* Try to send tx data, and arrange to be called back later if
* we can't (ie the char backend is busy/blocking).
*/
static gboolean uart_transmit(GIOChannel *chan, GIOCondition cond, void *opaque)
static gboolean uart_transmit(void *do_not_use, GIOCondition cond, void *opaque)
{
CMSDKAPBUART *s = CMSDK_APB_UART(opaque);
int ret;

View File

@ -135,7 +135,7 @@ static void ibex_uart_receive(void *opaque, const uint8_t *buf, int size)
ibex_uart_update_irqs(s);
}
static gboolean ibex_uart_xmit(GIOChannel *chan, GIOCondition cond,
static gboolean ibex_uart_xmit(void *do_not_use, GIOCondition cond,
void *opaque)
{
IbexUartState *s = opaque;

View File

@ -75,7 +75,7 @@ static uint64_t uart_read(void *opaque, hwaddr addr, unsigned int size)
return r;
}
static gboolean uart_transmit(GIOChannel *chan, GIOCondition cond, void *opaque)
static gboolean uart_transmit(void *do_not_use, GIOCondition cond, void *opaque)
{
NRF51UARTState *s = NRF51_UART(opaque);
int r;

View File

@ -220,7 +220,7 @@ static void serial_update_msl(SerialState *s)
}
}
static gboolean serial_watch_cb(GIOChannel *chan, GIOCondition cond,
static gboolean serial_watch_cb(void *do_not_use, GIOCondition cond,
void *opaque)
{
SerialState *s = opaque;

View File

@ -38,7 +38,7 @@ struct VirtConsole {
* Callback function that's called from chardevs when backend becomes
* writable.
*/
static gboolean chr_write_unblocked(GIOChannel *chan, GIOCondition cond,
static gboolean chr_write_unblocked(void *do_not_use, GIOCondition cond,
void *opaque)
{
VirtConsole *vcon = opaque;

View File

@ -270,7 +270,7 @@ static int usbredir_read(void *priv, uint8_t *data, int count)
return count;
}
static gboolean usbredir_write_unblocked(GIOChannel *chan, GIOCondition cond,
static gboolean usbredir_write_unblocked(void *do_not_use, GIOCondition cond,
void *opaque)
{
USBRedirDevice *dev = opaque;

View File

@ -303,7 +303,7 @@ struct vhost_user_read_cb_data {
int ret;
};
static gboolean vhost_user_read_cb(GIOChannel *source, GIOCondition condition,
static gboolean vhost_user_read_cb(void *do_not_use, GIOCondition condition,
gpointer opaque)
{
struct vhost_user_read_cb_data *data = opaque;

View File

@ -174,6 +174,9 @@ void qemu_chr_fe_set_open(CharBackend *be, int fe_open);
void qemu_chr_fe_printf(CharBackend *be, const char *fmt, ...)
GCC_FMT_ATTR(2, 3);
typedef gboolean (*FEWatchFunc)(void *do_not_use, GIOCondition condition, void *data);
/**
* qemu_chr_fe_add_watch:
* @cond: the condition to poll for
@ -188,10 +191,13 @@ void qemu_chr_fe_printf(CharBackend *be, const char *fmt, ...)
* Note that you are responsible to update the front-end sources if
* you are switching the main context with qemu_chr_fe_set_handlers().
*
* Warning: DO NOT use the first callback argument (it may be either
* a GIOChannel or a QIOChannel, depending on the underlying chardev)
*
* Returns: the source tag
*/
guint qemu_chr_fe_add_watch(CharBackend *be, GIOCondition cond,
GIOFunc func, void *user_data);
FEWatchFunc func, void *user_data);
/**
* qemu_chr_fe_write:

View File

@ -156,7 +156,7 @@ static inline bool monitor_is_hmp_non_interactive(const Monitor *mon)
static void monitor_flush_locked(Monitor *mon);
static gboolean monitor_unblocked(GIOChannel *chan, GIOCondition cond,
static gboolean monitor_unblocked(void *do_not_use, GIOCondition cond,
void *opaque)
{
Monitor *mon = opaque;

View File

@ -208,8 +208,8 @@ static NetClientInfo net_vhost_user_info = {
.set_vnet_le = vhost_user_set_vnet_endianness,
};
static gboolean net_vhost_user_watch(GIOChannel *chan, GIOCondition cond,
void *opaque)
static gboolean net_vhost_user_watch(void *do_not_use, GIOCondition cond,
void *opaque)
{
NetVhostUserState *s = opaque;

View File

@ -1345,13 +1345,16 @@ socket_sockaddr_to_address_unix(struct sockaddr_storage *sa,
SocketAddress *addr;
struct sockaddr_un *su = (struct sockaddr_un *)sa;
assert(salen >= sizeof(su->sun_family) + 1 &&
salen <= sizeof(struct sockaddr_un));
addr = g_new0(SocketAddress, 1);
addr->type = SOCKET_ADDRESS_TYPE_UNIX;
#ifdef CONFIG_LINUX
if (!su->sun_path[0]) {
/* Linux abstract socket */
addr->u.q_unix.path = g_strndup(su->sun_path + 1,
sizeof(su->sun_path) - 1);
salen - sizeof(su->sun_family) - 1);
addr->u.q_unix.has_abstract = true;
addr->u.q_unix.abstract = true;
addr->u.q_unix.has_tight = true;