Skip to content

Commit

Permalink
Drivers: hv: balloon: Ensure pressure reports are posted regularly
Browse files Browse the repository at this point in the history
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: K. Y. Srinivasan <kys@microsoft.com>
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
K. Y. Srinivasan authored and Greg Kroah-Hartman committed May 3, 2014
1 parent 24b8a40 commit ae33933
Showing 1 changed file with 26 additions and 3 deletions.
29 changes: 26 additions & 3 deletions drivers/hv/hv_balloon.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/kernel.h>
#include <linux/jiffies.h>
#include <linux/mman.h>
#include <linux/delay.h>
#include <linux/init.h>
Expand Down Expand Up @@ -459,6 +460,11 @@ static bool do_hot_add;
*/
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_PARM_DESC(hot_add, "If set attempt memory hot_add");

Expand Down Expand Up @@ -542,6 +548,7 @@ struct hv_dynmem_device {

static struct hv_dynmem_device dm_device;

static void post_status(struct hv_dynmem_device *dm);
#ifdef CONFIG_MEMORY_HOTPLUG

static void hv_bring_pgs_online(unsigned long start_pfn, unsigned long size)
Expand Down Expand Up @@ -612,7 +619,7 @@ static void hv_mem_hot_add(unsigned long start, unsigned long size,
* have not been "onlined" within the allowed time.
*/
wait_for_completion_timeout(&dm_device.ol_waitevent, 5*HZ);

post_status(&dm_device);
}

return;
Expand Down Expand Up @@ -951,11 +958,17 @@ static void post_status(struct hv_dynmem_device *dm)
{
struct dm_status status;
struct sysinfo val;
unsigned long now = jiffies;
unsigned long last_post = last_post_time;

if (pressure_report_delay > 0) {
--pressure_report_delay;
return;
}

if (!time_after(now, (last_post_time + HZ)))
return;

si_meminfo(&val);
memset(&status, 0, sizeof(struct dm_status));
status.hdr.type = DM_STATUS_REPORT;
Expand Down Expand Up @@ -983,6 +996,14 @@ static void post_status(struct hv_dynmem_device *dm)
if (status.hdr.trans_id != atomic_read(&trans_id))
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,
sizeof(struct dm_status),
(unsigned long)NULL,
Expand Down Expand Up @@ -1117,7 +1138,7 @@ static void balloon_up(struct work_struct *dummy)

if (ret == -EAGAIN)
msleep(20);

post_status(&dm_device);
} while (ret == -EAGAIN);

if (ret) {
Expand All @@ -1144,8 +1165,10 @@ static void balloon_down(struct hv_dynmem_device *dm,
struct dm_unballoon_response resp;
int i;

for (i = 0; i < range_count; i++)
for (i = 0; i < range_count; i++) {
free_balloon_pages(dm, &range_array[i]);
post_status(&dm_device);
}

if (req->more_pages == 1)
return;
Expand Down

0 comments on commit ae33933

Please sign in to comment.