[PATCH] vmbus: fix lockup if ring fills up

KY Srinivasan kys at microsoft.com
Mon Nov 7 20:08:05 UTC 2016



> -----Original Message-----
> From: Stephen Hemminger [mailto:stephen at networkplumber.org]
> Sent: Monday, November 7, 2016 8:50 AM
> To: Haiyang Zhang <haiyangz at microsoft.com>; KY Srinivasan
> <kys at microsoft.com>
> Cc: devel at linuxdriverproject.org; devel at linuxdriverproject.org
> Subject: [PATCH] vmbus: fix lockup if ring fills up
> 
> From: Stephen Hemminger <sthemmin at microsoft.com
> 
> This fixes a day one bug in circular ring buffer.  The ring buffer
> will get stuck if the number of bytes written exactly fills the
> ring buffer size.  The root cause is an off by one bug.
> 
> Ring empty state is when read_index == write_loc.
> The very last slot in the circular buffer must never be filled
> otherwise there is no way to tell the difference between completely
> full and empty!

Stephen,

I maybe missing something; but we do have code to prevent this very situation.
all ring buffer writes are done via this API: hv_ringbuffer_write() and the first thing
we do here is to check the very condition you bring up here:

        /*
         * If there is only room for the packet, assume it is full.
         * Otherwise, the next time around, we think the ring buffer
         * is empty since the read index == write index.
         */
        if (bytes_avail_towrite <= totalbytes_towrite) {
                if (lock)
                        spin_unlock_irqrestore(&outring_info->ring_lock, flags);
                return -EAGAIN;
        }

Regards,

K. Y

> 
> Signed-off-by: Stephen Hemminger <stephen at networkplumber.org>
> ---
> Please queue for stable as well
> 
>  include/linux/hyperv.h | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
> index cd184bd..28f88de 100644
> --- a/include/linux/hyperv.h
> +++ b/include/linux/hyperv.h
> @@ -150,6 +150,7 @@ hv_get_ringbuffer_availbytes(struct
> hv_ring_buffer_info *rbi,
> 
>  	*write = write_loc >= read_loc ? dsize - (write_loc - read_loc) :
>  		read_loc - write_loc;
> +	*write -= 1;
>  	*read = dsize - *write;
>  }
> 
> @@ -177,7 +178,8 @@ static inline u32 hv_get_bytes_to_write(struct
> hv_ring_buffer_info *rbi)
> 
>  	write = write_loc >= read_loc ? dsize - (write_loc - read_loc) :
>  		read_loc - write_loc;
> -	return write;
> +	/* make sure ring never gets completely full */
> +	return write - 1;
>  }
> 
>  /*
> --
> 2.7.4



More information about the devel mailing list