qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v4 2/4] char: convert from GIOChannel to QIOChan


From: Laurent Vivier
Subject: Re: [Qemu-devel] [PATCH v4 2/4] char: convert from GIOChannel to QIOChannel
Date: Fri, 18 Mar 2016 17:43:42 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.6.0

Hi,

testing something else (migration...) I've discovered (by bisecting)
that this patch can allow to lock the machine. I'm using the pseries
machine, but I think it should happen with PC too.

I start a machine with:

        ...
        -device virtio-serial-pci,id=serial0 \
        -chardev socket,id=channel0,path=/tmp/serial_socket,server,nowait \
        -device virtserialport,bus=serial0.0,nr=1,chardev=channel0

and I open the unix socket /tmp/serial_socket without reading it:

$ python
import socket
sock = socket.socket(socket.AF_UNIX)
sock.connect("/tmp/serial_socket_1")

Then in the guest:

cat /dev/zero > /dev/vport1p1

-> at this point, the machine hangs until we read data in unix socket
(we can't interact with monitor, we can't ping the machine...)

Laurent

On 19/01/2016 12:14, Daniel P. Berrange wrote:
> In preparation for introducing TLS support to the TCP chardev
> backend, convert existing chardev code from using GIOChannel
> to QIOChannel. This simplifies the chardev code by removing
> most of the OS platform conditional code for dealing with
> file descriptor passing.
> 
> Signed-off-by: Daniel P. Berrange <address@hidden>
> ---
>  qemu-char.c    | 648 
> ++++++++++++++++++++++-----------------------------------
>  tests/Makefile |   2 +-
>  2 files changed, 254 insertions(+), 396 deletions(-)
> 
> diff --git a/qemu-char.c b/qemu-char.c
> index 8e96f90..8e9156a 100644
> --- a/qemu-char.c
> +++ b/qemu-char.c
> @@ -33,6 +33,8 @@
>  #include "qapi/qmp-output-visitor.h"
>  #include "qapi-visit.h"
>  #include "qemu/base64.h"
> +#include "io/channel-socket.h"
> +#include "io/channel-file.h"
>  
>  #include <unistd.h>
>  #include <fcntl.h>
> @@ -766,7 +768,7 @@ typedef struct IOWatchPoll
>  {
>      GSource parent;
>  
> -    GIOChannel *channel;
> +    QIOChannel *ioc;
>      GSource *src;
>  
>      IOCanReadHandler *fd_can_read;
> @@ -789,8 +791,8 @@ static gboolean io_watch_poll_prepare(GSource *source, 
> gint *timeout_)
>      }
>  
>      if (now_active) {
> -        iwp->src = g_io_create_watch(iwp->channel,
> -                                     G_IO_IN | G_IO_ERR | G_IO_HUP | 
> G_IO_NVAL);
> +        iwp->src = qio_channel_create_watch(
> +            iwp->ioc, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL);
>          g_source_set_callback(iwp->src, iwp->fd_read, iwp->opaque, NULL);
>          g_source_attach(iwp->src, NULL);
>      } else {
> @@ -836,9 +838,9 @@ static GSourceFuncs io_watch_poll_funcs = {
>  };
>  
>  /* Can only be used for read */
> -static guint io_add_watch_poll(GIOChannel *channel,
> +static guint io_add_watch_poll(QIOChannel *ioc,
>                                 IOCanReadHandler *fd_can_read,
> -                               GIOFunc fd_read,
> +                               QIOChannelFunc fd_read,
>                                 gpointer user_data)
>  {
>      IOWatchPoll *iwp;
> @@ -847,7 +849,7 @@ static guint io_add_watch_poll(GIOChannel *channel,
>      iwp = (IOWatchPoll *) g_source_new(&io_watch_poll_funcs, 
> sizeof(IOWatchPoll));
>      iwp->fd_can_read = fd_can_read;
>      iwp->opaque = user_data;
> -    iwp->channel = channel;
> +    iwp->ioc = ioc;
>      iwp->fd_read = (GSourceFunc) fd_read;
>      iwp->src = NULL;
>  
> @@ -883,79 +885,50 @@ static void remove_fd_in_watch(CharDriverState *chr)
>      }
>  }
>  
> -#ifndef _WIN32
> -static GIOChannel *io_channel_from_fd(int fd)
> -{
> -    GIOChannel *chan;
> -
> -    if (fd == -1) {
> -        return NULL;
> -    }
>  
> -    chan = g_io_channel_unix_new(fd);
> -
> -    g_io_channel_set_encoding(chan, NULL, NULL);
> -    g_io_channel_set_buffered(chan, FALSE);
> -
> -    return chan;
> -}
> -#endif
> -
> -static GIOChannel *io_channel_from_socket(int fd)
> +static int io_channel_send_full(QIOChannel *ioc,
> +                                const void *buf, size_t len,
> +                                int *fds, size_t nfds)
>  {
> -    GIOChannel *chan;
> +    size_t offset = 0;
>  
> -    if (fd == -1) {
> -        return NULL;
> -    }
> +    while (offset < len) {
> +        ssize_t ret = 0;
> +        struct iovec iov = { .iov_base = (char *)buf + offset,
> +                             .iov_len = len - offset };
> +
> +        ret = qio_channel_writev_full(
> +            ioc, &iov, 1,
> +            fds, nfds, NULL);
> +        if (ret == QIO_CHANNEL_ERR_BLOCK) {
> +            errno = EAGAIN;
> +            return -1;
> +        } else if (ret < 0) {
> +            if (offset) {
> +                return offset;
> +            }
>  
> -#ifdef _WIN32
> -    chan = g_io_channel_win32_new_socket(fd);
> -#else
> -    chan = g_io_channel_unix_new(fd);
> -#endif
> +            errno = EINVAL;
> +            return -1;
> +        }
>  
> -    g_io_channel_set_encoding(chan, NULL, NULL);
> -    g_io_channel_set_buffered(chan, FALSE);
> +        offset += ret;
> +    }
>  
> -    return chan;
> +    return offset;
>  }
>  
> -static int io_channel_send(GIOChannel *fd, const void *buf, size_t len)
> -{
> -    size_t offset = 0;
> -    GIOStatus status = G_IO_STATUS_NORMAL;
> -
> -    while (offset < len && status == G_IO_STATUS_NORMAL) {
> -        gsize bytes_written = 0;
>  
> -        status = g_io_channel_write_chars(fd, buf + offset, len - offset,
> -                                          &bytes_written, NULL);
> -        offset += bytes_written;
> -    }
> -
> -    if (offset > 0) {
> -        return offset;
> -    }
> -    switch (status) {
> -    case G_IO_STATUS_NORMAL:
> -        g_assert(len == 0);
> -        return 0;
> -    case G_IO_STATUS_AGAIN:
> -        errno = EAGAIN;
> -        return -1;
> -    default:
> -        break;
> -    }
> -    errno = EINVAL;
> -    return -1;
> +static int io_channel_send(QIOChannel *ioc, const void *buf, size_t len)
> +{
> +    return io_channel_send_full(ioc, buf, len, NULL, 0);
>  }
>  
>  #ifndef _WIN32
>  
>  typedef struct FDCharDriver {
>      CharDriverState *chr;
> -    GIOChannel *fd_in, *fd_out;
> +    QIOChannel *ioc_in, *ioc_out;
>      int max_size;
>  } FDCharDriver;
>  
> @@ -964,17 +937,16 @@ static int fd_chr_write(CharDriverState *chr, const 
> uint8_t *buf, int len)
>  {
>      FDCharDriver *s = chr->opaque;
>      
> -    return io_channel_send(s->fd_out, buf, len);
> +    return io_channel_send(s->ioc_out, buf, len);
>  }
>  
> -static gboolean fd_chr_read(GIOChannel *chan, GIOCondition cond, void 
> *opaque)
> +static gboolean fd_chr_read(QIOChannel *chan, GIOCondition cond, void 
> *opaque)
>  {
>      CharDriverState *chr = opaque;
>      FDCharDriver *s = chr->opaque;
>      int len;
>      uint8_t buf[READ_BUF_LEN];
> -    GIOStatus status;
> -    gsize bytes_read;
> +    ssize_t ret;
>  
>      len = sizeof(buf);
>      if (len > s->max_size) {
> @@ -984,15 +956,15 @@ static gboolean fd_chr_read(GIOChannel *chan, 
> GIOCondition cond, void *opaque)
>          return TRUE;
>      }
>  
> -    status = g_io_channel_read_chars(chan, (gchar *)buf,
> -                                     len, &bytes_read, NULL);
> -    if (status == G_IO_STATUS_EOF) {
> +    ret = qio_channel_read(
> +        chan, (gchar *)buf, len, NULL);
> +    if (ret == 0) {
>          remove_fd_in_watch(chr);
>          qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
>          return FALSE;
>      }
> -    if (status == G_IO_STATUS_NORMAL) {
> -        qemu_chr_be_write(chr, buf, bytes_read);
> +    if (ret > 0) {
> +        qemu_chr_be_write(chr, buf, ret);
>      }
>  
>      return TRUE;
> @@ -1010,7 +982,7 @@ static int fd_chr_read_poll(void *opaque)
>  static GSource *fd_chr_add_watch(CharDriverState *chr, GIOCondition cond)
>  {
>      FDCharDriver *s = chr->opaque;
> -    return g_io_create_watch(s->fd_out, cond);
> +    return qio_channel_create_watch(s->ioc_out, cond);
>  }
>  
>  static void fd_chr_update_read_handler(CharDriverState *chr)
> @@ -1018,8 +990,9 @@ static void fd_chr_update_read_handler(CharDriverState 
> *chr)
>      FDCharDriver *s = chr->opaque;
>  
>      remove_fd_in_watch(chr);
> -    if (s->fd_in) {
> -        chr->fd_in_tag = io_add_watch_poll(s->fd_in, fd_chr_read_poll,
> +    if (s->ioc_in) {
> +        chr->fd_in_tag = io_add_watch_poll(s->ioc_in,
> +                                           fd_chr_read_poll,
>                                             fd_chr_read, chr);
>      }
>  }
> @@ -1029,11 +1002,11 @@ static void fd_chr_close(struct CharDriverState *chr)
>      FDCharDriver *s = chr->opaque;
>  
>      remove_fd_in_watch(chr);
> -    if (s->fd_in) {
> -        g_io_channel_unref(s->fd_in);
> +    if (s->ioc_in) {
> +        object_unref(OBJECT(s->ioc_in));
>      }
> -    if (s->fd_out) {
> -        g_io_channel_unref(s->fd_out);
> +    if (s->ioc_out) {
> +        object_unref(OBJECT(s->ioc_out));
>      }
>  
>      g_free(s);
> @@ -1052,8 +1025,8 @@ static CharDriverState *qemu_chr_open_fd(int fd_in, int 
> fd_out,
>          return NULL;
>      }
>      s = g_new0(FDCharDriver, 1);
> -    s->fd_in = io_channel_from_fd(fd_in);
> -    s->fd_out = io_channel_from_fd(fd_out);
> +    s->ioc_in = QIO_CHANNEL(qio_channel_file_new_fd(fd_in));
> +    s->ioc_out = QIO_CHANNEL(qio_channel_file_new_fd(fd_out));
>      qemu_set_nonblock(fd_out);
>      s->chr = chr;
>      chr->opaque = s;
> @@ -1196,7 +1169,7 @@ static CharDriverState *qemu_chr_open_stdio(const char 
> *id,
>  #define HAVE_CHARDEV_PTY 1
>  
>  typedef struct {
> -    GIOChannel *fd;
> +    QIOChannel *ioc;
>      int read_bytes;
>  
>      /* Protected by the CharDriverState chr_write_lock.  */
> @@ -1247,8 +1220,9 @@ static void 
> pty_chr_update_read_handler_locked(CharDriverState *chr)
>      PtyCharDriver *s = chr->opaque;
>      GPollFD pfd;
>      int rc;
> +    QIOChannelFile *fioc = QIO_CHANNEL_FILE(s->ioc);
>  
> -    pfd.fd = g_io_channel_unix_get_fd(s->fd);
> +    pfd.fd = fioc->fd;
>      pfd.events = G_IO_OUT;
>      pfd.revents = 0;
>      do {
> @@ -1282,7 +1256,7 @@ static int pty_chr_write(CharDriverState *chr, const 
> uint8_t *buf, int len)
>              return 0;
>          }
>      }
> -    return io_channel_send(s->fd, buf, len);
> +    return io_channel_send(s->ioc, buf, len);
>  }
>  
>  static GSource *pty_chr_add_watch(CharDriverState *chr, GIOCondition cond)
> @@ -1291,7 +1265,7 @@ static GSource *pty_chr_add_watch(CharDriverState *chr, 
> GIOCondition cond)
>      if (!s->connected) {
>          return NULL;
>      }
> -    return g_io_create_watch(s->fd, cond);
> +    return qio_channel_create_watch(s->ioc, cond);
>  }
>  
>  static int pty_chr_read_poll(void *opaque)
> @@ -1303,13 +1277,13 @@ static int pty_chr_read_poll(void *opaque)
>      return s->read_bytes;
>  }
>  
> -static gboolean pty_chr_read(GIOChannel *chan, GIOCondition cond, void 
> *opaque)
> +static gboolean pty_chr_read(QIOChannel *chan, GIOCondition cond, void 
> *opaque)
>  {
>      CharDriverState *chr = opaque;
>      PtyCharDriver *s = chr->opaque;
> -    gsize size, len;
> +    gsize len;
>      uint8_t buf[READ_BUF_LEN];
> -    GIOStatus status;
> +    ssize_t ret;
>  
>      len = sizeof(buf);
>      if (len > s->read_bytes)
> @@ -1317,13 +1291,13 @@ static gboolean pty_chr_read(GIOChannel *chan, 
> GIOCondition cond, void *opaque)
>      if (len == 0) {
>          return TRUE;
>      }
> -    status = g_io_channel_read_chars(s->fd, (gchar *)buf, len, &size, NULL);
> -    if (status != G_IO_STATUS_NORMAL) {
> +    ret = qio_channel_read(s->ioc, (char *)buf, len, NULL);
> +    if (ret <= 0) {
>          pty_chr_state(chr, 0);
>          return FALSE;
>      } else {
>          pty_chr_state(chr, 1);
> -        qemu_chr_be_write(chr, buf, size);
> +        qemu_chr_be_write(chr, buf, ret);
>      }
>      return TRUE;
>  }
> @@ -1365,7 +1339,8 @@ static void pty_chr_state(CharDriverState *chr, int 
> connected)
>              s->open_tag = g_idle_add(qemu_chr_be_generic_open_func, chr);
>          }
>          if (!chr->fd_in_tag) {
> -            chr->fd_in_tag = io_add_watch_poll(s->fd, pty_chr_read_poll,
> +            chr->fd_in_tag = io_add_watch_poll(s->ioc,
> +                                               pty_chr_read_poll,
>                                                 pty_chr_read, chr);
>          }
>      }
> @@ -1374,13 +1349,10 @@ static void pty_chr_state(CharDriverState *chr, int 
> connected)
>  static void pty_chr_close(struct CharDriverState *chr)
>  {
>      PtyCharDriver *s = chr->opaque;
> -    int fd;
>  
>      qemu_mutex_lock(&chr->chr_write_lock);
>      pty_chr_state(chr, 0);
> -    fd = g_io_channel_unix_get_fd(s->fd);
> -    g_io_channel_unref(s->fd);
> -    close(fd);
> +    object_unref(OBJECT(s->ioc));
>      if (s->timer_tag) {
>          g_source_remove(s->timer_tag);
>          s->timer_tag = 0;
> @@ -1431,7 +1403,7 @@ static CharDriverState *qemu_chr_open_pty(const char 
> *id,
>      chr->chr_add_watch = pty_chr_add_watch;
>      chr->explicit_be_open = true;
>  
> -    s->fd = io_channel_from_fd(master_fd);
> +    s->ioc = QIO_CHANNEL(qio_channel_file_new_fd(master_fd));
>      s->timer_tag = 0;
>  
>      return chr;
> @@ -1555,12 +1527,13 @@ static void tty_serial_init(int fd, int speed,
>  static int tty_serial_ioctl(CharDriverState *chr, int cmd, void *arg)
>  {
>      FDCharDriver *s = chr->opaque;
> +    QIOChannelFile *fioc = QIO_CHANNEL_FILE(s->ioc_in);
>  
>      switch(cmd) {
>      case CHR_IOCTL_SERIAL_SET_PARAMS:
>          {
>              QEMUSerialSetParams *ssp = arg;
> -            tty_serial_init(g_io_channel_unix_get_fd(s->fd_in),
> +            tty_serial_init(fioc->fd,
>                              ssp->speed, ssp->parity,
>                              ssp->data_bits, ssp->stop_bits);
>          }
> @@ -1569,7 +1542,7 @@ static int tty_serial_ioctl(CharDriverState *chr, int 
> cmd, void *arg)
>          {
>              int enable = *(int *)arg;
>              if (enable) {
> -                tcsendbreak(g_io_channel_unix_get_fd(s->fd_in), 1);
> +                tcsendbreak(fioc->fd, 1);
>              }
>          }
>          break;
> @@ -1577,7 +1550,7 @@ static int tty_serial_ioctl(CharDriverState *chr, int 
> cmd, void *arg)
>          {
>              int sarg = 0;
>              int *targ = (int *)arg;
> -            ioctl(g_io_channel_unix_get_fd(s->fd_in), TIOCMGET, &sarg);
> +            ioctl(fioc->fd, TIOCMGET, &sarg);
>              *targ = 0;
>              if (sarg & TIOCM_CTS)
>                  *targ |= CHR_TIOCM_CTS;
> @@ -1597,7 +1570,7 @@ static int tty_serial_ioctl(CharDriverState *chr, int 
> cmd, void *arg)
>          {
>              int sarg = *(int *)arg;
>              int targ = 0;
> -            ioctl(g_io_channel_unix_get_fd(s->fd_in), TIOCMGET, &targ);
> +            ioctl(fioc->fd, TIOCMGET, &targ);
>              targ &= ~(CHR_TIOCM_CTS | CHR_TIOCM_CAR | CHR_TIOCM_DSR
>                       | CHR_TIOCM_RI | CHR_TIOCM_DTR | CHR_TIOCM_RTS);
>              if (sarg & CHR_TIOCM_CTS)
> @@ -1612,7 +1585,7 @@ static int tty_serial_ioctl(CharDriverState *chr, int 
> cmd, void *arg)
>                  targ |= TIOCM_DTR;
>              if (sarg & CHR_TIOCM_RTS)
>                  targ |= TIOCM_RTS;
> -            ioctl(g_io_channel_unix_get_fd(s->fd_in), TIOCMSET, &targ);
> +            ioctl(fioc->fd, TIOCMSET, &targ);
>          }
>          break;
>      default:
> @@ -1623,18 +1596,7 @@ static int tty_serial_ioctl(CharDriverState *chr, int 
> cmd, void *arg)
>  
>  static void qemu_chr_close_tty(CharDriverState *chr)
>  {
> -    FDCharDriver *s = chr->opaque;
> -    int fd = -1;
> -
> -    if (s) {
> -        fd = g_io_channel_unix_get_fd(s->fd_in);
> -    }
> -
>      fd_chr_close(chr);
> -
> -    if (fd >= 0) {
> -        close(fd);
> -    }
>  }
>  
>  static CharDriverState *qemu_chr_open_tty_fd(int fd,
> @@ -2456,8 +2418,7 @@ err1:
>  /* UDP Net console */
>  
>  typedef struct {
> -    int fd;
> -    GIOChannel *chan;
> +    QIOChannel *ioc;
>      uint8_t buf[READ_BUF_LEN];
>      int bufcnt;
>      int bufptr;
> @@ -2468,17 +2429,9 @@ typedef struct {
>  static int udp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
>  {
>      NetCharDriver *s = chr->opaque;
> -    gsize bytes_written;
> -    GIOStatus status;
>  
> -    status = g_io_channel_write_chars(s->chan, (const gchar *)buf, len, 
> &bytes_written, NULL);
> -    if (status == G_IO_STATUS_EOF) {
> -        return 0;
> -    } else if (status != G_IO_STATUS_NORMAL) {
> -        return -1;
> -    }
> -
> -    return bytes_written;
> +    return qio_channel_write(
> +        s->ioc, (const char *)buf, len, NULL);
>  }
>  
>  static int udp_chr_read_poll(void *opaque)
> @@ -2499,24 +2452,22 @@ static int udp_chr_read_poll(void *opaque)
>      return s->max_size;
>  }
>  
> -static gboolean udp_chr_read(GIOChannel *chan, GIOCondition cond, void 
> *opaque)
> +static gboolean udp_chr_read(QIOChannel *chan, GIOCondition cond, void 
> *opaque)
>  {
>      CharDriverState *chr = opaque;
>      NetCharDriver *s = chr->opaque;
> -    gsize bytes_read = 0;
> -    GIOStatus status;
> +    ssize_t ret;
>  
>      if (s->max_size == 0) {
>          return TRUE;
>      }
> -    status = g_io_channel_read_chars(s->chan, (gchar *)s->buf, 
> sizeof(s->buf),
> -                                     &bytes_read, NULL);
> -    s->bufcnt = bytes_read;
> -    s->bufptr = s->bufcnt;
> -    if (status != G_IO_STATUS_NORMAL) {
> +    ret = qio_channel_read(
> +        s->ioc, (char *)s->buf, sizeof(s->buf), NULL);
> +    if (ret <= 0) {
>          remove_fd_in_watch(chr);
>          return FALSE;
>      }
> +    s->bufcnt = ret;
>  
>      s->bufptr = 0;
>      while (s->max_size > 0 && s->bufptr < s->bufcnt) {
> @@ -2533,8 +2484,9 @@ static void udp_chr_update_read_handler(CharDriverState 
> *chr)
>      NetCharDriver *s = chr->opaque;
>  
>      remove_fd_in_watch(chr);
> -    if (s->chan) {
> -        chr->fd_in_tag = io_add_watch_poll(s->chan, udp_chr_read_poll,
> +    if (s->ioc) {
> +        chr->fd_in_tag = io_add_watch_poll(s->ioc,
> +                                           udp_chr_read_poll,
>                                             udp_chr_read, chr);
>      }
>  }
> @@ -2544,17 +2496,16 @@ static void udp_chr_close(CharDriverState *chr)
>      NetCharDriver *s = chr->opaque;
>  
>      remove_fd_in_watch(chr);
> -    if (s->chan) {
> -        g_io_channel_unref(s->chan);
> -        closesocket(s->fd);
> +    if (s->ioc) {
> +        object_unref(OBJECT(s->ioc));
>      }
>      g_free(s);
>      qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
>  }
>  
> -static CharDriverState *qemu_chr_open_udp_fd(int fd,
> -                                             ChardevCommon *backend,
> -                                             Error **errp)
> +static CharDriverState *qemu_chr_open_udp(QIOChannelSocket *sioc,
> +                                          ChardevCommon *backend,
> +                                          Error **errp)
>  {
>      CharDriverState *chr = NULL;
>      NetCharDriver *s = NULL;
> @@ -2565,8 +2516,7 @@ static CharDriverState *qemu_chr_open_udp_fd(int fd,
>      }
>      s = g_new0(NetCharDriver, 1);
>  
> -    s->fd = fd;
> -    s->chan = io_channel_from_socket(s->fd);
> +    s->ioc = QIO_CHANNEL(sioc);
>      s->bufcnt = 0;
>      s->bufptr = 0;
>      chr->opaque = s;
> @@ -2582,19 +2532,18 @@ static CharDriverState *qemu_chr_open_udp_fd(int fd,
>  /* TCP Net console */
>  
>  typedef struct {
> -
> -    GIOChannel *chan, *listen_chan;
> +    QIOChannel *ioc;
> +    QIOChannelSocket *listen_ioc;
>      guint listen_tag;
> -    int fd, listen_fd;
>      int connected;
>      int max_size;
>      int do_telnetopt;
>      int do_nodelay;
>      int is_unix;
>      int *read_msgfds;
> -    int read_msgfds_num;
> +    size_t read_msgfds_num;
>      int *write_msgfds;
> -    int write_msgfds_num;
> +    size_t write_msgfds_num;
>  
>      SocketAddress *addr;
>      bool is_listen;
> @@ -2628,68 +2577,27 @@ static void 
> check_report_connect_error(CharDriverState *chr,
>      qemu_chr_socket_restart_timer(chr);
>  }
>  
> -static gboolean tcp_chr_accept(GIOChannel *chan, GIOCondition cond, void 
> *opaque);
> -
> -#ifndef _WIN32
> -static int unix_send_msgfds(CharDriverState *chr, const uint8_t *buf, int 
> len)
> -{
> -    TCPCharDriver *s = chr->opaque;
> -    struct msghdr msgh;
> -    struct iovec iov;
> -    int r;
> -
> -    size_t fd_size = s->write_msgfds_num * sizeof(int);
> -    char control[CMSG_SPACE(fd_size)];
> -    struct cmsghdr *cmsg;
> -
> -    memset(&msgh, 0, sizeof(msgh));
> -    memset(control, 0, sizeof(control));
> -
> -    /* set the payload */
> -    iov.iov_base = (uint8_t *) buf;
> -    iov.iov_len = len;
> -
> -    msgh.msg_iov = &iov;
> -    msgh.msg_iovlen = 1;
> -
> -    msgh.msg_control = control;
> -    msgh.msg_controllen = sizeof(control);
> -
> -    cmsg = CMSG_FIRSTHDR(&msgh);
> -
> -    cmsg->cmsg_len = CMSG_LEN(fd_size);
> -    cmsg->cmsg_level = SOL_SOCKET;
> -    cmsg->cmsg_type = SCM_RIGHTS;
> -    memcpy(CMSG_DATA(cmsg), s->write_msgfds, fd_size);
> -
> -    do {
> -        r = sendmsg(s->fd, &msgh, 0);
> -    } while (r < 0 && errno == EINTR);
> -
> -    /* free the written msgfds, no matter what */
> -    if (s->write_msgfds_num) {
> -        g_free(s->write_msgfds);
> -        s->write_msgfds = 0;
> -        s->write_msgfds_num = 0;
> -    }
> -
> -    return r;
> -}
> -#endif
> +static gboolean tcp_chr_accept(QIOChannel *chan,
> +                               GIOCondition cond,
> +                               void *opaque);
>  
>  /* Called with chr_write_lock held.  */
>  static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
>  {
>      TCPCharDriver *s = chr->opaque;
>      if (s->connected) {
> -#ifndef _WIN32
> -        if (s->is_unix && s->write_msgfds_num) {
> -            return unix_send_msgfds(chr, buf, len);
> -        } else
> -#endif
> -        {
> -            return io_channel_send(s->chan, buf, len);
> +        int ret =  io_channel_send_full(s->ioc, buf, len,
> +                                        s->write_msgfds,
> +                                        s->write_msgfds_num);
> +
> +        /* free the written msgfds, no matter what */
> +        if (s->write_msgfds_num) {
> +            g_free(s->write_msgfds);
> +            s->write_msgfds = 0;
> +            s->write_msgfds_num = 0;
>          }
> +
> +        return ret;
>      } else {
>          /* XXX: indicate an error ? */
>          return len;
> @@ -2785,6 +2693,10 @@ static int tcp_set_msgfds(CharDriverState *chr, int 
> *fds, int num)
>  {
>      TCPCharDriver *s = chr->opaque;
>  
> +    if (!qio_channel_has_feature(s->ioc,
> +                                 QIO_CHANNEL_FEATURE_FD_PASS)) {
> +        return -1;
> +    }
>      /* clear old pending fd array */
>      g_free(s->write_msgfds);
>  
> @@ -2798,27 +2710,26 @@ static int tcp_set_msgfds(CharDriverState *chr, int 
> *fds, int num)
>      return 0;
>  }
>  
> -#ifndef _WIN32
> -static void unix_process_msgfd(CharDriverState *chr, struct msghdr *msg)
> +static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len)
>  {
>      TCPCharDriver *s = chr->opaque;
> -    struct cmsghdr *cmsg;
> -
> -    for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
> -        int fd_size, i;
> -
> -        if (cmsg->cmsg_len < CMSG_LEN(sizeof(int)) ||
> -            cmsg->cmsg_level != SOL_SOCKET ||
> -            cmsg->cmsg_type != SCM_RIGHTS) {
> -            continue;
> -        }
> -
> -        fd_size = cmsg->cmsg_len - CMSG_LEN(0);
> -
> -        if (!fd_size) {
> -            continue;
> -        }
> +    struct iovec iov = { .iov_base = buf, .iov_len = len };
> +    int ret;
> +    size_t i;
> +    int *msgfds = NULL;
> +    size_t msgfds_num = 0;
> +
> +    if (qio_channel_has_feature(s->ioc, QIO_CHANNEL_FEATURE_FD_PASS)) {
> +        ret = qio_channel_readv_full(s->ioc, &iov, 1,
> +                                     &msgfds, &msgfds_num,
> +                                     NULL);
> +    } else {
> +        ret = qio_channel_readv_full(s->ioc, &iov, 1,
> +                                     NULL, NULL,
> +                                     NULL);
> +    }
>  
> +    if (msgfds_num) {
>          /* close and clean read_msgfds */
>          for (i = 0; i < s->read_msgfds_num; i++) {
>              close(s->read_msgfds[i]);
> @@ -2828,77 +2739,31 @@ static void unix_process_msgfd(CharDriverState *chr, 
> struct msghdr *msg)
>              g_free(s->read_msgfds);
>          }
>  
> -        s->read_msgfds_num = fd_size / sizeof(int);
> -        s->read_msgfds = g_malloc(fd_size);
> -        memcpy(s->read_msgfds, CMSG_DATA(cmsg), fd_size);
> -
> -        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_set_block(fd);
> -
> -    #ifndef MSG_CMSG_CLOEXEC
> -            qemu_set_cloexec(fd);
> -    #endif
> -        }
> +        s->read_msgfds = msgfds;
> +        s->read_msgfds_num = msgfds_num;
>      }
> -}
>  
> -static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len)
> -{
> -    TCPCharDriver *s = chr->opaque;
> -    struct msghdr msg = { NULL, };
> -    struct iovec iov[1];
> -    union {
> -        struct cmsghdr cmsg;
> -        char control[CMSG_SPACE(sizeof(int) * TCP_MAX_FDS)];
> -    } msg_control;
> -    int flags = 0;
> -    ssize_t ret;
> -
> -    iov[0].iov_base = buf;
> -    iov[0].iov_len = len;
> +    for (i = 0; i < s->read_msgfds_num; i++) {
> +        int fd = s->read_msgfds[i];
> +        if (fd < 0) {
> +            continue;
> +        }
>  
> -    msg.msg_iov = iov;
> -    msg.msg_iovlen = 1;
> -    msg.msg_control = &msg_control;
> -    msg.msg_controllen = sizeof(msg_control);
> +        /* O_NONBLOCK is preserved across SCM_RIGHTS so reset it */
> +        qemu_set_block(fd);
>  
> -#ifdef MSG_CMSG_CLOEXEC
> -    flags |= MSG_CMSG_CLOEXEC;
> +#ifndef MSG_CMSG_CLOEXEC
> +        qemu_set_cloexec(fd);
>  #endif
> -    do {
> -        ret = recvmsg(s->fd, &msg, flags);
> -    } while (ret == -1 && errno == EINTR);
> -
> -    if (ret > 0 && s->is_unix) {
> -        unix_process_msgfd(chr, &msg);
>      }
>  
>      return ret;
>  }
> -#else
> -static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len)
> -{
> -    TCPCharDriver *s = chr->opaque;
> -    ssize_t ret;
> -
> -    do {
> -        ret = qemu_recv(s->fd, buf, len, 0);
> -    } while (ret == -1 && socket_error() == EINTR);
> -
> -    return ret;
> -}
> -#endif
>  
>  static GSource *tcp_chr_add_watch(CharDriverState *chr, GIOCondition cond)
>  {
>      TCPCharDriver *s = chr->opaque;
> -    return g_io_create_watch(s->chan, cond);
> +    return qio_channel_create_watch(s->ioc, cond);
>  }
>  
>  static void tcp_chr_disconnect(CharDriverState *chr)
> @@ -2906,15 +2771,13 @@ static void tcp_chr_disconnect(CharDriverState *chr)
>      TCPCharDriver *s = chr->opaque;
>  
>      s->connected = 0;
> -    if (s->listen_chan) {
> -        s->listen_tag = g_io_add_watch(s->listen_chan, G_IO_IN,
> -                                       tcp_chr_accept, chr);
> +    if (s->listen_ioc) {
> +        s->listen_tag = qio_channel_add_watch(
> +            QIO_CHANNEL(s->listen_ioc), G_IO_IN, tcp_chr_accept, chr, NULL);
>      }
>      remove_fd_in_watch(chr);
> -    g_io_channel_unref(s->chan);
> -    s->chan = NULL;
> -    closesocket(s->fd);
> -    s->fd = -1;
> +    object_unref(OBJECT(s->ioc));
> +    s->ioc = NULL;
>      g_free(chr->filename);
>      chr->filename = SocketAddress_to_str("disconnected:", s->addr,
>                                           s->is_listen, s->is_telnet);
> @@ -2924,7 +2787,7 @@ static void tcp_chr_disconnect(CharDriverState *chr)
>      }
>  }
>  
> -static gboolean tcp_chr_read(GIOChannel *chan, GIOCondition cond, void 
> *opaque)
> +static gboolean tcp_chr_read(QIOChannel *chan, GIOCondition cond, void 
> *opaque)
>  {
>      CharDriverState *chr = opaque;
>      TCPCharDriver *s = chr->opaque;
> @@ -2938,9 +2801,7 @@ static gboolean tcp_chr_read(GIOChannel *chan, 
> GIOCondition cond, void *opaque)
>      if (len > s->max_size)
>          len = s->max_size;
>      size = tcp_chr_recv(chr, (void *)buf, len);
> -    if (size == 0 ||
> -        (size < 0 &&
> -         socket_error() != EAGAIN && socket_error() != EWOULDBLOCK)) {
> +    if (size == 0 || size == -1) {
>          /* connection closed */
>          tcp_chr_disconnect(chr);
>      } else if (size > 0) {
> @@ -2988,25 +2849,17 @@ static void tcp_chr_connect(void *opaque)
>  {
>      CharDriverState *chr = opaque;
>      TCPCharDriver *s = chr->opaque;
> -    struct sockaddr_storage ss, ps;
> -    socklen_t ss_len = sizeof(ss), ps_len = sizeof(ps);
> +    QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(s->ioc);
>  
> -    memset(&ss, 0, ss_len);
>      g_free(chr->filename);
> -    if (getsockname(s->fd, (struct sockaddr *) &ss, &ss_len) != 0) {
> -        chr->filename = g_strdup_printf("Error in getsockname: %s\n",
> -                                        strerror(errno));
> -    } else if (getpeername(s->fd, (struct sockaddr *) &ps, &ps_len) != 0) {
> -        chr->filename = g_strdup_printf("Error in getpeername: %s\n",
> -                                        strerror(errno));
> -    } else {
> -        chr->filename = sockaddr_to_str(&ss, ss_len, &ps, ps_len,
> -                                        s->is_listen, s->is_telnet);
> -    }
> +    chr->filename = sockaddr_to_str(&sioc->localAddr, sioc->localAddrLen,
> +                                    &sioc->remoteAddr, sioc->remoteAddrLen,
> +                                    s->is_listen, s->is_telnet);
>  
>      s->connected = 1;
> -    if (s->chan) {
> -        chr->fd_in_tag = io_add_watch_poll(s->chan, tcp_chr_read_poll,
> +    if (s->ioc) {
> +        chr->fd_in_tag = io_add_watch_poll(s->ioc,
> +                                           tcp_chr_read_poll,
>                                             tcp_chr_read, chr);
>      }
>      qemu_chr_be_generic_open(chr);
> @@ -3017,38 +2870,41 @@ static void 
> tcp_chr_update_read_handler(CharDriverState *chr)
>      TCPCharDriver *s = chr->opaque;
>  
>      remove_fd_in_watch(chr);
> -    if (s->chan) {
> -        chr->fd_in_tag = io_add_watch_poll(s->chan, tcp_chr_read_poll,
> +    if (s->ioc) {
> +        chr->fd_in_tag = io_add_watch_poll(s->ioc,
> +                                           tcp_chr_read_poll,
>                                             tcp_chr_read, chr);
>      }
>  }
>  
>  #define IACSET(x,a,b,c) x[0] = a; x[1] = b; x[2] = c;
> -static void tcp_chr_telnet_init(int fd)
> +static void tcp_chr_telnet_init(QIOChannel *ioc)
>  {
>      char buf[3];
>      /* Send the telnet negotion to put telnet in binary, no echo, single 
> char mode */
>      IACSET(buf, 0xff, 0xfb, 0x01);  /* IAC WILL ECHO */
> -    send(fd, (char *)buf, 3, 0);
> +    qio_channel_write(ioc, buf, 3, NULL);
>      IACSET(buf, 0xff, 0xfb, 0x03);  /* IAC WILL Suppress go ahead */
> -    send(fd, (char *)buf, 3, 0);
> +    qio_channel_write(ioc, buf, 3, NULL);
>      IACSET(buf, 0xff, 0xfb, 0x00);  /* IAC WILL Binary */
> -    send(fd, (char *)buf, 3, 0);
> +    qio_channel_write(ioc, buf, 3, NULL);
>      IACSET(buf, 0xff, 0xfd, 0x00);  /* IAC DO Binary */
> -    send(fd, (char *)buf, 3, 0);
> +    qio_channel_write(ioc, buf, 3, NULL);
>  }
>  
> -static int tcp_chr_add_client(CharDriverState *chr, int fd)
> +static int tcp_chr_new_client(CharDriverState *chr, QIOChannelSocket *sioc)
>  {
>      TCPCharDriver *s = chr->opaque;
> -    if (s->fd != -1)
> +    if (s->ioc != NULL) {
>       return -1;
> +    }
>  
> -    qemu_set_nonblock(fd);
> -    if (s->do_nodelay)
> -        socket_set_nodelay(fd);
> -    s->fd = fd;
> -    s->chan = io_channel_from_socket(fd);
> +    s->ioc = QIO_CHANNEL(sioc);
> +    object_ref(OBJECT(sioc));
> +
> +    if (s->do_nodelay) {
> +        qio_channel_set_delay(s->ioc, false);
> +    }
>      if (s->listen_tag) {
>          g_source_remove(s->listen_tag);
>          s->listen_tag = 0;
> @@ -3058,41 +2914,43 @@ static int tcp_chr_add_client(CharDriverState *chr, 
> int fd)
>      return 0;
>  }
>  
> -static gboolean tcp_chr_accept(GIOChannel *channel, GIOCondition cond, void 
> *opaque)
> +
> +static int tcp_chr_add_client(CharDriverState *chr, int fd)
> +{
> +    int ret;
> +    QIOChannelSocket *sioc;
> +
> +    sioc = qio_channel_socket_new_fd(fd, NULL);
> +    if (!sioc) {
> +        return -1;
> +    }
> +    qio_channel_set_blocking(QIO_CHANNEL(sioc), false, NULL);
> +    ret = tcp_chr_new_client(chr, sioc);
> +    object_unref(OBJECT(sioc));
> +    return ret;
> +}
> +
> +static gboolean tcp_chr_accept(QIOChannel *channel,
> +                               GIOCondition cond,
> +                               void *opaque)
>  {
>      CharDriverState *chr = opaque;
>      TCPCharDriver *s = chr->opaque;
> -    struct sockaddr_in saddr;
> -#ifndef _WIN32
> -    struct sockaddr_un uaddr;
> -#endif
> -    struct sockaddr *addr;
> -    socklen_t len;
> -    int fd;
> +    QIOChannelSocket *sioc;
>  
> -    for(;;) {
> -#ifndef _WIN32
> -     if (s->is_unix) {
> -         len = sizeof(uaddr);
> -         addr = (struct sockaddr *)&uaddr;
> -     } else
> -#endif
> -     {
> -         len = sizeof(saddr);
> -         addr = (struct sockaddr *)&saddr;
> -     }
> -        fd = qemu_accept(s->listen_fd, addr, &len);
> -        if (fd < 0 && errno != EINTR) {
> -            s->listen_tag = 0;
> -            return FALSE;
> -        } else if (fd >= 0) {
> -            if (s->do_telnetopt)
> -                tcp_chr_telnet_init(fd);
> -            break;
> -        }
> +    sioc = qio_channel_socket_accept(QIO_CHANNEL_SOCKET(channel),
> +                                     NULL);
> +    if (!sioc) {
> +        return TRUE;
>      }
> -    if (tcp_chr_add_client(chr, fd) < 0)
> -     close(fd);
> +
> +    if (s->do_telnetopt) {
> +        tcp_chr_telnet_init(QIO_CHANNEL(sioc));
> +    }
> +
> +    tcp_chr_new_client(chr, sioc);
> +
> +    object_unref(OBJECT(sioc));
>  
>      return TRUE;
>  }
> @@ -3107,22 +2965,16 @@ static void tcp_chr_close(CharDriverState *chr)
>          s->reconnect_timer = 0;
>      }
>      qapi_free_SocketAddress(s->addr);
> -    if (s->fd >= 0) {
> -        remove_fd_in_watch(chr);
> -        if (s->chan) {
> -            g_io_channel_unref(s->chan);
> -        }
> -        closesocket(s->fd);
> +    remove_fd_in_watch(chr);
> +    if (s->ioc) {
> +        object_unref(OBJECT(s->ioc));
>      }
> -    if (s->listen_fd >= 0) {
> -        if (s->listen_tag) {
> -            g_source_remove(s->listen_tag);
> -            s->listen_tag = 0;
> -        }
> -        if (s->listen_chan) {
> -            g_io_channel_unref(s->listen_chan);
> -        }
> -        closesocket(s->listen_fd);
> +    if (s->listen_tag) {
> +        g_source_remove(s->listen_tag);
> +        s->listen_tag = 0;
> +    }
> +    if (s->listen_ioc) {
> +        object_unref(OBJECT(s->listen_ioc));
>      }
>      if (s->read_msgfds_num) {
>          for (i = 0; i < s->read_msgfds_num; i++) {
> @@ -3137,57 +2989,63 @@ static void tcp_chr_close(CharDriverState *chr)
>      qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
>  }
>  
> -static void qemu_chr_finish_socket_connection(CharDriverState *chr, int fd)
> +static void qemu_chr_finish_socket_connection(CharDriverState *chr,
> +                                              QIOChannelSocket *sioc)
>  {
>      TCPCharDriver *s = chr->opaque;
>  
>      if (s->is_listen) {
> -        s->listen_fd = fd;
> -        s->listen_chan = io_channel_from_socket(s->listen_fd);
> -        s->listen_tag = g_io_add_watch(s->listen_chan, G_IO_IN,
> -                                       tcp_chr_accept, chr);
> +        s->listen_ioc = sioc;
> +        s->listen_tag = qio_channel_add_watch(
> +            QIO_CHANNEL(s->listen_ioc), G_IO_IN, tcp_chr_accept, chr, NULL);
>      } else {
> -        s->connected = 1;
> -        s->fd = fd;
> -        socket_set_nodelay(fd);
> -        s->chan = io_channel_from_socket(s->fd);
> -        tcp_chr_connect(chr);
> +        tcp_chr_new_client(chr, sioc);
> +        object_unref(OBJECT(sioc));
>      }
>  }
>  
> -static void qemu_chr_socket_connected(int fd, Error *err, void *opaque)
> +static void qemu_chr_socket_connected(Object *src, Error *err, void *opaque)
>  {
> +    QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(src);
>      CharDriverState *chr = opaque;
>      TCPCharDriver *s = chr->opaque;
>  
> -    if (fd < 0) {
> +    if (err) {
>          check_report_connect_error(chr, err);
> +        object_unref(src);
>          return;
>      }
>  
>      s->connect_err_reported = false;
> -    qemu_chr_finish_socket_connection(chr, fd);
> +    qemu_chr_finish_socket_connection(chr, sioc);
>  }
>  
>  static bool qemu_chr_open_socket_fd(CharDriverState *chr, Error **errp)
>  {
>      TCPCharDriver *s = chr->opaque;
> -    int fd;
> +    QIOChannelSocket *sioc = qio_channel_socket_new();
>  
>      if (s->is_listen) {
> -        fd = socket_listen(s->addr, errp);
> +        if (qio_channel_socket_listen_sync(sioc, s->addr, errp) < 0) {
> +            goto fail;
> +        }
> +        qemu_chr_finish_socket_connection(chr, sioc);
>      } else if (s->reconnect_time) {
> -        fd = socket_connect(s->addr, errp, qemu_chr_socket_connected, chr);
> -        return fd >= 0;
> +        qio_channel_socket_connect_async(sioc, s->addr,
> +                                         qemu_chr_socket_connected,
> +                                         chr, NULL);
>      } else {
> -        fd = socket_connect(s->addr, errp, NULL, NULL);
> -    }
> -    if (fd < 0) {
> -        return false;
> +        if (qio_channel_socket_connect_sync(sioc, s->addr, errp) < 0) {
> +            goto fail;
> +        }
> +        qemu_chr_finish_socket_connection(chr, sioc);
>      }
>  
> -    qemu_chr_finish_socket_connection(chr, fd);
>      return true;
> +
> + fail:
> +    object_unref(OBJECT(sioc));
> +    return false;
>  }
>  
>  /*********************************************************/
> @@ -4318,8 +4176,6 @@ static CharDriverState *qmp_chardev_open_socket(const 
> char *id,
>      }
>      s = g_new0(TCPCharDriver, 1);
>  
> -    s->fd = -1;
> -    s->listen_fd = -1;
>      s->is_unix = addr->type == SOCKET_ADDRESS_KIND_UNIX;
>      s->is_listen = is_listen;
>      s->is_telnet = is_telnet;
> @@ -4360,8 +4216,8 @@ static CharDriverState *qmp_chardev_open_socket(const 
> char *id,
>      if (is_listen && is_waitconnect) {
>          fprintf(stderr, "QEMU waiting for connection on: %s\n",
>                  chr->filename);
> -        tcp_chr_accept(s->listen_chan, G_IO_IN, chr);
> -        qemu_set_nonblock(s->listen_fd);
> +        tcp_chr_accept(QIO_CHANNEL(s->listen_ioc), G_IO_IN, chr);
> +        qio_channel_set_blocking(QIO_CHANNEL(s->listen_ioc), false, NULL);
>      }
>  
>      return chr;
> @@ -4374,13 +4230,15 @@ static CharDriverState *qmp_chardev_open_udp(const 
> char *id,
>  {
>      ChardevUdp *udp = backend->u.udp;
>      ChardevCommon *common = qapi_ChardevUdp_base(backend->u.udp);
> -    int fd;
> +    QIOChannelSocket *sioc = qio_channel_socket_new();
>  
> -    fd = socket_dgram(udp->remote, udp->local, errp);
> -    if (fd < 0) {
> +    if (qio_channel_socket_dgram_sync(sioc,
> +                                      udp->remote, udp->local,
> +                                      errp) < 0) {
> +        object_unref(OBJECT(sioc));
>          return NULL;
>      }
> -    return qemu_chr_open_udp_fd(fd, common, errp);
> +    return qemu_chr_open_udp(sioc, common, errp);
>  }
>  
>  ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
> diff --git a/tests/Makefile b/tests/Makefile
> index b7352f1..650e654 100644
> --- a/tests/Makefile
> +++ b/tests/Makefile
> @@ -558,7 +558,7 @@ tests/usb-hcd-uhci-test$(EXESUF): 
> tests/usb-hcd-uhci-test.o $(libqos-usb-obj-y)
>  tests/usb-hcd-ehci-test$(EXESUF): tests/usb-hcd-ehci-test.o 
> $(libqos-usb-obj-y)
>  tests/usb-hcd-xhci-test$(EXESUF): tests/usb-hcd-xhci-test.o 
> $(libqos-usb-obj-y)
>  tests/pc-cpu-test$(EXESUF): tests/pc-cpu-test.o
> -tests/vhost-user-test$(EXESUF): tests/vhost-user-test.o qemu-char.o 
> qemu-timer.o $(qtest-obj-y)
> +tests/vhost-user-test$(EXESUF): tests/vhost-user-test.o qemu-char.o 
> qemu-timer.o $(qtest-obj-y) $(test-io-obj-y)
>  tests/qemu-iotests/socket_scm_helper$(EXESUF): 
> tests/qemu-iotests/socket_scm_helper.o
>  tests/test-qemu-opts$(EXESUF): tests/test-qemu-opts.o $(test-util-obj-y)
>  tests/test-write-threshold$(EXESUF): tests/test-write-threshold.o 
> $(test-block-obj-y)
> 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]