On Wed, Jun 17, 2026 at 02:43:31PM +0800, Bin Guo wrote: > QIOChannelRDMA's readv already blocks inside qemu_rdma_exchange_recv() > when waiting for the next RDMA SEND message. What it did not do was > keep blocking when the bytes from a single receive were insufficient > to satisfy the full request -- it returned partial data (or EAGAIN) > instead of waiting for more.
Sorry if I wasn't clear when commenting, but what I meant is, this is correct behavior for blocking/nonblocking. If io_readv() reads partial, IIUC returning how much it reads is the correct behavior. You can refer to qio_channel_socket_readv(). Here, RDMA doesn't respect blocking is because it _always_ blocks. That is, qemu_rdma_exchange_recv() always will block even if blocking=false. I believe it will normally stop working when it's used in a coroutine, because normally we rely on non-blocking to allow it fallback to caller then things like qio_channel_wait_cond() will yield if it's coroutine. I recall RDMA still works only because it has some internal hack to yield, maybe that's qemu_rdma_wait_comp_channel(), but I really don't know RDMA well, at least so far.. maybe I should try to improve at some point. Before that, it would be good Zhijian can have another look on this. Let me loop in Dan too. Thanks, > > Loop on qemu_rdma_exchange_recv() when the channel is blocking and > the receive buffer cannot satisfy the request. This matches the > behaviour of other QIOChannel implementations, which block until > the full request is satisfied (or an error occurs). > > Also remove the stale XXX comments about unimplemented blocking support. > > Reviewed-by: Li Zhijian <[email protected]> > Signed-off-by: Bin Guo <[email protected]> > --- > migration/rdma.c | 46 +++++++++++++++++++++------------------------- > 1 file changed, 21 insertions(+), 25 deletions(-) > > diff --git a/migration/rdma.c b/migration/rdma.c > index 3e37a1d440..201cb9eb12 100644 > --- a/migration/rdma.c > +++ b/migration/rdma.c > @@ -388,7 +388,7 @@ struct QIOChannelRDMA { > QIOChannel parent; > RDMAContext *rdmain; > RDMAContext *rdmaout; > - bool blocking; /* XXX we don't actually honour this yet */ > + bool blocking; > }; > > /* > @@ -2710,32 +2710,29 @@ static ssize_t qio_channel_rdma_readv(QIOChannel *ioc, > break; > } > > - > - /* We've got nothing at all, so lets wait for > - * more to arrive > - */ > - ret = qemu_rdma_exchange_recv(rdma, &head, RDMA_CONTROL_QEMU_FILE, > - errp); > - > - if (ret < 0) { > - rdma->errored = true; > - return -1; > - } > - > /* > - * SEND was received with new bytes, now try again. > + * We've got nothing at all, so lets wait for > + * more to arrive. > */ > - len = qemu_rdma_fill(rdma, data, want, 0); > - done += len; > - want -= len; > - > - /* Still didn't get enough, so lets just return */ > - if (want) { > - if (done == 0) { > - return QIO_CHANNEL_ERR_BLOCK; > - } else { > - break; > + do { > + ret = qemu_rdma_exchange_recv(rdma, &head, > + RDMA_CONTROL_QEMU_FILE, errp); > + if (ret < 0) { > + rdma->errored = true; > + return -1; > } > + > + /* > + * SEND was received with new bytes, now try again. > + */ > + len = qemu_rdma_fill(rdma, data, want, 0); > + done += len; > + want -= len; > + data += len; > + } while (want && rioc->blocking); > + > + if (want && done == 0) { > + return QIO_CHANNEL_ERR_BLOCK; > } > } > return done; > @@ -2771,7 +2768,6 @@ static int qio_channel_rdma_set_blocking(QIOChannel > *ioc, > Error **errp) > { > QIOChannelRDMA *rioc = QIO_CHANNEL_RDMA(ioc); > - /* XXX we should make readv/writev actually honour this :-) */ > rioc->blocking = blocking; > return 0; > } > -- > 2.50.1 (Apple Git-155) > -- Peter Xu
