diff options
Diffstat (limited to 'drivers/hv/hv_balloon.c')
| -rw-r--r-- | drivers/hv/hv_balloon.c | 32 | 
1 files changed, 28 insertions, 4 deletions
diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c index 7e17a5495e0..5e90c5d771a 100644 --- a/drivers/hv/hv_balloon.c +++ b/drivers/hv/hv_balloon.c @@ -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> @@ -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"); @@ -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) @@ -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; @@ -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; @@ -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, @@ -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) { @@ -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; @@ -1171,7 +1194,8 @@ static int dm_thread_func(void *dm_dev)  	int t;  	while (!kthread_should_stop()) { -		t = wait_for_completion_timeout(&dm_device.config_event, 1*HZ); +		t = wait_for_completion_interruptible_timeout( +						&dm_device.config_event, 1*HZ);  		/*  		 * The host expects us to post information on the memory  		 * pressure every second.  | 
