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


Reply via email to