[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