|
@@ -1492,23 +1492,31 @@ static inline struct vmpacket_descriptor *
|
|
get_next_pkt_raw(struct vmbus_channel *channel)
|
|
get_next_pkt_raw(struct vmbus_channel *channel)
|
|
{
|
|
{
|
|
struct hv_ring_buffer_info *ring_info = &channel->inbound;
|
|
struct hv_ring_buffer_info *ring_info = &channel->inbound;
|
|
- u32 priv_read_loc = ring_info->priv_read_index;
|
|
|
|
|
|
+ u32 read_loc = ring_info->priv_read_index;
|
|
void *ring_buffer = hv_get_ring_buffer(ring_info);
|
|
void *ring_buffer = hv_get_ring_buffer(ring_info);
|
|
|
|
+ struct vmpacket_descriptor *cur_desc;
|
|
|
|
+ u32 packetlen;
|
|
u32 dsize = ring_info->ring_datasize;
|
|
u32 dsize = ring_info->ring_datasize;
|
|
- /*
|
|
|
|
- * delta is the difference between what is available to read and
|
|
|
|
- * what was already consumed in place. We commit read index after
|
|
|
|
- * the whole batch is processed.
|
|
|
|
- */
|
|
|
|
- u32 delta = priv_read_loc >= ring_info->ring_buffer->read_index ?
|
|
|
|
- priv_read_loc - ring_info->ring_buffer->read_index :
|
|
|
|
- (dsize - ring_info->ring_buffer->read_index) + priv_read_loc;
|
|
|
|
|
|
+ u32 delta = read_loc - ring_info->ring_buffer->read_index;
|
|
u32 bytes_avail_toread = (hv_get_bytes_to_read(ring_info) - delta);
|
|
u32 bytes_avail_toread = (hv_get_bytes_to_read(ring_info) - delta);
|
|
|
|
|
|
if (bytes_avail_toread < sizeof(struct vmpacket_descriptor))
|
|
if (bytes_avail_toread < sizeof(struct vmpacket_descriptor))
|
|
return NULL;
|
|
return NULL;
|
|
|
|
|
|
- return ring_buffer + priv_read_loc;
|
|
|
|
|
|
+ if ((read_loc + sizeof(*cur_desc)) > dsize)
|
|
|
|
+ return NULL;
|
|
|
|
+
|
|
|
|
+ cur_desc = ring_buffer + read_loc;
|
|
|
|
+ packetlen = cur_desc->len8 << 3;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * If the packet under consideration is wrapping around,
|
|
|
|
+ * return failure.
|
|
|
|
+ */
|
|
|
|
+ if ((read_loc + packetlen + VMBUS_PKT_TRAILER) > (dsize - 1))
|
|
|
|
+ return NULL;
|
|
|
|
+
|
|
|
|
+ return cur_desc;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -1520,14 +1528,16 @@ static inline void put_pkt_raw(struct vmbus_channel *channel,
|
|
struct vmpacket_descriptor *desc)
|
|
struct vmpacket_descriptor *desc)
|
|
{
|
|
{
|
|
struct hv_ring_buffer_info *ring_info = &channel->inbound;
|
|
struct hv_ring_buffer_info *ring_info = &channel->inbound;
|
|
|
|
+ u32 read_loc = ring_info->priv_read_index;
|
|
u32 packetlen = desc->len8 << 3;
|
|
u32 packetlen = desc->len8 << 3;
|
|
u32 dsize = ring_info->ring_datasize;
|
|
u32 dsize = ring_info->ring_datasize;
|
|
|
|
|
|
|
|
+ if ((read_loc + packetlen + VMBUS_PKT_TRAILER) > dsize)
|
|
|
|
+ BUG();
|
|
/*
|
|
/*
|
|
* Include the packet trailer.
|
|
* Include the packet trailer.
|
|
*/
|
|
*/
|
|
ring_info->priv_read_index += packetlen + VMBUS_PKT_TRAILER;
|
|
ring_info->priv_read_index += packetlen + VMBUS_PKT_TRAILER;
|
|
- ring_info->priv_read_index %= dsize;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|