On Wed, Dec 17, 2025 at 10:30 AM Angus Chen <[email protected]> wrote:
>

It looks like the title is too long.

> However, the error handling logic was flawed:
>
> 1. Read Failure (err <= 0): The TX VQ completion
>    (vdpasim_net_complete(txq, 0)) was performed, but the unconditional
>    break that followed prevented theprocessing of subsequent pending work
>    items (other descriptors) in the queue in the same work function call.
>
> 2. Write Failure (write <= 0): If data could not be written to the RX VQ
>    descriptor (e.g., vringh_iov_push_iotlb failed), the flow would 'break'
>    before the TX VQ descriptor was completed. This led to a leak of TX VQ
>    descriptors, as the work was never notified that the TX buffer was
>    free to use again.
>
> This commit refactors the control flow to ensure:
> a) The TX VQ descriptor is completed back to the rx in all error and
>    success paths related to the current descriptor processing.
> b) The unconditional break on read failure is removed, allowing the
>    function to continue processing remaining work items
>    until the loop naturally exits.
>
> Fixes: 0899774cb360 ("vdpa_sim_net: vendor satistics")

This is suspicious, the logic was there since introduced? Or we can
split this patch

1) fix the stats
2) fix the error handling

> ---
>
> Signed-off-by: Angus Chen <[email protected]>
> ---
>  drivers/vdpa/vdpa_sim/vdpa_sim_net.c | 28 ++++++++++++++--------------
>  1 file changed, 14 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim_net.c 
> b/drivers/vdpa/vdpa_sim/vdpa_sim_net.c
> index 6caf09a1907b..298bd6e8e0a0 100644
> --- a/drivers/vdpa/vdpa_sim/vdpa_sim_net.c
> +++ b/drivers/vdpa/vdpa_sim/vdpa_sim_net.c
> @@ -242,22 +242,22 @@ static void vdpasim_net_work(struct vdpasim *vdpasim)
>                 if (err <= 0) {
>                         ++rx_overruns;
>                         vdpasim_net_complete(txq, 0);
> -                       break;
> -               }
> -
> -               write = vringh_iov_push_iotlb(&rxq->vring, &rxq->in_iov,
> -                                             net->buffer, read);
> -               if (write <= 0) {
> -                       ++rx_errors;
> -                       break;
> +               } else {

This else seem useless?

> +
> +                       write = vringh_iov_push_iotlb(&rxq->vring, 
> &rxq->in_iov,
> +                                                     net->buffer, read);
> +                       if (write <= 0) {
> +                               ++rx_errors;
> +                               vdpasim_net_complete(txq, 0);

I'd move this after:

                read = vringh_iov_pull_iotlb(&txq->vring, &txq->out_iov,
                                             net->buffer, PAGE_SIZE);

So we would have a single vdpasim_net_complete()

> +                               break;
> +                       }
> +
> +                       ++rx_pkts;
> +                       rx_bytes += write;
> +                       vdpasim_net_complete(txq, 0);
> +                       vdpasim_net_complete(rxq, write);
>                 }
>
> -               ++rx_pkts;
> -               rx_bytes += write;
> -
> -               vdpasim_net_complete(txq, 0);
> -               vdpasim_net_complete(rxq, write);
> -
>                 if (tx_pkts > 4) {
>                         vdpasim_schedule_work(vdpasim);
>                         goto out;
> --
> 2.34.1
>

Thanks


Reply via email to