Commit 411aba3c authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'hyperv-fixes-signed' of...

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
parents 36bdf3ca b5679ceb
...@@ -701,19 +701,12 @@ static int vmbus_close_internal(struct vmbus_channel *channel) ...@@ -701,19 +701,12 @@ static int vmbus_close_internal(struct vmbus_channel *channel)
int vmbus_disconnect_ring(struct vmbus_channel *channel) int vmbus_disconnect_ring(struct vmbus_channel *channel)
{ {
struct vmbus_channel *cur_channel, *tmp; struct vmbus_channel *cur_channel, *tmp;
unsigned long flags;
LIST_HEAD(list);
int ret; int ret;
if (channel->primary_channel != NULL) if (channel->primary_channel != NULL)
return -EINVAL; return -EINVAL;
/* Snapshot the list of subchannels */ list_for_each_entry_safe(cur_channel, tmp, &channel->sc_list, sc_list) {
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) {
if (cur_channel->rescind) if (cur_channel->rescind)
wait_for_completion(&cur_channel->rescind_event); wait_for_completion(&cur_channel->rescind_event);
......
...@@ -888,12 +888,14 @@ static unsigned long handle_pg_range(unsigned long pg_start, ...@@ -888,12 +888,14 @@ static unsigned long handle_pg_range(unsigned long pg_start,
pfn_cnt -= pgs_ol; pfn_cnt -= pgs_ol;
/* /*
* Check if the corresponding memory block is already * Check if the corresponding memory block is already
* online by checking its last previously backed page. * online. It is possible to observe struct pages still
* In case it is we need to bring rest (which was not * being uninitialized here so check section instead.
* backed previously) online too. * 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 && 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); hv_bring_pgs_online(has, start_pfn, pgs_ol);
} }
......
...@@ -164,26 +164,25 @@ hv_get_ringbuffer_availbytes(const struct hv_ring_buffer_info *rbi, ...@@ -164,26 +164,25 @@ hv_get_ringbuffer_availbytes(const struct hv_ring_buffer_info *rbi,
} }
/* Get various debug metrics for the specified ring buffer. */ /* Get various debug metrics for the specified ring buffer. */
void hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info, int hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info,
struct hv_ring_buffer_debug_info *debug_info) struct hv_ring_buffer_debug_info *debug_info)
{ {
u32 bytes_avail_towrite; u32 bytes_avail_towrite;
u32 bytes_avail_toread; u32 bytes_avail_toread;
if (ring_info->ring_buffer) { if (!ring_info->ring_buffer)
hv_get_ringbuffer_availbytes(ring_info, return -EINVAL;
&bytes_avail_toread,
&bytes_avail_towrite); hv_get_ringbuffer_availbytes(ring_info,
&bytes_avail_toread,
debug_info->bytes_avail_toread = bytes_avail_toread; &bytes_avail_towrite);
debug_info->bytes_avail_towrite = bytes_avail_towrite; debug_info->bytes_avail_toread = bytes_avail_toread;
debug_info->current_read_index = debug_info->bytes_avail_towrite = bytes_avail_towrite;
ring_info->ring_buffer->read_index; debug_info->current_read_index = ring_info->ring_buffer->read_index;
debug_info->current_write_index = debug_info->current_write_index = ring_info->ring_buffer->write_index;
ring_info->ring_buffer->write_index; debug_info->current_interrupt_mask
debug_info->current_interrupt_mask = = ring_info->ring_buffer->interrupt_mask;
ring_info->ring_buffer->interrupt_mask; return 0;
}
} }
EXPORT_SYMBOL_GPL(hv_ringbuffer_get_debuginfo); EXPORT_SYMBOL_GPL(hv_ringbuffer_get_debuginfo);
......
...@@ -313,12 +313,16 @@ static ssize_t out_intr_mask_show(struct device *dev, ...@@ -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_device *hv_dev = device_to_hv_device(dev);
struct hv_ring_buffer_debug_info outbound; struct hv_ring_buffer_debug_info outbound;
int ret;
if (!hv_dev->channel) if (!hv_dev->channel)
return -ENODEV; return -ENODEV;
if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
return -EINVAL; ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound); &outbound);
if (ret < 0)
return ret;
return sprintf(buf, "%d\n", outbound.current_interrupt_mask); return sprintf(buf, "%d\n", outbound.current_interrupt_mask);
} }
static DEVICE_ATTR_RO(out_intr_mask); static DEVICE_ATTR_RO(out_intr_mask);
...@@ -328,12 +332,15 @@ static ssize_t out_read_index_show(struct device *dev, ...@@ -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_device *hv_dev = device_to_hv_device(dev);
struct hv_ring_buffer_debug_info outbound; struct hv_ring_buffer_debug_info outbound;
int ret;
if (!hv_dev->channel) if (!hv_dev->channel)
return -ENODEV; return -ENODEV;
if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
return -EINVAL; ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound); &outbound);
if (ret < 0)
return ret;
return sprintf(buf, "%d\n", outbound.current_read_index); return sprintf(buf, "%d\n", outbound.current_read_index);
} }
static DEVICE_ATTR_RO(out_read_index); static DEVICE_ATTR_RO(out_read_index);
...@@ -344,12 +351,15 @@ static ssize_t out_write_index_show(struct device *dev, ...@@ -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_device *hv_dev = device_to_hv_device(dev);
struct hv_ring_buffer_debug_info outbound; struct hv_ring_buffer_debug_info outbound;
int ret;
if (!hv_dev->channel) if (!hv_dev->channel)
return -ENODEV; return -ENODEV;
if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
return -EINVAL; ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound); &outbound);
if (ret < 0)
return ret;
return sprintf(buf, "%d\n", outbound.current_write_index); return sprintf(buf, "%d\n", outbound.current_write_index);
} }
static DEVICE_ATTR_RO(out_write_index); static DEVICE_ATTR_RO(out_write_index);
...@@ -360,12 +370,15 @@ static ssize_t out_read_bytes_avail_show(struct device *dev, ...@@ -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_device *hv_dev = device_to_hv_device(dev);
struct hv_ring_buffer_debug_info outbound; struct hv_ring_buffer_debug_info outbound;
int ret;
if (!hv_dev->channel) if (!hv_dev->channel)
return -ENODEV; return -ENODEV;
if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
return -EINVAL; ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound); &outbound);
if (ret < 0)
return ret;
return sprintf(buf, "%d\n", outbound.bytes_avail_toread); return sprintf(buf, "%d\n", outbound.bytes_avail_toread);
} }
static DEVICE_ATTR_RO(out_read_bytes_avail); static DEVICE_ATTR_RO(out_read_bytes_avail);
...@@ -376,12 +389,15 @@ static ssize_t out_write_bytes_avail_show(struct device *dev, ...@@ -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_device *hv_dev = device_to_hv_device(dev);
struct hv_ring_buffer_debug_info outbound; struct hv_ring_buffer_debug_info outbound;
int ret;
if (!hv_dev->channel) if (!hv_dev->channel)
return -ENODEV; return -ENODEV;
if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
return -EINVAL; ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound); &outbound);
if (ret < 0)
return ret;
return sprintf(buf, "%d\n", outbound.bytes_avail_towrite); return sprintf(buf, "%d\n", outbound.bytes_avail_towrite);
} }
static DEVICE_ATTR_RO(out_write_bytes_avail); static DEVICE_ATTR_RO(out_write_bytes_avail);
...@@ -391,12 +407,15 @@ static ssize_t in_intr_mask_show(struct device *dev, ...@@ -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_device *hv_dev = device_to_hv_device(dev);
struct hv_ring_buffer_debug_info inbound; struct hv_ring_buffer_debug_info inbound;
int ret;
if (!hv_dev->channel) if (!hv_dev->channel)
return -ENODEV; return -ENODEV;
if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
return -EINVAL; ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound); if (ret < 0)
return ret;
return sprintf(buf, "%d\n", inbound.current_interrupt_mask); return sprintf(buf, "%d\n", inbound.current_interrupt_mask);
} }
static DEVICE_ATTR_RO(in_intr_mask); static DEVICE_ATTR_RO(in_intr_mask);
...@@ -406,12 +425,15 @@ static ssize_t in_read_index_show(struct device *dev, ...@@ -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_device *hv_dev = device_to_hv_device(dev);
struct hv_ring_buffer_debug_info inbound; struct hv_ring_buffer_debug_info inbound;
int ret;
if (!hv_dev->channel) if (!hv_dev->channel)
return -ENODEV; return -ENODEV;
if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
return -EINVAL; ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound); if (ret < 0)
return ret;
return sprintf(buf, "%d\n", inbound.current_read_index); return sprintf(buf, "%d\n", inbound.current_read_index);
} }
static DEVICE_ATTR_RO(in_read_index); static DEVICE_ATTR_RO(in_read_index);
...@@ -421,12 +443,15 @@ static ssize_t in_write_index_show(struct device *dev, ...@@ -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_device *hv_dev = device_to_hv_device(dev);
struct hv_ring_buffer_debug_info inbound; struct hv_ring_buffer_debug_info inbound;
int ret;
if (!hv_dev->channel) if (!hv_dev->channel)
return -ENODEV; return -ENODEV;
if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
return -EINVAL; ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound); if (ret < 0)
return ret;
return sprintf(buf, "%d\n", inbound.current_write_index); return sprintf(buf, "%d\n", inbound.current_write_index);
} }
static DEVICE_ATTR_RO(in_write_index); static DEVICE_ATTR_RO(in_write_index);
...@@ -437,12 +462,15 @@ static ssize_t in_read_bytes_avail_show(struct device *dev, ...@@ -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_device *hv_dev = device_to_hv_device(dev);
struct hv_ring_buffer_debug_info inbound; struct hv_ring_buffer_debug_info inbound;
int ret;
if (!hv_dev->channel) if (!hv_dev->channel)
return -ENODEV; return -ENODEV;
if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
return -EINVAL; ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound); if (ret < 0)
return ret;
return sprintf(buf, "%d\n", inbound.bytes_avail_toread); return sprintf(buf, "%d\n", inbound.bytes_avail_toread);
} }
static DEVICE_ATTR_RO(in_read_bytes_avail); static DEVICE_ATTR_RO(in_read_bytes_avail);
...@@ -453,12 +481,15 @@ static ssize_t in_write_bytes_avail_show(struct device *dev, ...@@ -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_device *hv_dev = device_to_hv_device(dev);
struct hv_ring_buffer_debug_info inbound; struct hv_ring_buffer_debug_info inbound;
int ret;
if (!hv_dev->channel) if (!hv_dev->channel)
return -ENODEV; return -ENODEV;
if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
return -EINVAL; ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound); if (ret < 0)
return ret;
return sprintf(buf, "%d\n", inbound.bytes_avail_towrite); return sprintf(buf, "%d\n", inbound.bytes_avail_towrite);
} }
static DEVICE_ATTR_RO(in_write_bytes_avail); static DEVICE_ATTR_RO(in_write_bytes_avail);
......
...@@ -1159,8 +1159,9 @@ struct hv_ring_buffer_debug_info { ...@@ -1159,8 +1159,9 @@ struct hv_ring_buffer_debug_info {
u32 bytes_avail_towrite; 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 */ /* Vmbus interface */
#define vmbus_driver_register(driver) \ #define vmbus_driver_register(driver) \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment