* Update security triage contact address
* Check and honour failures to the blocking flag on FDs * Don't touch blocking flags on FDs received during migration -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEE2vOm/bJrYpEtDo4/vobrtBUQT98FAmjNQuAACgkQvobrtBUQ T99xaBAAr6zQPii1tjzuzLovF6MIqtldXnmVO/yjcl5NgLWonIRDt2JsxnRxi3es 9uNDed5+ePNXmUAYd46k81gBEjBWbv465kt5FHAZZV6BRw/PPzkoh+jzGc8NVir8 3GZJ2kPr51PxGEl8md2vRthg4bMuhlS5ogCEqAMDYT4f6AVemfnNQ5NttGX353T2 etxoMhEeMtTBKjMoTBv+SVhhO4nKwZ+6CFhvuGON423EfrGlkNTXyprKTdzpr4i0 4KDQLxxoANlmg/1W0PxfrLiBCmGpHweMR44Piv715VYa2YNPRq0G6EC6AFGbHZ51 N+mKmWNE0CS5rP1TEacSCX4q6If5VxjSLLj+og8LmpIlJ6tiqdrisSqA6bzCJ1f/ lMsfUsKoMqPhqat9ZGUkYu8REgKP+O+CSGJNftYTsEEY0oKZrAW4fsoN3E9qpfcG Xy6eSu0TTGDWE6CEe0vkHiQwlVHMtRcWMSPwlsvrgt2TO6k97reT3AoIBK2VfygC WzMv0P0nBvHFKeIbqmFOk3BEI5+JECgxVRc1WXWbSFLW0PBY/xd7g6ow8uaQsd9e pzMA1Pwh2EuM4DTlOy+m9zBOhm9YP9An188NLldOne3TFKFYe5QO1DQpvvEGvIGB +4XpmyOj3g2ycelZZ5XsDJk0LumCCOcbSPSiAvHZyWwLo24EABE= =rrMd -----END PGP SIGNATURE----- Merge tag 'misc-fixes-pull-request' of https://gitlab.com/berrange/qemu into staging * Update security triage contact address * Check and honour failures to the blocking flag on FDs * Don't touch blocking flags on FDs received during migration # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCAAdFiEE2vOm/bJrYpEtDo4/vobrtBUQT98FAmjNQuAACgkQvobrtBUQ # T99xaBAAr6zQPii1tjzuzLovF6MIqtldXnmVO/yjcl5NgLWonIRDt2JsxnRxi3es # 9uNDed5+ePNXmUAYd46k81gBEjBWbv465kt5FHAZZV6BRw/PPzkoh+jzGc8NVir8 # 3GZJ2kPr51PxGEl8md2vRthg4bMuhlS5ogCEqAMDYT4f6AVemfnNQ5NttGX353T2 # etxoMhEeMtTBKjMoTBv+SVhhO4nKwZ+6CFhvuGON423EfrGlkNTXyprKTdzpr4i0 # 4KDQLxxoANlmg/1W0PxfrLiBCmGpHweMR44Piv715VYa2YNPRq0G6EC6AFGbHZ51 # N+mKmWNE0CS5rP1TEacSCX4q6If5VxjSLLj+og8LmpIlJ6tiqdrisSqA6bzCJ1f/ # lMsfUsKoMqPhqat9ZGUkYu8REgKP+O+CSGJNftYTsEEY0oKZrAW4fsoN3E9qpfcG # Xy6eSu0TTGDWE6CEe0vkHiQwlVHMtRcWMSPwlsvrgt2TO6k97reT3AoIBK2VfygC # WzMv0P0nBvHFKeIbqmFOk3BEI5+JECgxVRc1WXWbSFLW0PBY/xd7g6ow8uaQsd9e # pzMA1Pwh2EuM4DTlOy+m9zBOhm9YP9An188NLldOne3TFKFYe5QO1DQpvvEGvIGB # +4XpmyOj3g2ycelZZ5XsDJk0LumCCOcbSPSiAvHZyWwLo24EABE= # =rrMd # -----END PGP SIGNATURE----- # gpg: Signature made Fri 19 Sep 2025 04:47:44 AM PDT # gpg: using RSA key DAF3A6FDB26B62912D0E8E3FBE86EBB415104FDF # gpg: Good signature from "Daniel P. Berrange <dan@berrange.com>" [unknown] # gpg: aka "Daniel P. Berrange <berrange@redhat.com>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: DAF3 A6FD B26B 6291 2D0E 8E3F BE86 EBB4 1510 4FDF * tag 'misc-fixes-pull-request' of https://gitlab.com/berrange/qemu: util/vhost-user-server: vu_message_read(): improve error handling chardev: close an fd on failure path chardev: qemu_chr_open_fd(): add errp treewide: use qemu_set_blocking instead of g_unix_set_fd_nonblocking util: drop qemu_socket_set_block() io/channel-socket: rework qio_channel_socket_copy_fds() util: drop qemu_socket_try_set_nonblock() util: drop qemu_socket_set_nonblock() migration: qemu_file_set_blocking(): add errp parameter treewide: handle result of qio_channel_set_blocking() util: add qemu_set_blocking() function char-socket: tcp_chr_recv(): add comment char-socket: tcp_chr_recv(): drop extra _set_(block,cloexec) io/channel: document how qio_channel_readv_full() handles fds migration/qemu-file: don't make incoming fds blocking again MAINTAINERS: list qemu-security@nongnu.org as security contact Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
commit
caf2e8de4e
63 changed files with 376 additions and 220 deletions
|
|
@ -85,7 +85,7 @@ Responsible Disclosure, Reporting Security Issues
|
|||
-------------------------------------------------
|
||||
W: https://wiki.qemu.org/SecurityProcess
|
||||
M: Michael S. Tsirkin <mst@redhat.com>
|
||||
L: secalert@redhat.com
|
||||
L: qemu-security@nongnu.org
|
||||
|
||||
Trivial patches
|
||||
---------------
|
||||
|
|
|
|||
|
|
@ -351,7 +351,9 @@ int coroutine_fn nbd_co_do_establish_connection(BlockDriverState *bs,
|
|||
return ret;
|
||||
}
|
||||
|
||||
qio_channel_set_blocking(s->ioc, false, NULL);
|
||||
if (!qio_channel_set_blocking(s->ioc, false, errp)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
qio_channel_set_follow_coroutine_ctx(s->ioc, true);
|
||||
|
||||
/* successfully connected */
|
||||
|
|
|
|||
|
|
@ -206,14 +206,16 @@ int qmp_chardev_open_file_source(char *src, int flags, Error **errp)
|
|||
}
|
||||
|
||||
/* open a character device to a unix fd */
|
||||
void qemu_chr_open_fd(Chardev *chr,
|
||||
int fd_in, int fd_out)
|
||||
bool qemu_chr_open_fd(Chardev *chr,
|
||||
int fd_in, int fd_out, Error **errp)
|
||||
{
|
||||
FDChardev *s = FD_CHARDEV(chr);
|
||||
g_autofree char *name = NULL;
|
||||
|
||||
if (fd_out >= 0 && !g_unix_set_fd_nonblocking(fd_out, true, NULL)) {
|
||||
assert(!"Failed to set FD nonblocking");
|
||||
if (fd_out >= 0) {
|
||||
if (!qemu_set_blocking(fd_out, false, errp)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (fd_out == fd_in && fd_in >= 0) {
|
||||
|
|
@ -221,7 +223,7 @@ void qemu_chr_open_fd(Chardev *chr,
|
|||
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;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (fd_in >= 0) {
|
||||
|
|
@ -236,6 +238,8 @@ void qemu_chr_open_fd(Chardev *chr,
|
|||
name = g_strdup_printf("chardev-file-out-%s", chr->label);
|
||||
qio_channel_set_name(QIO_CHANNEL(s->ioc_out), name);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void char_fd_class_init(ObjectClass *oc, const void *data)
|
||||
|
|
|
|||
|
|
@ -92,7 +92,11 @@ static void qmp_chardev_open_file(Chardev *chr,
|
|||
}
|
||||
}
|
||||
|
||||
qemu_chr_open_fd(chr, in, out);
|
||||
if (!qemu_chr_open_fd(chr, in, out, errp)) {
|
||||
qemu_close(out);
|
||||
qemu_close(in);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -150,7 +150,14 @@ static void qemu_chr_open_pipe(Chardev *chr,
|
|||
return;
|
||||
}
|
||||
}
|
||||
qemu_chr_open_fd(chr, fd_in, fd_out);
|
||||
|
||||
if (!qemu_chr_open_fd(chr, fd_in, fd_out, errp)) {
|
||||
close(fd_in);
|
||||
if (fd_out != fd_in) {
|
||||
close(fd_out);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* !_WIN32 */
|
||||
|
|
|
|||
|
|
@ -349,8 +349,8 @@ static void char_pty_open(Chardev *chr,
|
|||
}
|
||||
|
||||
close(slave_fd);
|
||||
if (!g_unix_set_fd_nonblocking(master_fd, true, NULL)) {
|
||||
error_setg_errno(errp, errno, "Failed to set FD nonblocking");
|
||||
if (!qemu_set_blocking(master_fd, false, errp)) {
|
||||
close(master_fd);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -271,13 +271,16 @@ static void qmp_chardev_open_serial(Chardev *chr,
|
|||
if (fd < 0) {
|
||||
return;
|
||||
}
|
||||
if (!g_unix_set_fd_nonblocking(fd, true, NULL)) {
|
||||
error_setg_errno(errp, errno, "Failed to set FD nonblocking");
|
||||
if (!qemu_set_blocking(fd, false, errp)) {
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
tty_serial_init(fd, 115200, 'N', 8, 1);
|
||||
|
||||
qemu_chr_open_fd(chr, fd, fd);
|
||||
if (!qemu_chr_open_fd(chr, fd, fd, errp)) {
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif /* __linux__ || __sun__ */
|
||||
|
||||
|
|
|
|||
|
|
@ -294,7 +294,12 @@ static ssize_t tcp_chr_recv(Chardev *chr, char *buf, size_t len)
|
|||
}
|
||||
|
||||
if (msgfds_num) {
|
||||
/* close and clean read_msgfds */
|
||||
/*
|
||||
* Close and clean previous read_msgfds, they are obsolete at
|
||||
* this point, regardless result of new call to
|
||||
* qio_channel_readv_full().
|
||||
*/
|
||||
|
||||
for (i = 0; i < s->read_msgfds_num; i++) {
|
||||
close(s->read_msgfds[i]);
|
||||
}
|
||||
|
|
@ -307,20 +312,6 @@ static ssize_t tcp_chr_recv(Chardev *chr, char *buf, size_t len)
|
|||
s->read_msgfds_num = msgfds_num;
|
||||
}
|
||||
|
||||
for (i = 0; i < s->read_msgfds_num; i++) {
|
||||
int fd = s->read_msgfds[i];
|
||||
if (fd < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* O_NONBLOCK is preserved across SCM_RIGHTS so reset it */
|
||||
qemu_socket_set_block(fd);
|
||||
|
||||
#ifndef MSG_CMSG_CLOEXEC
|
||||
qemu_set_cloexec(fd);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (ret == QIO_CHANNEL_ERR_BLOCK) {
|
||||
errno = EAGAIN;
|
||||
ret = -1;
|
||||
|
|
@ -539,16 +530,24 @@ static int tcp_chr_sync_read(Chardev *chr, const uint8_t *buf, int len)
|
|||
SocketChardev *s = SOCKET_CHARDEV(chr);
|
||||
int size;
|
||||
int saved_errno;
|
||||
Error *local_err = NULL;
|
||||
|
||||
if (s->state != TCP_CHARDEV_STATE_CONNECTED) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
qio_channel_set_blocking(s->ioc, true, NULL);
|
||||
if (!qio_channel_set_blocking(s->ioc, true, &local_err)) {
|
||||
error_report_err(local_err);
|
||||
return -1;
|
||||
}
|
||||
size = tcp_chr_recv(chr, (void *) buf, len);
|
||||
saved_errno = errno;
|
||||
if (s->state != TCP_CHARDEV_STATE_DISCONNECTED) {
|
||||
qio_channel_set_blocking(s->ioc, false, NULL);
|
||||
if (!qio_channel_set_blocking(s->ioc, false, &local_err)) {
|
||||
error_report_err(local_err);
|
||||
/* failed to recover non-blocking state */
|
||||
tcp_chr_disconnect(chr);
|
||||
}
|
||||
}
|
||||
if (size == 0) {
|
||||
/* connection closed */
|
||||
|
|
@ -893,18 +892,22 @@ static void tcp_chr_set_client_ioc_name(Chardev *chr,
|
|||
static int tcp_chr_new_client(Chardev *chr, QIOChannelSocket *sioc)
|
||||
{
|
||||
SocketChardev *s = SOCKET_CHARDEV(chr);
|
||||
Error *local_err = NULL;
|
||||
|
||||
if (s->state != TCP_CHARDEV_STATE_CONNECTING) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!qio_channel_set_blocking(QIO_CHANNEL(sioc), false, &local_err)) {
|
||||
error_report_err(local_err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
s->ioc = QIO_CHANNEL(sioc);
|
||||
object_ref(OBJECT(sioc));
|
||||
s->sioc = sioc;
|
||||
object_ref(OBJECT(sioc));
|
||||
|
||||
qio_channel_set_blocking(s->ioc, false, NULL);
|
||||
|
||||
if (s->do_nodelay) {
|
||||
qio_channel_set_delay(s->ioc, false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,18 +107,20 @@ static void qemu_chr_open_stdio(Chardev *chr,
|
|||
old_fd0_flags = fcntl(0, F_GETFL);
|
||||
old_fd1_flags = fcntl(1, F_GETFL);
|
||||
tcgetattr(0, &oldtty);
|
||||
if (!g_unix_set_fd_nonblocking(0, true, NULL)) {
|
||||
error_setg_errno(errp, errno, "Failed to set FD nonblocking");
|
||||
if (!qemu_set_blocking(0, false, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!qemu_chr_open_fd(chr, 0, 1, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
atexit(term_exit);
|
||||
|
||||
memset(&act, 0, sizeof(act));
|
||||
act.sa_handler = term_stdio_handler;
|
||||
sigaction(SIGCONT, &act, NULL);
|
||||
|
||||
qemu_chr_open_fd(chr, 0, 1);
|
||||
|
||||
stdio_allow_signal = !opts->has_signal || opts->signal;
|
||||
qemu_chr_set_echo_stdio(chr, false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
* top-level directory.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/host-utils.h"
|
||||
#include "qemu/sockets.h"
|
||||
|
||||
|
|
@ -135,6 +136,7 @@ ivshmem_server_handle_new_conn(IvshmemServer *server)
|
|||
socklen_t unaddr_len;
|
||||
int newfd;
|
||||
unsigned i;
|
||||
Error *local_err = NULL;
|
||||
|
||||
/* accept the incoming connection */
|
||||
unaddr_len = sizeof(unaddr);
|
||||
|
|
@ -146,9 +148,14 @@ ivshmem_server_handle_new_conn(IvshmemServer *server)
|
|||
return -1;
|
||||
}
|
||||
|
||||
qemu_socket_set_nonblock(newfd);
|
||||
IVSHMEM_SERVER_DEBUG(server, "accept()=%d\n", newfd);
|
||||
|
||||
if (!qemu_set_blocking(newfd, false, &local_err)) {
|
||||
error_report_err(local_err);
|
||||
close(newfd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* allocate new structure for this peer */
|
||||
peer = g_malloc0(sizeof(*peer));
|
||||
peer->sock_fd = newfd;
|
||||
|
|
|
|||
|
|
@ -338,7 +338,9 @@ static void hv_syndbg_realize(DeviceState *dev, Error **errp)
|
|||
return;
|
||||
}
|
||||
|
||||
qemu_socket_set_nonblock(syndbg->socket);
|
||||
if (!qemu_set_blocking(syndbg->socket, false, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
syndbg->servaddr.sin_port = htons(syndbg->host_port);
|
||||
syndbg->servaddr.sin_family = AF_INET;
|
||||
|
|
|
|||
|
|
@ -114,8 +114,7 @@ static void virtio_input_host_realize(DeviceState *dev, Error **errp)
|
|||
error_setg_file_open(errp, errno, vih->evdev);
|
||||
return;
|
||||
}
|
||||
if (!g_unix_set_fd_nonblocking(vih->fd, true, NULL)) {
|
||||
error_setg_errno(errp, errno, "Failed to set FD nonblocking");
|
||||
if (!qemu_set_blocking(vih->fd, false, errp)) {
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -154,7 +154,8 @@ static void ivshmem_flat_add_vector(IvshmemFTState *s, IvshmemPeer *peer,
|
|||
* peer.
|
||||
*/
|
||||
peer->vector[peer->vector_counter].id = peer->vector_counter;
|
||||
g_unix_set_fd_nonblocking(vector_fd, true, NULL);
|
||||
/* WARNING: qemu_socket_set_nonblock() return code ignored */
|
||||
qemu_set_blocking(vector_fd, false, &error_warn);
|
||||
event_notifier_init_fd(&peer->vector[peer->vector_counter].event_notifier,
|
||||
vector_fd);
|
||||
|
||||
|
|
|
|||
|
|
@ -540,7 +540,12 @@ static void process_msg_connect(IVShmemState *s, uint16_t posn, int fd,
|
|||
|
||||
IVSHMEM_DPRINTF("eventfds[%d][%d] = %d\n", posn, vector, fd);
|
||||
event_notifier_init_fd(&peer->eventfds[vector], fd);
|
||||
g_unix_set_fd_nonblocking(fd, true, NULL); /* msix/irqfd poll non block */
|
||||
|
||||
/* msix/irqfd poll non block */
|
||||
if (!qemu_set_blocking(fd, false, errp)) {
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
if (posn == s->vm_id) {
|
||||
setup_interrupt(s, vector, errp);
|
||||
|
|
|
|||
|
|
@ -112,8 +112,12 @@ static void pci_proxy_dev_realize(PCIDevice *device, Error **errp)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!qio_channel_set_blocking(dev->ioc, true, errp)) {
|
||||
object_unref(dev->ioc);
|
||||
return;
|
||||
}
|
||||
|
||||
qemu_mutex_init(&dev->io_mutex);
|
||||
qio_channel_set_blocking(dev->ioc, true, NULL);
|
||||
|
||||
pci_conf[PCI_LATENCY_TIMER] = 0xff;
|
||||
pci_conf[PCI_INTERRUPT_PIN] = 0x01;
|
||||
|
|
|
|||
|
|
@ -107,7 +107,11 @@ static void remote_object_machine_done(Notifier *notifier, void *data)
|
|||
error_report_err(err);
|
||||
return;
|
||||
}
|
||||
qio_channel_set_blocking(ioc, false, NULL);
|
||||
if (!qio_channel_set_blocking(ioc, false, &err)) {
|
||||
error_report_err(err);
|
||||
object_unref(OBJECT(ioc));
|
||||
return;
|
||||
}
|
||||
|
||||
o->dev = dev;
|
||||
|
||||
|
|
|
|||
|
|
@ -886,10 +886,11 @@ VFIOUserProxy *vfio_user_connect_dev(SocketAddress *addr, Error **errp)
|
|||
sioc = qio_channel_socket_new();
|
||||
ioc = QIO_CHANNEL(sioc);
|
||||
if (qio_channel_socket_connect_sync(sioc, addr, errp) < 0) {
|
||||
object_unref(OBJECT(ioc));
|
||||
return NULL;
|
||||
goto fail;
|
||||
}
|
||||
if (!qio_channel_set_blocking(ioc, false, errp)) {
|
||||
goto fail;
|
||||
}
|
||||
qio_channel_set_blocking(ioc, false, NULL);
|
||||
|
||||
proxy = g_malloc0(sizeof(VFIOUserProxy));
|
||||
proxy->sockname = g_strdup_printf("unix:%s", sockname);
|
||||
|
|
@ -923,6 +924,10 @@ VFIOUserProxy *vfio_user_connect_dev(SocketAddress *addr, Error **errp)
|
|||
QLIST_INSERT_HEAD(&vfio_user_sockets, proxy, next);
|
||||
|
||||
return proxy;
|
||||
|
||||
fail:
|
||||
object_unref(OBJECT(ioc));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void vfio_user_set_handler(VFIODevice *vbasedev,
|
||||
|
|
|
|||
|
|
@ -2039,7 +2039,10 @@ static int vhost_user_postcopy_advise(struct vhost_dev *dev, Error **errp)
|
|||
error_setg(errp, "%s: Failed to get ufd", __func__);
|
||||
return -EIO;
|
||||
}
|
||||
qemu_socket_set_nonblock(ufd);
|
||||
if (!qemu_set_blocking(ufd, false, errp)) {
|
||||
close(ufd);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* register ufd with userfault thread */
|
||||
u->postcopy_fd.fd = ufd;
|
||||
|
|
|
|||
|
|
@ -147,9 +147,7 @@ static void vhost_vsock_device_realize(DeviceState *dev, Error **errp)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!g_unix_set_fd_nonblocking(vhostfd, true, NULL)) {
|
||||
error_setg_errno(errp, errno,
|
||||
"vhost-vsock: unable to set non-blocking mode");
|
||||
if (!qemu_set_blocking(vhostfd, false, errp)) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -160,9 +158,7 @@ static void vhost_vsock_device_realize(DeviceState *dev, Error **errp)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!g_unix_set_fd_nonblocking(vhostfd, true, NULL)) {
|
||||
error_setg_errno(errp, errno,
|
||||
"Failed to set FD nonblocking");
|
||||
if (!qemu_set_blocking(vhostfd, false, errp)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ typedef struct FDChardev FDChardev;
|
|||
DECLARE_INSTANCE_CHECKER(FDChardev, FD_CHARDEV,
|
||||
TYPE_CHARDEV_FD)
|
||||
|
||||
void qemu_chr_open_fd(Chardev *chr, int fd_in, int fd_out);
|
||||
bool qemu_chr_open_fd(Chardev *chr, int fd_in, int fd_out, Error **errp);
|
||||
int qmp_chardev_open_file_source(char *src, int flags, Error **errp);
|
||||
|
||||
#endif /* CHAR_FD_H */
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ OBJECT_DECLARE_TYPE(QIOChannel, QIOChannelClass,
|
|||
|
||||
#define QIO_CHANNEL_READ_FLAG_MSG_PEEK 0x1
|
||||
#define QIO_CHANNEL_READ_FLAG_RELAXED_EOF 0x2
|
||||
#define QIO_CHANNEL_READ_FLAG_FD_PRESERVE_BLOCKING 0x4
|
||||
|
||||
typedef enum QIOChannelFeature QIOChannelFeature;
|
||||
|
||||
|
|
@ -117,6 +118,15 @@ struct QIOChannelClass {
|
|||
size_t nfds,
|
||||
int flags,
|
||||
Error **errp);
|
||||
|
||||
/*
|
||||
* The io_readv handler must guarantee that all
|
||||
* incoming fds are set BLOCKING (unless
|
||||
* QIO_CHANNEL_READ_FLAG_FD_PRESERVE_BLOCKING flag is set) and
|
||||
* CLOEXEC (if available).
|
||||
* @fds and @nfds are set only on success path. Still, setting
|
||||
* @fds and @nfds to zero is acceptable on failure path.
|
||||
*/
|
||||
ssize_t (*io_readv)(QIOChannel *ioc,
|
||||
const struct iovec *iov,
|
||||
size_t niov,
|
||||
|
|
@ -124,6 +134,7 @@ struct QIOChannelClass {
|
|||
size_t *nfds,
|
||||
int flags,
|
||||
Error **errp);
|
||||
|
||||
int (*io_close)(QIOChannel *ioc,
|
||||
Error **errp);
|
||||
GSource * (*io_create_watch)(QIOChannel *ioc,
|
||||
|
|
@ -234,6 +245,13 @@ void qio_channel_set_name(QIOChannel *ioc,
|
|||
* was allocated. It is the callers responsibility
|
||||
* to call close() on each file descriptor and to
|
||||
* call g_free() on the array pointer in @fds.
|
||||
* @fds allocated and set (and @nfds is set too)
|
||||
* _only_ on success path. Still, @fds and @nfds
|
||||
* may be set to zero on failure path.
|
||||
* qio_channel_readv_full() guarantees that all
|
||||
* incoming fds are set BLOCKING (unless
|
||||
* QIO_CHANNEL_READ_FLAG_FD_PRESERVE_BLOCKING flag
|
||||
* is set) and CLOEXEC (if available).
|
||||
*
|
||||
* It is an error to pass a non-NULL @fds parameter
|
||||
* unless qio_channel_has_feature() returns a true
|
||||
|
|
@ -513,9 +531,9 @@ int coroutine_mixed_fn qio_channel_write_all(QIOChannel *ioc,
|
|||
* return QIO_CHANNEL_ERR_BLOCK if they would otherwise
|
||||
* block on I/O
|
||||
*/
|
||||
int qio_channel_set_blocking(QIOChannel *ioc,
|
||||
bool enabled,
|
||||
Error **errp);
|
||||
bool qio_channel_set_blocking(QIOChannel *ioc,
|
||||
bool enabled,
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* qio_channel_set_follow_coroutine_ctx:
|
||||
|
|
|
|||
|
|
@ -687,6 +687,7 @@ ssize_t qemu_write_full(int fd, const void *buf, size_t count)
|
|||
G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
void qemu_set_cloexec(int fd);
|
||||
bool qemu_set_blocking(int fd, bool block, Error **errp);
|
||||
|
||||
/* Return a dynamically allocated directory path that is appropriate for storing
|
||||
* local state.
|
||||
|
|
|
|||
|
|
@ -46,9 +46,6 @@ ssize_t qemu_send_full(int s, const void *buf, size_t count)
|
|||
G_GNUC_WARN_UNUSED_RESULT;
|
||||
int socket_set_cork(int fd, int v);
|
||||
int socket_set_nodelay(int fd);
|
||||
void qemu_socket_set_block(int fd);
|
||||
int qemu_socket_try_set_nonblock(int fd);
|
||||
void qemu_socket_set_nonblock(int fd);
|
||||
int socket_set_fast_reuse(int fd);
|
||||
|
||||
#ifdef WIN32
|
||||
|
|
|
|||
|
|
@ -277,9 +277,12 @@ static int qio_channel_command_set_blocking(QIOChannel *ioc,
|
|||
cioc->blocking = enabled;
|
||||
#else
|
||||
|
||||
if ((cioc->writefd >= 0 && !g_unix_set_fd_nonblocking(cioc->writefd, !enabled, NULL)) ||
|
||||
(cioc->readfd >= 0 && !g_unix_set_fd_nonblocking(cioc->readfd, !enabled, NULL))) {
|
||||
error_setg_errno(errp, errno, "Failed to set FD nonblocking");
|
||||
if (cioc->writefd >= 0 &&
|
||||
!qemu_set_blocking(cioc->writefd, enabled, errp)) {
|
||||
return -1;
|
||||
}
|
||||
if (cioc->readfd >= 0 &&
|
||||
!qemu_set_blocking(cioc->readfd, enabled, errp)) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -223,8 +223,7 @@ static int qio_channel_file_set_blocking(QIOChannel *ioc,
|
|||
#else
|
||||
QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);
|
||||
|
||||
if (!g_unix_set_fd_nonblocking(fioc->fd, !enabled, NULL)) {
|
||||
error_setg_errno(errp, errno, "Failed to set FD nonblocking");
|
||||
if (!qemu_set_blocking(fioc->fd, enabled, errp)) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -472,7 +472,7 @@ static void qio_channel_socket_copy_fds(struct msghdr *msg,
|
|||
*fds = NULL;
|
||||
|
||||
for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
|
||||
int fd_size, i;
|
||||
int fd_size;
|
||||
int gotfds;
|
||||
|
||||
if (cmsg->cmsg_len < CMSG_LEN(sizeof(int)) ||
|
||||
|
|
@ -490,24 +490,55 @@ static void qio_channel_socket_copy_fds(struct msghdr *msg,
|
|||
gotfds = fd_size / sizeof(int);
|
||||
*fds = g_renew(int, *fds, *nfds + gotfds);
|
||||
memcpy(*fds + *nfds, CMSG_DATA(cmsg), fd_size);
|
||||
|
||||
for (i = 0; i < gotfds; i++) {
|
||||
int fd = (*fds)[*nfds + i];
|
||||
if (fd < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* O_NONBLOCK is preserved across SCM_RIGHTS so reset it */
|
||||
qemu_socket_set_block(fd);
|
||||
|
||||
#ifndef MSG_CMSG_CLOEXEC
|
||||
qemu_set_cloexec(fd);
|
||||
#endif
|
||||
}
|
||||
*nfds += gotfds;
|
||||
}
|
||||
}
|
||||
|
||||
static bool qio_channel_handle_fds(int *fds, size_t nfds,
|
||||
bool preserve_blocking, Error **errp)
|
||||
{
|
||||
int *end = fds + nfds, *fd;
|
||||
|
||||
#ifdef MSG_CMSG_CLOEXEC
|
||||
if (preserve_blocking) {
|
||||
/* Nothing to do */
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (fd = fds; fd != end; fd++) {
|
||||
if (*fd < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!preserve_blocking) {
|
||||
/* O_NONBLOCK is preserved across SCM_RIGHTS so reset it */
|
||||
if (!qemu_set_blocking(*fd, true, errp)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef MSG_CMSG_CLOEXEC
|
||||
qemu_set_cloexec(*fd);
|
||||
#endif
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void qio_channel_cleanup_fds(int **fds, size_t *nfds)
|
||||
{
|
||||
for (size_t i = 0; i < *nfds; i++) {
|
||||
if ((*fds)[i] < 0) {
|
||||
continue;
|
||||
}
|
||||
close((*fds)[i]);
|
||||
}
|
||||
|
||||
g_clear_pointer(fds, g_free);
|
||||
*nfds = 0;
|
||||
}
|
||||
|
||||
|
||||
static ssize_t qio_channel_socket_readv(QIOChannel *ioc,
|
||||
const struct iovec *iov,
|
||||
|
|
@ -556,7 +587,16 @@ static ssize_t qio_channel_socket_readv(QIOChannel *ioc,
|
|||
}
|
||||
|
||||
if (fds && nfds) {
|
||||
bool preserve_blocking =
|
||||
flags & QIO_CHANNEL_READ_FLAG_FD_PRESERVE_BLOCKING;
|
||||
|
||||
qio_channel_socket_copy_fds(&msg, fds, nfds);
|
||||
|
||||
if (!qio_channel_handle_fds(*fds, *nfds,
|
||||
preserve_blocking, errp)) {
|
||||
qio_channel_cleanup_fds(fds, nfds);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
@ -820,11 +860,10 @@ qio_channel_socket_set_blocking(QIOChannel *ioc,
|
|||
{
|
||||
QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
|
||||
|
||||
if (enabled) {
|
||||
qemu_socket_set_block(sioc->fd);
|
||||
} else {
|
||||
qemu_socket_set_nonblock(sioc->fd);
|
||||
if (!qemu_set_blocking(sioc->fd, enabled, errp)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -425,7 +425,7 @@ static int qio_channel_tls_set_blocking(QIOChannel *ioc,
|
|||
{
|
||||
QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc);
|
||||
|
||||
return qio_channel_set_blocking(tioc->master, enabled, errp);
|
||||
return qio_channel_set_blocking(tioc->master, enabled, errp) ? 0 : -1;
|
||||
}
|
||||
|
||||
static void qio_channel_tls_set_delay(QIOChannel *ioc,
|
||||
|
|
|
|||
|
|
@ -1184,8 +1184,7 @@ static int qio_channel_websock_set_blocking(QIOChannel *ioc,
|
|||
{
|
||||
QIOChannelWebsock *wioc = QIO_CHANNEL_WEBSOCK(ioc);
|
||||
|
||||
qio_channel_set_blocking(wioc->master, enabled, errp);
|
||||
return 0;
|
||||
return qio_channel_set_blocking(wioc->master, enabled, errp) ? 0 : -1;
|
||||
}
|
||||
|
||||
static void qio_channel_websock_set_delay(QIOChannel *ioc,
|
||||
|
|
|
|||
|
|
@ -359,12 +359,12 @@ int coroutine_mixed_fn qio_channel_write_all(QIOChannel *ioc,
|
|||
}
|
||||
|
||||
|
||||
int qio_channel_set_blocking(QIOChannel *ioc,
|
||||
bool qio_channel_set_blocking(QIOChannel *ioc,
|
||||
bool enabled,
|
||||
Error **errp)
|
||||
{
|
||||
QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
|
||||
return klass->io_set_blocking(ioc, enabled, errp);
|
||||
return klass->io_set_blocking(ioc, enabled, errp) == 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -859,7 +859,10 @@ static void *colo_process_incoming_thread(void *opaque)
|
|||
* coroutine, and here we are in the COLO incoming thread, so it is ok to
|
||||
* set the fd back to blocked.
|
||||
*/
|
||||
qemu_file_set_blocking(mis->from_src_file, true);
|
||||
if (!qemu_file_set_blocking(mis->from_src_file, true, &local_err)) {
|
||||
error_report_err(local_err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
colo_incoming_start_dirty_log();
|
||||
|
||||
|
|
|
|||
|
|
@ -951,7 +951,7 @@ static void migration_incoming_setup(QEMUFile *f)
|
|||
|
||||
assert(!mis->from_src_file);
|
||||
mis->from_src_file = f;
|
||||
qemu_file_set_blocking(f, false);
|
||||
qemu_file_set_blocking(f, false, &error_abort);
|
||||
}
|
||||
|
||||
void migration_incoming_process(void)
|
||||
|
|
@ -971,7 +971,7 @@ static bool postcopy_try_recover(void)
|
|||
/* This should be set already in migration_incoming_setup() */
|
||||
assert(mis->from_src_file);
|
||||
/* Postcopy has standalone thread to do vm load */
|
||||
qemu_file_set_blocking(mis->from_src_file, true);
|
||||
qemu_file_set_blocking(mis->from_src_file, true, &error_abort);
|
||||
|
||||
/* Re-configure the return path */
|
||||
mis->to_src_file = qemu_file_get_return_path(mis->from_src_file);
|
||||
|
|
@ -4002,7 +4002,9 @@ void migration_connect(MigrationState *s, Error *error_in)
|
|||
}
|
||||
|
||||
migration_rate_set(rate_limit);
|
||||
qemu_file_set_blocking(s->to_dst_file, true);
|
||||
if (!qemu_file_set_blocking(s->to_dst_file, true, &local_err)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Open the return path. For postcopy, it is used exclusively. For
|
||||
|
|
|
|||
|
|
@ -1909,7 +1909,7 @@ void postcopy_preempt_new_channel(MigrationIncomingState *mis, QEMUFile *file)
|
|||
* The new loading channel has its own threads, so it needs to be
|
||||
* blocked too. It's by default true, just be explicit.
|
||||
*/
|
||||
qemu_file_set_blocking(file, true);
|
||||
qemu_file_set_blocking(file, true, &error_abort);
|
||||
mis->postcopy_qemufile_dst = file;
|
||||
qemu_sem_post(&mis->postcopy_qemufile_dst_done);
|
||||
trace_postcopy_preempt_new_channel();
|
||||
|
|
|
|||
|
|
@ -340,7 +340,8 @@ static ssize_t coroutine_mixed_fn qemu_fill_buffer(QEMUFile *f)
|
|||
|
||||
do {
|
||||
struct iovec iov = { f->buf + pending, IO_BUF_SIZE - pending };
|
||||
len = qio_channel_readv_full(f->ioc, &iov, 1, pfds, pnfd, 0,
|
||||
len = qio_channel_readv_full(f->ioc, &iov, 1, pfds, pnfd,
|
||||
QIO_CHANNEL_READ_FLAG_FD_PRESERVE_BLOCKING,
|
||||
&local_error);
|
||||
if (len == QIO_CHANNEL_ERR_BLOCK) {
|
||||
if (qemu_in_coroutine()) {
|
||||
|
|
@ -887,9 +888,9 @@ void qemu_put_counted_string(QEMUFile *f, const char *str)
|
|||
* both directions, and thus changing the blocking on the main
|
||||
* QEMUFile can also affect the return path.
|
||||
*/
|
||||
void qemu_file_set_blocking(QEMUFile *f, bool block)
|
||||
bool qemu_file_set_blocking(QEMUFile *f, bool block, Error **errp)
|
||||
{
|
||||
qio_channel_set_blocking(f->ioc, block, NULL);
|
||||
return qio_channel_set_blocking(f->ioc, block, errp);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ void qemu_file_set_error(QEMUFile *f, int ret);
|
|||
int qemu_file_shutdown(QEMUFile *f);
|
||||
QEMUFile *qemu_file_get_return_path(QEMUFile *f);
|
||||
int qemu_fflush(QEMUFile *f);
|
||||
void qemu_file_set_blocking(QEMUFile *f, bool block);
|
||||
bool qemu_file_set_blocking(QEMUFile *f, bool block, Error **errp);
|
||||
int qemu_file_get_to_fd(QEMUFile *f, int fd, size_t size);
|
||||
void qemu_set_offset(QEMUFile *f, off_t off, int whence);
|
||||
off_t qemu_get_offset(QEMUFile *f);
|
||||
|
|
|
|||
|
|
@ -2095,7 +2095,7 @@ static void *postcopy_ram_listen_thread(void *opaque)
|
|||
* Because we're a thread and not a coroutine we can't yield
|
||||
* in qemu_file, and thus we must be blocking now.
|
||||
*/
|
||||
qemu_file_set_blocking(f, true);
|
||||
qemu_file_set_blocking(f, true, &error_fatal);
|
||||
|
||||
/* TODO: sanity check that only postcopiable data will be loaded here */
|
||||
load_res = qemu_loadvm_state_main(f, mis);
|
||||
|
|
@ -2108,7 +2108,7 @@ static void *postcopy_ram_listen_thread(void *opaque)
|
|||
f = mis->from_src_file;
|
||||
|
||||
/* And non-blocking again so we don't block in any cleanup */
|
||||
qemu_file_set_blocking(f, false);
|
||||
qemu_file_set_blocking(f, false, &error_fatal);
|
||||
|
||||
trace_postcopy_ram_listen_thread_exit();
|
||||
if (load_res < 0) {
|
||||
|
|
|
|||
|
|
@ -1411,7 +1411,9 @@ static coroutine_fn int nbd_negotiate(NBDClient *client, Error **errp)
|
|||
....options sent, ending in NBD_OPT_EXPORT_NAME or NBD_OPT_GO....
|
||||
*/
|
||||
|
||||
qio_channel_set_blocking(client->ioc, false, NULL);
|
||||
if (!qio_channel_set_blocking(client->ioc, false, errp)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
qio_channel_set_follow_coroutine_ctx(client->ioc, true);
|
||||
|
||||
trace_nbd_negotiate_begin();
|
||||
|
|
|
|||
28
net/dgram.c
28
net/dgram.c
|
|
@ -226,7 +226,10 @@ static int net_dgram_mcast_create(struct sockaddr_in *mcastaddr,
|
|||
}
|
||||
}
|
||||
|
||||
qemu_socket_set_nonblock(fd);
|
||||
if (!qemu_set_blocking(fd, false, errp)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return fd;
|
||||
fail:
|
||||
if (fd >= 0) {
|
||||
|
|
@ -284,7 +287,7 @@ static int net_dgram_mcast_init(NetClientState *peer,
|
|||
Error **errp)
|
||||
{
|
||||
NetDgramState *s;
|
||||
int fd, ret;
|
||||
int fd;
|
||||
struct sockaddr_in *saddr;
|
||||
|
||||
if (remote->type != SOCKET_ADDRESS_TYPE_INET) {
|
||||
|
|
@ -332,11 +335,8 @@ static int net_dgram_mcast_init(NetClientState *peer,
|
|||
g_free(saddr);
|
||||
return -1;
|
||||
}
|
||||
ret = qemu_socket_try_set_nonblock(fd);
|
||||
if (ret < 0) {
|
||||
if (!qemu_set_blocking(fd, false, errp)) {
|
||||
g_free(saddr);
|
||||
error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d",
|
||||
name, fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -504,7 +504,11 @@ int net_init_dgram(const Netdev *netdev, const char *name,
|
|||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
qemu_socket_set_nonblock(fd);
|
||||
|
||||
if (!qemu_set_blocking(fd, false, errp)) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dest_len = sizeof(raddr_in);
|
||||
dest_addr = g_malloc(dest_len);
|
||||
|
|
@ -551,7 +555,10 @@ int net_init_dgram(const Netdev *netdev, const char *name,
|
|||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
qemu_socket_set_nonblock(fd);
|
||||
if (!qemu_set_blocking(fd, false, errp)) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dest_len = sizeof(raddr_un);
|
||||
dest_addr = g_malloc(dest_len);
|
||||
|
|
@ -562,10 +569,7 @@ int net_init_dgram(const Netdev *netdev, const char *name,
|
|||
if (fd == -1) {
|
||||
return -1;
|
||||
}
|
||||
ret = qemu_socket_try_set_nonblock(fd);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d",
|
||||
name, fd);
|
||||
if (!qemu_set_blocking(fd, false, errp)) {
|
||||
return -1;
|
||||
}
|
||||
dest_addr = NULL;
|
||||
|
|
|
|||
|
|
@ -648,6 +648,9 @@ int net_init_l2tpv3(const Netdev *netdev,
|
|||
error_setg(errp, "could not bind socket err=%i", errno);
|
||||
goto outerr;
|
||||
}
|
||||
if (!qemu_set_blocking(fd, false, errp)) {
|
||||
goto outerr;
|
||||
}
|
||||
|
||||
freeaddrinfo(result);
|
||||
|
||||
|
|
@ -709,8 +712,6 @@ int net_init_l2tpv3(const Netdev *netdev,
|
|||
s->vec = g_new(struct iovec, MAX_L2TPV3_IOVCNT);
|
||||
s->header_buf = g_malloc(s->header_size);
|
||||
|
||||
qemu_socket_set_nonblock(fd);
|
||||
|
||||
s->fd = fd;
|
||||
s->counter = 0;
|
||||
|
||||
|
|
|
|||
27
net/socket.c
27
net/socket.c
|
|
@ -295,7 +295,10 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr,
|
|||
}
|
||||
}
|
||||
|
||||
qemu_socket_set_nonblock(fd);
|
||||
if (!qemu_set_blocking(fd, false, errp)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return fd;
|
||||
fail:
|
||||
if (fd >= 0)
|
||||
|
|
@ -508,7 +511,10 @@ static int net_socket_listen_init(NetClientState *peer,
|
|||
error_setg_errno(errp, errno, "can't create stream socket");
|
||||
return -1;
|
||||
}
|
||||
qemu_socket_set_nonblock(fd);
|
||||
if (!qemu_set_blocking(fd, false, errp)) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
socket_set_fast_reuse(fd);
|
||||
|
||||
|
|
@ -556,7 +562,10 @@ static int net_socket_connect_init(NetClientState *peer,
|
|||
error_setg_errno(errp, errno, "can't create stream socket");
|
||||
return -1;
|
||||
}
|
||||
qemu_socket_set_nonblock(fd);
|
||||
if (!qemu_set_blocking(fd, false, errp)) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
connected = 0;
|
||||
for(;;) {
|
||||
|
|
@ -671,7 +680,10 @@ static int net_socket_udp_init(NetClientState *peer,
|
|||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
qemu_socket_set_nonblock(fd);
|
||||
if (!qemu_set_blocking(fd, false, errp)) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
s = net_socket_fd_init_dgram(peer, model, name, fd, 0, NULL, errp);
|
||||
if (!s) {
|
||||
|
|
@ -706,7 +718,7 @@ int net_init_socket(const Netdev *netdev, const char *name,
|
|||
}
|
||||
|
||||
if (sock->fd) {
|
||||
int fd, ret, so_type;
|
||||
int fd, so_type;
|
||||
|
||||
fd = monitor_fd_param(monitor_cur(), sock->fd, errp);
|
||||
if (fd == -1) {
|
||||
|
|
@ -716,10 +728,7 @@ int net_init_socket(const Netdev *netdev, const char *name,
|
|||
if (so_type < 0) {
|
||||
return -1;
|
||||
}
|
||||
ret = qemu_socket_try_set_nonblock(fd);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d",
|
||||
name, fd);
|
||||
if (!qemu_set_blocking(fd, false, errp)) {
|
||||
return -1;
|
||||
}
|
||||
switch (so_type) {
|
||||
|
|
|
|||
|
|
@ -138,7 +138,6 @@ static void net_stream_server_listening(QIOTask *task, gpointer opaque)
|
|||
NetStreamData *d = opaque;
|
||||
QIOChannelSocket *listen_sioc = QIO_CHANNEL_SOCKET(d->listen_ioc);
|
||||
SocketAddress *addr;
|
||||
int ret;
|
||||
Error *err = NULL;
|
||||
|
||||
if (qio_task_propagate_error(task, &err)) {
|
||||
|
|
@ -149,13 +148,11 @@ static void net_stream_server_listening(QIOTask *task, gpointer opaque)
|
|||
|
||||
addr = qio_channel_socket_get_local_address(listen_sioc, NULL);
|
||||
g_assert(addr != NULL);
|
||||
ret = qemu_socket_try_set_nonblock(listen_sioc->fd);
|
||||
if (addr->type == SOCKET_ADDRESS_TYPE_FD && ret < 0) {
|
||||
qemu_set_info_str(&d->nc, "can't use file descriptor %s (errno %d)",
|
||||
addr->u.fd.str, -ret);
|
||||
if (!qemu_set_blocking(listen_sioc->fd, false, &err)) {
|
||||
qemu_set_info_str(&d->nc, "error: %s", error_get_pretty(err));
|
||||
error_free(err);
|
||||
return;
|
||||
}
|
||||
g_assert(ret == 0);
|
||||
qapi_free_SocketAddress(addr);
|
||||
|
||||
d->nc.link_down = true;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include "net/net.h"
|
||||
#include "io/channel.h"
|
||||
#include "io/net-listener.h"
|
||||
#include "qemu/sockets.h"
|
||||
|
||||
#include "stream_data.h"
|
||||
|
||||
|
|
@ -154,7 +155,6 @@ int net_stream_data_client_connected(QIOTask *task, NetStreamData *d)
|
|||
{
|
||||
QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(d->ioc);
|
||||
SocketAddress *addr;
|
||||
int ret;
|
||||
Error *err = NULL;
|
||||
|
||||
if (qio_task_propagate_error(task, &err)) {
|
||||
|
|
@ -166,14 +166,12 @@ int net_stream_data_client_connected(QIOTask *task, NetStreamData *d)
|
|||
addr = qio_channel_socket_get_remote_address(sioc, NULL);
|
||||
g_assert(addr != NULL);
|
||||
|
||||
ret = qemu_socket_try_set_nonblock(sioc->fd);
|
||||
if (addr->type == SOCKET_ADDRESS_TYPE_FD && ret < 0) {
|
||||
qemu_set_info_str(&d->nc, "can't use file descriptor %s (errno %d)",
|
||||
addr->u.fd.str, -ret);
|
||||
if (!qemu_set_blocking(sioc->fd, false, &err)) {
|
||||
qemu_set_info_str(&d->nc, "error: %s", error_get_pretty(err));
|
||||
error_free(err);
|
||||
qapi_free_SocketAddress(addr);
|
||||
goto error;
|
||||
}
|
||||
g_assert(ret == 0);
|
||||
qapi_free_SocketAddress(addr);
|
||||
|
||||
net_socket_rs_init(&d->rs, net_stream_data_rs_finalize, false);
|
||||
|
|
|
|||
|
|
@ -98,7 +98,12 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
g_unix_set_fd_nonblocking(fd, true, NULL);
|
||||
|
||||
if (!qemu_set_blocking(fd, false, errp)) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
|
@ -189,7 +194,10 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
|
|||
goto error;
|
||||
}
|
||||
|
||||
g_unix_set_fd_nonblocking(fd, true, NULL);
|
||||
if (!qemu_set_blocking(fd, false, errp)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
return fd;
|
||||
|
||||
error:
|
||||
|
|
|
|||
|
|
@ -124,7 +124,12 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
|
|||
return -1;
|
||||
}
|
||||
pstrcpy(ifname, ifname_size, ifr.ifr_name);
|
||||
g_unix_set_fd_nonblocking(fd, true, NULL);
|
||||
|
||||
if (!qemu_set_blocking(fd, false, errp)) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -198,7 +198,12 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
g_unix_set_fd_nonblocking(fd, true, NULL);
|
||||
|
||||
if (!qemu_set_blocking(fd, false, errp)) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
|
|
|||
21
net/tap.c
21
net/tap.c
|
|
@ -627,8 +627,7 @@ int net_init_bridge(const Netdev *netdev, const char *name,
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (!g_unix_set_fd_nonblocking(fd, true, NULL)) {
|
||||
error_setg_errno(errp, errno, "Failed to set FD nonblocking");
|
||||
if (!qemu_set_blocking(fd, false, errp)) {
|
||||
return -1;
|
||||
}
|
||||
vnet_hdr = tap_probe_vnet_hdr(fd, errp);
|
||||
|
|
@ -729,9 +728,7 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
|
|||
error_propagate(errp, err);
|
||||
goto failed;
|
||||
}
|
||||
if (!g_unix_set_fd_nonblocking(vhostfd, true, NULL)) {
|
||||
error_setg_errno(errp, errno, "%s: Can't use file descriptor %d",
|
||||
name, fd);
|
||||
if (!qemu_set_blocking(vhostfd, false, errp)) {
|
||||
goto failed;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -741,8 +738,7 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
|
|||
"tap: open vhost char device failed");
|
||||
goto failed;
|
||||
}
|
||||
if (!g_unix_set_fd_nonblocking(vhostfd, true, NULL)) {
|
||||
error_setg_errno(errp, errno, "Failed to set FD nonblocking");
|
||||
if (!qemu_set_blocking(vhostfd, false, errp)) {
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
|
@ -839,9 +835,7 @@ int net_init_tap(const Netdev *netdev, const char *name,
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (!g_unix_set_fd_nonblocking(fd, true, NULL)) {
|
||||
error_setg_errno(errp, errno, "%s: Can't use file descriptor %d",
|
||||
name, fd);
|
||||
if (!qemu_set_blocking(fd, false, errp)) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -895,10 +889,8 @@ int net_init_tap(const Netdev *netdev, const char *name,
|
|||
goto free_fail;
|
||||
}
|
||||
|
||||
if (!g_unix_set_fd_nonblocking(fd, true, NULL)) {
|
||||
if (!qemu_set_blocking(fd, false, errp)) {
|
||||
ret = -1;
|
||||
error_setg_errno(errp, errno, "%s: Can't use file descriptor %d",
|
||||
name, fd);
|
||||
goto free_fail;
|
||||
}
|
||||
|
||||
|
|
@ -951,8 +943,7 @@ free_fail:
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (!g_unix_set_fd_nonblocking(fd, true, NULL)) {
|
||||
error_setg_errno(errp, errno, "Failed to set FD nonblocking");
|
||||
if (!qemu_set_blocking(fd, false, errp)) {
|
||||
return -1;
|
||||
}
|
||||
vnet_hdr = tap_probe_vnet_hdr(fd, errp);
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ static gboolean ga_channel_listen_accept(GIOChannel *channel,
|
|||
GAChannel *c = data;
|
||||
int ret, client_fd;
|
||||
bool accepted = false;
|
||||
Error *err = NULL;
|
||||
|
||||
g_assert(channel != NULL);
|
||||
|
||||
|
|
@ -36,7 +37,11 @@ static gboolean ga_channel_listen_accept(GIOChannel *channel,
|
|||
g_warning("error converting fd to gsocket: %s", strerror(errno));
|
||||
goto out;
|
||||
}
|
||||
qemu_socket_set_nonblock(client_fd);
|
||||
if (!qemu_set_blocking(client_fd, false, &err)) {
|
||||
g_warning("%s", error_get_pretty(err));
|
||||
error_free(err);
|
||||
goto out;
|
||||
}
|
||||
ret = ga_channel_client_add(c, client_fd);
|
||||
if (ret) {
|
||||
g_warning("error setting up connection");
|
||||
|
|
|
|||
|
|
@ -503,9 +503,8 @@ int64_t qmp_guest_file_open(const char *path, const char *mode,
|
|||
/* set fd non-blocking to avoid common use cases (like reading from a
|
||||
* named pipe) from hanging the agent
|
||||
*/
|
||||
if (!g_unix_set_fd_nonblocking(fileno(fh), true, NULL)) {
|
||||
if (!qemu_set_blocking(fileno(fh), false, errp)) {
|
||||
fclose(fh);
|
||||
error_setg_errno(errp, errno, "Failed to set FD nonblocking");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -733,8 +733,11 @@ static void coroutine_fn prh_co_entry(void *opaque)
|
|||
uint32_t flags;
|
||||
int r;
|
||||
|
||||
qio_channel_set_blocking(QIO_CHANNEL(client->ioc),
|
||||
false, NULL);
|
||||
if (!qio_channel_set_blocking(QIO_CHANNEL(client->ioc),
|
||||
false, &local_err)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
qio_channel_set_follow_coroutine_ctx(QIO_CHANNEL(client->ioc), true);
|
||||
|
||||
/* A very simple negotiation for future extensibility. No features
|
||||
|
|
@ -786,6 +789,7 @@ static void coroutine_fn prh_co_entry(void *opaque)
|
|||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if (local_err) {
|
||||
if (verbose == 0) {
|
||||
error_free(local_err);
|
||||
|
|
@ -794,7 +798,6 @@ static void coroutine_fn prh_co_entry(void *opaque)
|
|||
}
|
||||
}
|
||||
|
||||
out:
|
||||
object_unref(OBJECT(client->ioc));
|
||||
g_free(client);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ static void *virtio_net_test_setup_socket(GString *cmd_line, void *arg)
|
|||
{
|
||||
int ret = socketpair(PF_UNIX, SOCK_STREAM, 0, sockfds);
|
||||
g_assert_cmpint(ret, !=, -1);
|
||||
g_unix_set_fd_nonblocking(sockfds[0], true, NULL);
|
||||
qemu_set_blocking(sockfds[0], false, &error_abort);
|
||||
sockfds_initialized = true;
|
||||
g_string_append_printf(cmd_line, " -netdev socket,fd=%d,id=hs0 ",
|
||||
sockfds[1]);
|
||||
|
|
|
|||
|
|
@ -330,7 +330,6 @@ static int chr_can_read(void *opaque)
|
|||
|
||||
static void chr_read(void *opaque, const uint8_t *buf, int size)
|
||||
{
|
||||
g_autoptr(GError) err = NULL;
|
||||
TestServer *s = opaque;
|
||||
CharBackend *chr = &s->chr;
|
||||
VhostUserMsg msg;
|
||||
|
|
@ -471,8 +470,7 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
|
|||
* The receive function forces it to be blocking,
|
||||
* so revert it back to non-blocking.
|
||||
*/
|
||||
g_unix_set_fd_nonblocking(fd, true, &err);
|
||||
g_assert_no_error(err);
|
||||
qemu_set_blocking(fd, false, &error_abort);
|
||||
break;
|
||||
|
||||
case VHOST_USER_SET_LOG_BASE:
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "qemu/osdep.h"
|
||||
#include "io-channel-helpers.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/iov.h"
|
||||
|
||||
struct QIOChannelTest {
|
||||
|
|
@ -109,8 +110,8 @@ void qio_channel_test_run_threads(QIOChannelTest *test,
|
|||
test->src = src;
|
||||
test->dst = dst;
|
||||
|
||||
qio_channel_set_blocking(test->dst, blocking, NULL);
|
||||
qio_channel_set_blocking(test->src, blocking, NULL);
|
||||
qio_channel_set_blocking(test->dst, blocking, &error_abort);
|
||||
qio_channel_set_blocking(test->src, blocking, &error_abort);
|
||||
|
||||
reader = g_thread_new("reader",
|
||||
test_io_thread_reader,
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/sockets.h"
|
||||
#include "socket-helpers.h"
|
||||
|
||||
|
|
@ -88,7 +89,8 @@ static int socket_can_bind_connect(const char *hostname, int family)
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
qemu_socket_set_nonblock(cfd);
|
||||
qemu_set_blocking(cfd, false, &error_abort);
|
||||
|
||||
if (connect(cfd, (struct sockaddr *)&ss, sslen) < 0) {
|
||||
if (errno == EINPROGRESS) {
|
||||
check_soerr = true;
|
||||
|
|
|
|||
|
|
@ -112,8 +112,8 @@ static void test_crypto_tls_session_psk(void)
|
|||
* thread, so we need these non-blocking to avoid deadlock
|
||||
* of ourselves
|
||||
*/
|
||||
qemu_socket_set_nonblock(channel[0]);
|
||||
qemu_socket_set_nonblock(channel[1]);
|
||||
qemu_set_blocking(channel[0], false, &error_abort);
|
||||
qemu_set_blocking(channel[1], false, &error_abort);
|
||||
|
||||
clientCreds = test_tls_creds_psk_create(
|
||||
QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT,
|
||||
|
|
@ -264,8 +264,8 @@ static void test_crypto_tls_session_x509(const void *opaque)
|
|||
* thread, so we need these non-blocking to avoid deadlock
|
||||
* of ourselves
|
||||
*/
|
||||
qemu_socket_set_nonblock(channel[0]);
|
||||
qemu_socket_set_nonblock(channel[1]);
|
||||
qemu_set_blocking(channel[0], false, &error_abort);
|
||||
qemu_set_blocking(channel[1], false, &error_abort);
|
||||
|
||||
#define CLIENT_CERT_DIR "tests/test-crypto-tlssession-client/"
|
||||
#define SERVER_CERT_DIR "tests/test-crypto-tlssession-server/"
|
||||
|
|
|
|||
|
|
@ -184,8 +184,8 @@ static void test_io_channel_tls(const void *opaque)
|
|||
* thread, so we need these non-blocking to avoid deadlock
|
||||
* of ourselves
|
||||
*/
|
||||
qio_channel_set_blocking(QIO_CHANNEL(clientChanSock), false, NULL);
|
||||
qio_channel_set_blocking(QIO_CHANNEL(serverChanSock), false, NULL);
|
||||
qio_channel_set_blocking(QIO_CHANNEL(clientChanSock), false, &error_abort);
|
||||
qio_channel_set_blocking(QIO_CHANNEL(serverChanSock), false, &error_abort);
|
||||
|
||||
/* Now the real part of the test, setup the sessions */
|
||||
clientChanTLS = qio_channel_tls_new_client(
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/iov.h"
|
||||
#include "qemu/sockets.h"
|
||||
|
||||
|
|
@ -186,7 +187,7 @@ static void test_io(void)
|
|||
|
||||
close(sv[0]);
|
||||
FD_SET(sv[1], &fds);
|
||||
g_unix_set_fd_nonblocking(sv[1], true, NULL);
|
||||
qemu_set_blocking(sv[1], false, &error_abort);
|
||||
r = g_test_rand_int_range(sz / 2, sz);
|
||||
setsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &r, sizeof(r));
|
||||
|
||||
|
|
@ -222,7 +223,7 @@ static void test_io(void)
|
|||
|
||||
close(sv[1]);
|
||||
FD_SET(sv[0], &fds);
|
||||
g_unix_set_fd_nonblocking(sv[0], true, NULL);
|
||||
qemu_set_blocking(sv[0], false, &error_abort);
|
||||
r = g_test_rand_int_range(sz / 2, sz);
|
||||
setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &r, sizeof(r));
|
||||
usleep(500000);
|
||||
|
|
|
|||
|
|
@ -213,8 +213,10 @@ static void coroutine_fn vh_co_entry(void *opaque)
|
|||
uint64_t vmsr;
|
||||
int r;
|
||||
|
||||
qio_channel_set_blocking(QIO_CHANNEL(client->ioc),
|
||||
false, NULL);
|
||||
if (!qio_channel_set_blocking(QIO_CHANNEL(client->ioc),
|
||||
false, &local_err)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
qio_channel_set_follow_coroutine_ctx(QIO_CHANNEL(client->ioc), true);
|
||||
|
||||
|
|
|
|||
|
|
@ -316,8 +316,7 @@ static void input_linux_complete(UserCreatable *uc, Error **errp)
|
|||
error_setg_file_open(errp, errno, il->evdev);
|
||||
return;
|
||||
}
|
||||
if (!g_unix_set_fd_nonblocking(il->fd, true, NULL)) {
|
||||
error_setg_errno(errp, errno, "Failed to set FD nonblocking");
|
||||
if (!qemu_set_blocking(il->fd, false, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
2
ui/vnc.c
2
ui/vnc.c
|
|
@ -3337,7 +3337,7 @@ static void vnc_connect(VncDisplay *vd, QIOChannelSocket *sioc,
|
|||
|
||||
VNC_DEBUG("New client on socket %p\n", vs->sioc);
|
||||
update_displaychangelistener(&vd->dcl, VNC_REFRESH_INTERVAL_BASE);
|
||||
qio_channel_set_blocking(vs->ioc, false, NULL);
|
||||
qio_channel_set_blocking(vs->ioc, false, &error_abort);
|
||||
if (vs->ioc_tag) {
|
||||
g_source_remove(vs->ioc_tag);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "qemu/event_notifier.h"
|
||||
#include "qemu/main-loop.h"
|
||||
|
|
@ -36,6 +37,7 @@ int event_notifier_init(EventNotifier *e, int active)
|
|||
{
|
||||
int fds[2];
|
||||
int ret;
|
||||
Error *local_err = NULL;
|
||||
|
||||
#ifdef CONFIG_EVENTFD
|
||||
ret = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
|
||||
|
|
@ -52,11 +54,11 @@ int event_notifier_init(EventNotifier *e, int active)
|
|||
if (!g_unix_open_pipe(fds, FD_CLOEXEC, NULL)) {
|
||||
return -errno;
|
||||
}
|
||||
if (!g_unix_set_fd_nonblocking(fds[0], true, NULL)) {
|
||||
if (!qemu_set_blocking(fds[0], false, &local_err)) {
|
||||
ret = -errno;
|
||||
goto fail;
|
||||
}
|
||||
if (!g_unix_set_fd_nonblocking(fds[1], true, NULL)) {
|
||||
if (!qemu_set_blocking(fds[1], false, &local_err)) {
|
||||
ret = -errno;
|
||||
goto fail;
|
||||
}
|
||||
|
|
@ -70,6 +72,7 @@ int event_notifier_init(EventNotifier *e, int active)
|
|||
return 0;
|
||||
|
||||
fail:
|
||||
error_report_err(local_err);
|
||||
close(fds[0]);
|
||||
close(fds[1]);
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -114,7 +114,10 @@ static int qemu_signal_init(Error **errp)
|
|||
return -errno;
|
||||
}
|
||||
|
||||
g_unix_set_fd_nonblocking(sigfd, true, NULL);
|
||||
if (!qemu_set_blocking(sigfd, false, errp)) {
|
||||
close(sigfd);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
qemu_set_fd_handler(sigfd, sigfd_handler, NULL, (void *)(intptr_t)sigfd);
|
||||
|
||||
|
|
|
|||
|
|
@ -250,21 +250,19 @@ void qemu_anon_ram_free(void *ptr, size_t size)
|
|||
#endif
|
||||
}
|
||||
|
||||
void qemu_socket_set_block(int fd)
|
||||
bool qemu_set_blocking(int fd, bool block, Error **errp)
|
||||
{
|
||||
g_unix_set_fd_nonblocking(fd, false, NULL);
|
||||
}
|
||||
g_autoptr(GError) err = NULL;
|
||||
|
||||
int qemu_socket_try_set_nonblock(int fd)
|
||||
{
|
||||
return g_unix_set_fd_nonblocking(fd, true, NULL) ? 0 : -errno;
|
||||
}
|
||||
if (!g_unix_set_fd_nonblocking(fd, !block, &err)) {
|
||||
error_setg_errno(errp, errno,
|
||||
"Can't set file descriptor %d %s: %s", fd,
|
||||
block ? "blocking" : "non-blocking",
|
||||
err->message);
|
||||
return false;
|
||||
}
|
||||
|
||||
void qemu_socket_set_nonblock(int fd)
|
||||
{
|
||||
int f;
|
||||
f = qemu_socket_try_set_nonblock(fd);
|
||||
assert(f == 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
int socket_set_fast_reuse(int fd)
|
||||
|
|
|
|||
|
|
@ -177,25 +177,22 @@ static int socket_error(void)
|
|||
}
|
||||
}
|
||||
|
||||
void qemu_socket_set_block(int fd)
|
||||
bool qemu_set_blocking(int fd, bool block, Error **errp)
|
||||
{
|
||||
unsigned long opt = 0;
|
||||
qemu_socket_unselect(fd, NULL);
|
||||
ioctlsocket(fd, FIONBIO, &opt);
|
||||
}
|
||||
unsigned long opt = block ? 0 : 1;
|
||||
|
||||
int qemu_socket_try_set_nonblock(int fd)
|
||||
{
|
||||
unsigned long opt = 1;
|
||||
if (ioctlsocket(fd, FIONBIO, &opt) != NO_ERROR) {
|
||||
return -socket_error();
|
||||
if (block) {
|
||||
qemu_socket_unselect(fd, NULL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void qemu_socket_set_nonblock(int fd)
|
||||
{
|
||||
(void)qemu_socket_try_set_nonblock(fd);
|
||||
if (ioctlsocket(fd, FIONBIO, &opt) != NO_ERROR) {
|
||||
error_setg_errno(errp, socket_error(),
|
||||
"Can't set file descriptor %d %s", fd,
|
||||
block ? "blocking" : "non-blocking");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int socket_set_fast_reuse(int fd)
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ static void vmsg_close_fds(VhostUserMsg *vmsg)
|
|||
}
|
||||
}
|
||||
|
||||
static void vmsg_unblock_fds(VhostUserMsg *vmsg)
|
||||
static bool vmsg_unblock_fds(VhostUserMsg *vmsg, Error **errp)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
|
@ -74,12 +74,16 @@ static void vmsg_unblock_fds(VhostUserMsg *vmsg)
|
|||
*/
|
||||
if (vmsg->request == VHOST_USER_ADD_MEM_REG ||
|
||||
vmsg->request == VHOST_USER_SET_MEM_TABLE) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
for (i = 0; i < vmsg->fd_num; i++) {
|
||||
qemu_socket_set_nonblock(vmsg->fds[i]);
|
||||
if (!qemu_set_blocking(vmsg->fds[i], false, errp)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void panic_cb(VuDev *vu_dev, const char *buf)
|
||||
|
|
@ -122,7 +126,6 @@ vu_message_read(VuDev *vu_dev, int conn_fd, VhostUserMsg *vmsg)
|
|||
|
||||
vmsg->fd_num = 0;
|
||||
if (!ioc) {
|
||||
error_report_err(local_err);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
@ -176,7 +179,10 @@ vu_message_read(VuDev *vu_dev, int conn_fd, VhostUserMsg *vmsg)
|
|||
} while (read_bytes != VHOST_USER_HDR_SIZE);
|
||||
|
||||
/* qio_channel_readv_full will make socket fds blocking, unblock them */
|
||||
vmsg_unblock_fds(vmsg);
|
||||
if (!vmsg_unblock_fds(vmsg, &local_err)) {
|
||||
error_report_err(local_err);
|
||||
goto fail;
|
||||
}
|
||||
if (vmsg->size > sizeof(vmsg->payload)) {
|
||||
error_report("Error: too big message request: %d, "
|
||||
"size: vmsg->size: %u, "
|
||||
|
|
@ -303,7 +309,8 @@ set_watch(VuDev *vu_dev, int fd, int vu_evt,
|
|||
|
||||
vu_fd_watch->fd = fd;
|
||||
vu_fd_watch->cb = cb;
|
||||
qemu_socket_set_nonblock(fd);
|
||||
/* TODO: handle error more gracefully than aborting */
|
||||
qemu_set_blocking(fd, false, &error_abort);
|
||||
aio_set_fd_handler(server->ctx, fd, kick_handler,
|
||||
NULL, NULL, NULL, vu_fd_watch);
|
||||
vu_fd_watch->vu_dev = vu_dev;
|
||||
|
|
@ -336,6 +343,7 @@ static void vu_accept(QIONetListener *listener, QIOChannelSocket *sioc,
|
|||
gpointer opaque)
|
||||
{
|
||||
VuServer *server = opaque;
|
||||
Error *local_err = NULL;
|
||||
|
||||
if (server->sioc) {
|
||||
warn_report("Only one vhost-user client is allowed to "
|
||||
|
|
@ -368,7 +376,11 @@ static void vu_accept(QIONetListener *listener, QIOChannelSocket *sioc,
|
|||
object_ref(OBJECT(server->ioc));
|
||||
|
||||
/* TODO vu_message_write() spins if non-blocking! */
|
||||
qio_channel_set_blocking(server->ioc, false, NULL);
|
||||
if (!qio_channel_set_blocking(server->ioc, false, &local_err)) {
|
||||
error_report_err(local_err);
|
||||
vu_deinit(&server->vu_dev);
|
||||
return;
|
||||
}
|
||||
|
||||
qio_channel_set_follow_coroutine_ctx(server->ioc, true);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue