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:
commit
287d53398a
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user