Three bug fixes for different parts of the hyper-v code:
- Fix for a lockup when changing NIC's MTU from Dexuan. - Fix of use of uninitialized memory from Dexuan. - Fix for memory corruption caused by ballooning from Vitaly. All 3 were tested internally. -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEE4n5dijQDou9mhzu83qZv95d3LNwFAlw3YrYACgkQ3qZv95d3 LNyNfQ//eRbs8VloBom7NGKMnUQpbouwX+CkOvZMWsNq4/E52weehAC9Vpxa8KLS ulCfF3gwt44i50r00FuiZwzZtmMj/7I6YuCkqevZTrASPlbREMUpegGAsKvHedjq 1EeairWJq1/1tukXrVyTDpikN0wlE61dVNy6qGs5JBCpc5eT8l9gFH7kjOGLzgIt +/u/dTSS7x9ZX+VWn9F00JPHWzw9+rcI5aim1OKfKzkJ2JuDrjuXFz3iIJTwAKVL 4X2+H6s4XaTI47AMmIPcn+iAbELqA63RtUZhDHQoJxwCwZXy08TSNUB0IgVjylN+ aSJE4yKekhGOQrn9yaCFBJ6UudBbSGJbpU7uORG7XEHbIar5BWAsjDseFd1cUmgA 7nfPgDw+j1ttvR5mmB5DUyq5/8Mfo1vFo6l5sXNMoiaGzmHCqJ7EzdM5j/cP5pPO SP58fVPU5UXGjrr1Wyjr18noqeheRpj9wOLsYkFMqyktsxcdx8kd5UFGKUM3Y/xi 9RYDPrEDIlaLXNZxFR3kmDqCa+JowTmhqNQPxanTjtEijtq/caW9V3aovR+KL4v1 toug3GtC0xSyKBZFG6CzDUJz22W6d8VK4XxhD6i+2JFQHXWn0x26kLUKBK5Pbl0L 8FsDFVEGlgpuq5L5TgcUlgg6zKvwrZm9RiEhtefns825yVF+P54= =zd27 -----END PGP SIGNATURE----- Merge tag 'hyperv-fixes-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux into char-misc-linus Sasha writes: Three bug fixes for different parts of the hyper-v code: - Fix for a lockup when changing NIC's MTU from Dexuan. - Fix of use of uninitialized memory from Dexuan. - Fix for memory corruption caused by ballooning from Vitaly. All 3 were tested internally. * tag 'hyperv-fixes-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux: vmbus: fix subchannel removal hv_balloon: avoid touching uninitialized struct page during tail onlining Drivers: hv: vmbus: Check for ring when getting debug info
This commit is contained in:
commit
411aba3c12
@ -701,19 +701,12 @@ static int vmbus_close_internal(struct vmbus_channel *channel)
|
||||
int vmbus_disconnect_ring(struct vmbus_channel *channel)
|
||||
{
|
||||
struct vmbus_channel *cur_channel, *tmp;
|
||||
unsigned long flags;
|
||||
LIST_HEAD(list);
|
||||
int ret;
|
||||
|
||||
if (channel->primary_channel != NULL)
|
||||
return -EINVAL;
|
||||
|
||||
/* Snapshot the list of subchannels */
|
||||
spin_lock_irqsave(&channel->lock, flags);
|
||||
list_splice_init(&channel->sc_list, &list);
|
||||
spin_unlock_irqrestore(&channel->lock, flags);
|
||||
|
||||
list_for_each_entry_safe(cur_channel, tmp, &list, sc_list) {
|
||||
list_for_each_entry_safe(cur_channel, tmp, &channel->sc_list, sc_list) {
|
||||
if (cur_channel->rescind)
|
||||
wait_for_completion(&cur_channel->rescind_event);
|
||||
|
||||
|
@ -888,12 +888,14 @@ static unsigned long handle_pg_range(unsigned long pg_start,
|
||||
pfn_cnt -= pgs_ol;
|
||||
/*
|
||||
* Check if the corresponding memory block is already
|
||||
* online by checking its last previously backed page.
|
||||
* In case it is we need to bring rest (which was not
|
||||
* backed previously) online too.
|
||||
* online. It is possible to observe struct pages still
|
||||
* being uninitialized here so check section instead.
|
||||
* In case the section is online we need to bring the
|
||||
* rest of pfns (which were not backed previously)
|
||||
* online too.
|
||||
*/
|
||||
if (start_pfn > has->start_pfn &&
|
||||
!PageReserved(pfn_to_page(start_pfn - 1)))
|
||||
online_section_nr(pfn_to_section_nr(start_pfn)))
|
||||
hv_bring_pgs_online(has, start_pfn, pgs_ol);
|
||||
|
||||
}
|
||||
|
@ -164,26 +164,25 @@ hv_get_ringbuffer_availbytes(const struct hv_ring_buffer_info *rbi,
|
||||
}
|
||||
|
||||
/* Get various debug metrics for the specified ring buffer. */
|
||||
void hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info,
|
||||
struct hv_ring_buffer_debug_info *debug_info)
|
||||
int hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info,
|
||||
struct hv_ring_buffer_debug_info *debug_info)
|
||||
{
|
||||
u32 bytes_avail_towrite;
|
||||
u32 bytes_avail_toread;
|
||||
|
||||
if (ring_info->ring_buffer) {
|
||||
hv_get_ringbuffer_availbytes(ring_info,
|
||||
&bytes_avail_toread,
|
||||
&bytes_avail_towrite);
|
||||
if (!ring_info->ring_buffer)
|
||||
return -EINVAL;
|
||||
|
||||
debug_info->bytes_avail_toread = bytes_avail_toread;
|
||||
debug_info->bytes_avail_towrite = bytes_avail_towrite;
|
||||
debug_info->current_read_index =
|
||||
ring_info->ring_buffer->read_index;
|
||||
debug_info->current_write_index =
|
||||
ring_info->ring_buffer->write_index;
|
||||
debug_info->current_interrupt_mask =
|
||||
ring_info->ring_buffer->interrupt_mask;
|
||||
}
|
||||
hv_get_ringbuffer_availbytes(ring_info,
|
||||
&bytes_avail_toread,
|
||||
&bytes_avail_towrite);
|
||||
debug_info->bytes_avail_toread = bytes_avail_toread;
|
||||
debug_info->bytes_avail_towrite = bytes_avail_towrite;
|
||||
debug_info->current_read_index = ring_info->ring_buffer->read_index;
|
||||
debug_info->current_write_index = ring_info->ring_buffer->write_index;
|
||||
debug_info->current_interrupt_mask
|
||||
= ring_info->ring_buffer->interrupt_mask;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hv_ringbuffer_get_debuginfo);
|
||||
|
||||
|
@ -313,12 +313,16 @@ static ssize_t out_intr_mask_show(struct device *dev,
|
||||
{
|
||||
struct hv_device *hv_dev = device_to_hv_device(dev);
|
||||
struct hv_ring_buffer_debug_info outbound;
|
||||
int ret;
|
||||
|
||||
if (!hv_dev->channel)
|
||||
return -ENODEV;
|
||||
if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
|
||||
return -EINVAL;
|
||||
hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
|
||||
|
||||
ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
|
||||
&outbound);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return sprintf(buf, "%d\n", outbound.current_interrupt_mask);
|
||||
}
|
||||
static DEVICE_ATTR_RO(out_intr_mask);
|
||||
@ -328,12 +332,15 @@ static ssize_t out_read_index_show(struct device *dev,
|
||||
{
|
||||
struct hv_device *hv_dev = device_to_hv_device(dev);
|
||||
struct hv_ring_buffer_debug_info outbound;
|
||||
int ret;
|
||||
|
||||
if (!hv_dev->channel)
|
||||
return -ENODEV;
|
||||
if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
|
||||
return -EINVAL;
|
||||
hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
|
||||
|
||||
ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
|
||||
&outbound);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return sprintf(buf, "%d\n", outbound.current_read_index);
|
||||
}
|
||||
static DEVICE_ATTR_RO(out_read_index);
|
||||
@ -344,12 +351,15 @@ static ssize_t out_write_index_show(struct device *dev,
|
||||
{
|
||||
struct hv_device *hv_dev = device_to_hv_device(dev);
|
||||
struct hv_ring_buffer_debug_info outbound;
|
||||
int ret;
|
||||
|
||||
if (!hv_dev->channel)
|
||||
return -ENODEV;
|
||||
if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
|
||||
return -EINVAL;
|
||||
hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
|
||||
|
||||
ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
|
||||
&outbound);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return sprintf(buf, "%d\n", outbound.current_write_index);
|
||||
}
|
||||
static DEVICE_ATTR_RO(out_write_index);
|
||||
@ -360,12 +370,15 @@ static ssize_t out_read_bytes_avail_show(struct device *dev,
|
||||
{
|
||||
struct hv_device *hv_dev = device_to_hv_device(dev);
|
||||
struct hv_ring_buffer_debug_info outbound;
|
||||
int ret;
|
||||
|
||||
if (!hv_dev->channel)
|
||||
return -ENODEV;
|
||||
if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
|
||||
return -EINVAL;
|
||||
hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
|
||||
|
||||
ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
|
||||
&outbound);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return sprintf(buf, "%d\n", outbound.bytes_avail_toread);
|
||||
}
|
||||
static DEVICE_ATTR_RO(out_read_bytes_avail);
|
||||
@ -376,12 +389,15 @@ static ssize_t out_write_bytes_avail_show(struct device *dev,
|
||||
{
|
||||
struct hv_device *hv_dev = device_to_hv_device(dev);
|
||||
struct hv_ring_buffer_debug_info outbound;
|
||||
int ret;
|
||||
|
||||
if (!hv_dev->channel)
|
||||
return -ENODEV;
|
||||
if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
|
||||
return -EINVAL;
|
||||
hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
|
||||
|
||||
ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
|
||||
&outbound);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return sprintf(buf, "%d\n", outbound.bytes_avail_towrite);
|
||||
}
|
||||
static DEVICE_ATTR_RO(out_write_bytes_avail);
|
||||
@ -391,12 +407,15 @@ static ssize_t in_intr_mask_show(struct device *dev,
|
||||
{
|
||||
struct hv_device *hv_dev = device_to_hv_device(dev);
|
||||
struct hv_ring_buffer_debug_info inbound;
|
||||
int ret;
|
||||
|
||||
if (!hv_dev->channel)
|
||||
return -ENODEV;
|
||||
if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
|
||||
return -EINVAL;
|
||||
hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
|
||||
|
||||
ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return sprintf(buf, "%d\n", inbound.current_interrupt_mask);
|
||||
}
|
||||
static DEVICE_ATTR_RO(in_intr_mask);
|
||||
@ -406,12 +425,15 @@ static ssize_t in_read_index_show(struct device *dev,
|
||||
{
|
||||
struct hv_device *hv_dev = device_to_hv_device(dev);
|
||||
struct hv_ring_buffer_debug_info inbound;
|
||||
int ret;
|
||||
|
||||
if (!hv_dev->channel)
|
||||
return -ENODEV;
|
||||
if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
|
||||
return -EINVAL;
|
||||
hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
|
||||
|
||||
ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return sprintf(buf, "%d\n", inbound.current_read_index);
|
||||
}
|
||||
static DEVICE_ATTR_RO(in_read_index);
|
||||
@ -421,12 +443,15 @@ static ssize_t in_write_index_show(struct device *dev,
|
||||
{
|
||||
struct hv_device *hv_dev = device_to_hv_device(dev);
|
||||
struct hv_ring_buffer_debug_info inbound;
|
||||
int ret;
|
||||
|
||||
if (!hv_dev->channel)
|
||||
return -ENODEV;
|
||||
if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
|
||||
return -EINVAL;
|
||||
hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
|
||||
|
||||
ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return sprintf(buf, "%d\n", inbound.current_write_index);
|
||||
}
|
||||
static DEVICE_ATTR_RO(in_write_index);
|
||||
@ -437,12 +462,15 @@ static ssize_t in_read_bytes_avail_show(struct device *dev,
|
||||
{
|
||||
struct hv_device *hv_dev = device_to_hv_device(dev);
|
||||
struct hv_ring_buffer_debug_info inbound;
|
||||
int ret;
|
||||
|
||||
if (!hv_dev->channel)
|
||||
return -ENODEV;
|
||||
if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
|
||||
return -EINVAL;
|
||||
hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
|
||||
|
||||
ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return sprintf(buf, "%d\n", inbound.bytes_avail_toread);
|
||||
}
|
||||
static DEVICE_ATTR_RO(in_read_bytes_avail);
|
||||
@ -453,12 +481,15 @@ static ssize_t in_write_bytes_avail_show(struct device *dev,
|
||||
{
|
||||
struct hv_device *hv_dev = device_to_hv_device(dev);
|
||||
struct hv_ring_buffer_debug_info inbound;
|
||||
int ret;
|
||||
|
||||
if (!hv_dev->channel)
|
||||
return -ENODEV;
|
||||
if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
|
||||
return -EINVAL;
|
||||
hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
|
||||
|
||||
ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return sprintf(buf, "%d\n", inbound.bytes_avail_towrite);
|
||||
}
|
||||
static DEVICE_ATTR_RO(in_write_bytes_avail);
|
||||
|
@ -1159,8 +1159,9 @@ struct hv_ring_buffer_debug_info {
|
||||
u32 bytes_avail_towrite;
|
||||
};
|
||||
|
||||
void hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info,
|
||||
struct hv_ring_buffer_debug_info *debug_info);
|
||||
|
||||
int hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info,
|
||||
struct hv_ring_buffer_debug_info *debug_info);
|
||||
|
||||
/* Vmbus interface */
|
||||
#define vmbus_driver_register(driver) \
|
||||
|
Loading…
x
Reference in New Issue
Block a user