Commit ae339336 authored by K. Y. Srinivasan's avatar K. Y. Srinivasan Committed by Greg Kroah-Hartman

Drivers: hv: balloon: Ensure pressure reports are posted regularly

The current code posts periodic memory pressure status from a dedicated thread.
Under some conditions, especially when we are releasing a lot of memory into
the guest, we may not send timely pressure reports back to the host. Fix this
issue by reporting pressure in all contexts that can be active in this driver.
Signed-off-by: default avatarK. Y. Srinivasan <kys@microsoft.com>
Cc: stable@vger.kernel.org
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 24b8a406
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/jiffies.h>
#include <linux/mman.h> #include <linux/mman.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -459,6 +460,11 @@ static bool do_hot_add; ...@@ -459,6 +460,11 @@ static bool do_hot_add;
*/ */
static uint pressure_report_delay = 45; static uint pressure_report_delay = 45;
/*
* The last time we posted a pressure report to host.
*/
static unsigned long last_post_time;
module_param(hot_add, bool, (S_IRUGO | S_IWUSR)); module_param(hot_add, bool, (S_IRUGO | S_IWUSR));
MODULE_PARM_DESC(hot_add, "If set attempt memory hot_add"); MODULE_PARM_DESC(hot_add, "If set attempt memory hot_add");
...@@ -542,6 +548,7 @@ struct hv_dynmem_device { ...@@ -542,6 +548,7 @@ struct hv_dynmem_device {
static struct hv_dynmem_device dm_device; static struct hv_dynmem_device dm_device;
static void post_status(struct hv_dynmem_device *dm);
#ifdef CONFIG_MEMORY_HOTPLUG #ifdef CONFIG_MEMORY_HOTPLUG
static void hv_bring_pgs_online(unsigned long start_pfn, unsigned long size) static void hv_bring_pgs_online(unsigned long start_pfn, unsigned long size)
...@@ -612,7 +619,7 @@ static void hv_mem_hot_add(unsigned long start, unsigned long size, ...@@ -612,7 +619,7 @@ static void hv_mem_hot_add(unsigned long start, unsigned long size,
* have not been "onlined" within the allowed time. * have not been "onlined" within the allowed time.
*/ */
wait_for_completion_timeout(&dm_device.ol_waitevent, 5*HZ); wait_for_completion_timeout(&dm_device.ol_waitevent, 5*HZ);
post_status(&dm_device);
} }
return; return;
...@@ -951,11 +958,17 @@ static void post_status(struct hv_dynmem_device *dm) ...@@ -951,11 +958,17 @@ static void post_status(struct hv_dynmem_device *dm)
{ {
struct dm_status status; struct dm_status status;
struct sysinfo val; struct sysinfo val;
unsigned long now = jiffies;
unsigned long last_post = last_post_time;
if (pressure_report_delay > 0) { if (pressure_report_delay > 0) {
--pressure_report_delay; --pressure_report_delay;
return; return;
} }
if (!time_after(now, (last_post_time + HZ)))
return;
si_meminfo(&val); si_meminfo(&val);
memset(&status, 0, sizeof(struct dm_status)); memset(&status, 0, sizeof(struct dm_status));
status.hdr.type = DM_STATUS_REPORT; status.hdr.type = DM_STATUS_REPORT;
...@@ -983,6 +996,14 @@ static void post_status(struct hv_dynmem_device *dm) ...@@ -983,6 +996,14 @@ static void post_status(struct hv_dynmem_device *dm)
if (status.hdr.trans_id != atomic_read(&trans_id)) if (status.hdr.trans_id != atomic_read(&trans_id))
return; return;
/*
* If the last post time that we sampled has changed,
* we have raced, don't post the status.
*/
if (last_post != last_post_time)
return;
last_post_time = jiffies;
vmbus_sendpacket(dm->dev->channel, &status, vmbus_sendpacket(dm->dev->channel, &status,
sizeof(struct dm_status), sizeof(struct dm_status),
(unsigned long)NULL, (unsigned long)NULL,
...@@ -1117,7 +1138,7 @@ static void balloon_up(struct work_struct *dummy) ...@@ -1117,7 +1138,7 @@ static void balloon_up(struct work_struct *dummy)
if (ret == -EAGAIN) if (ret == -EAGAIN)
msleep(20); msleep(20);
post_status(&dm_device);
} while (ret == -EAGAIN); } while (ret == -EAGAIN);
if (ret) { if (ret) {
...@@ -1144,8 +1165,10 @@ static void balloon_down(struct hv_dynmem_device *dm, ...@@ -1144,8 +1165,10 @@ static void balloon_down(struct hv_dynmem_device *dm,
struct dm_unballoon_response resp; struct dm_unballoon_response resp;
int i; int i;
for (i = 0; i < range_count; i++) for (i = 0; i < range_count; i++) {
free_balloon_pages(dm, &range_array[i]); free_balloon_pages(dm, &range_array[i]);
post_status(&dm_device);
}
if (req->more_pages == 1) if (req->more_pages == 1)
return; return;
......
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