linux-hyperv.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2] Drivers: hv: vm_bus: Handle vmbus rescind calls after vmbus is suspended
@ 2022-07-10 18:14 Shradha Gupta
  2022-07-11  1:31 ` kernel test robot
  0 siblings, 1 reply; 2+ messages in thread
From: Shradha Gupta @ 2022-07-10 18:14 UTC (permalink / raw)
  To: linux-hyperv, linux-kernel
  Cc: K. Y. Srinivasan, Haiyang Zhang, Stephen Hemminger, Wei Liu,
	Dexuan Cui, Shradha Gupta, Praveen Kumar

Add a flag to indicate that the vmbus is suspended so we should ignore
any offer message. Add a new work_queue for rescind msg, so we could drain
it along with other offer work_queues upon suspension.
It was observed that in some hibernation related scenario testing, after
vmbus_bus_suspend() we get rescind offer message for the vmbus. This would
lead to processing of a rescind message for a channel that has already been
suspended.

Signed-off-by: Shradha Gupta <shradhagupta@linux.microsoft.com>
---

Changes in v2:
* Rename the ignore_offer_rescind_msg flag to ignore_any_offer_msg, to
  indicate that the flag can cause any offer message to be dropped.
* Remove redundent tasklet_enable(), tasklet_disable() calls around
  ignore_any_offer_msg flag when value is changed from true to false.
* Add comment about tasklet_enable() providing memory barrier.
* In vmbus_bus_suspend() after we drain all workqueues, remove the code
  to wait for any offer_in_progress

---
 drivers/hv/connection.c   | 11 +++++++++++
 drivers/hv/hyperv_vmbus.h |  7 +++++++
 drivers/hv/vmbus_drv.c    | 29 +++++++++++++++++++++--------
 3 files changed, 39 insertions(+), 8 deletions(-)

diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c
index 6218bbf6863a..eca7afd366d6 100644
--- a/drivers/hv/connection.c
+++ b/drivers/hv/connection.c
@@ -171,6 +171,14 @@ int vmbus_connect(void)
 		goto cleanup;
 	}
 
+	vmbus_connection.rescind_work_queue =
+		create_workqueue("hv_vmbus_rescind");
+	if (!vmbus_connection.rescind_work_queue) {
+		ret = -ENOMEM;
+		goto cleanup;
+	}
+	vmbus_connection.ignore_any_offer_msg = false;
+
 	vmbus_connection.handle_primary_chan_wq =
 		create_workqueue("hv_pri_chan");
 	if (!vmbus_connection.handle_primary_chan_wq) {
@@ -357,6 +365,9 @@ void vmbus_disconnect(void)
 	if (vmbus_connection.handle_primary_chan_wq)
 		destroy_workqueue(vmbus_connection.handle_primary_chan_wq);
 
+	if (vmbus_connection.rescind_work_queue)
+		destroy_workqueue(vmbus_connection.rescind_work_queue);
+
 	if (vmbus_connection.work_queue)
 		destroy_workqueue(vmbus_connection.work_queue);
 
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
index 4f5b824b16cf..dc673edf053c 100644
--- a/drivers/hv/hyperv_vmbus.h
+++ b/drivers/hv/hyperv_vmbus.h
@@ -261,6 +261,13 @@ struct vmbus_connection {
 	struct workqueue_struct *work_queue;
 	struct workqueue_struct *handle_primary_chan_wq;
 	struct workqueue_struct *handle_sub_chan_wq;
+	struct workqueue_struct *rescind_work_queue;
+
+	/*
+	 * On suspension of the vmbus, the accumulated offer messages
+	 * must be dropped.
+	 */
+	bool ignore_any_offer_msg;
 
 	/*
 	 * The number of sub-channels and hv_sock channels that should be
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index 547ae334e5cd..4ba0eb2441cf 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -1160,7 +1160,9 @@ void vmbus_on_msg_dpc(unsigned long data)
 			 * work queue: the RESCIND handler can not start to
 			 * run before the OFFER handler finishes.
 			 */
-			schedule_work(&ctx->work);
+			if (vmbus_connection.ignore_any_offer_msg)
+				break;
+			queue_work(vmbus_connection.rescind_work_queue, &ctx->work);
 			break;
 
 		case CHANNELMSG_OFFERCHANNEL:
@@ -1186,6 +1188,8 @@ void vmbus_on_msg_dpc(unsigned long data)
 			 * to the CPUs which will execute the offer & rescind
 			 * works by the time these works will start execution.
 			 */
+			if (vmbus_connection.ignore_any_offer_msg)
+				break;
 			atomic_inc(&vmbus_connection.offer_in_progress);
 			fallthrough;
 
@@ -2446,15 +2450,20 @@ static int vmbus_acpi_add(struct acpi_device *device)
 #ifdef CONFIG_PM_SLEEP
 static int vmbus_bus_suspend(struct device *dev)
 {
+	struct hv_per_cpu_context *hv_cpu = per_cpu_ptr(
+			hv_context.cpu_context, VMBUS_CONNECT_CPU);
 	struct vmbus_channel *channel, *sc;
 
-	while (atomic_read(&vmbus_connection.offer_in_progress) != 0) {
-		/*
-		 * We wait here until the completion of any channel
-		 * offers that are currently in progress.
-		 */
-		usleep_range(1000, 2000);
-	}
+	tasklet_disable(&hv_cpu->msg_dpc);
+	vmbus_connection.ignore_any_offer_msg = true;
+	/* The tasklet_enable() takes care of providing a memory barrier */
+	tasklet_enable(&hv_cpu->msg_dpc);
+
+	/* Drain all the workqueues as we are in suspend */
+	drain_workqueue(vmbus_connection.rescind_work_queue);
+	drain_workqueue(vmbus_connection.work_queue);
+	drain_workqueue(vmbus_connection.handle_primary_chan_wq);
+	drain_workqueue(vmbus_connection.handle_sub_chan_wq);
 
 	mutex_lock(&vmbus_connection.channel_mutex);
 	list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) {
@@ -2527,10 +2536,14 @@ static int vmbus_bus_suspend(struct device *dev)
 
 static int vmbus_bus_resume(struct device *dev)
 {
+	struct hv_per_cpu_context *hv_cpu = per_cpu_ptr(
+			hv_context.cpu_context, VMBUS_CONNECT_CPU);
 	struct vmbus_channel_msginfo *msginfo;
 	size_t msgsize;
 	int ret;
 
+	vmbus_connection.ignore_any_offer_msg = false;
+
 	/*
 	 * We only use the 'vmbus_proto_version', which was in use before
 	 * hibernation, to re-negotiate with the host.
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH v2] Drivers: hv: vm_bus: Handle vmbus rescind calls after vmbus is suspended
  2022-07-10 18:14 [PATCH v2] Drivers: hv: vm_bus: Handle vmbus rescind calls after vmbus is suspended Shradha Gupta
@ 2022-07-11  1:31 ` kernel test robot
  0 siblings, 0 replies; 2+ messages in thread
From: kernel test robot @ 2022-07-11  1:31 UTC (permalink / raw)
  To: Shradha Gupta, linux-hyperv, linux-kernel
  Cc: kbuild-all, K. Y. Srinivasan, Haiyang Zhang, Stephen Hemminger,
	Wei Liu, Dexuan Cui, Shradha Gupta, Praveen Kumar

Hi Shradha,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on linus/master]
[also build test WARNING on v5.19-rc5 next-20220708]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Shradha-Gupta/Drivers-hv-vm_bus-Handle-vmbus-rescind-calls-after-vmbus-is-suspended/20220711-021702
base:   https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 5867f3b88bb54016c42cdde510c184255488a12b
config: i386-allyesconfig (https://download.01.org/0day-ci/archive/20220711/202207110545.MC79d9J7-lkp@intel.com/config)
compiler: gcc-11 (Debian 11.3.0-3) 11.3.0
reproduce (this is a W=1 build):
        # https://github.com/intel-lab-lkp/linux/commit/7fbe63d321d3e0c099e90e8d8c36921c58c8868f
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Shradha-Gupta/Drivers-hv-vm_bus-Handle-vmbus-rescind-calls-after-vmbus-is-suspended/20220711-021702
        git checkout 7fbe63d321d3e0c099e90e8d8c36921c58c8868f
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        make W=1 O=build_dir ARCH=i386 SHELL=/bin/bash drivers/hv/

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   drivers/hv/vmbus_drv.c: In function 'vmbus_bus_resume':
>> drivers/hv/vmbus_drv.c:2539:36: warning: unused variable 'hv_cpu' [-Wunused-variable]
    2539 |         struct hv_per_cpu_context *hv_cpu = per_cpu_ptr(
         |                                    ^~~~~~


vim +/hv_cpu +2539 drivers/hv/vmbus_drv.c

  2536	
  2537	static int vmbus_bus_resume(struct device *dev)
  2538	{
> 2539		struct hv_per_cpu_context *hv_cpu = per_cpu_ptr(
  2540				hv_context.cpu_context, VMBUS_CONNECT_CPU);
  2541		struct vmbus_channel_msginfo *msginfo;
  2542		size_t msgsize;
  2543		int ret;
  2544	
  2545		vmbus_connection.ignore_any_offer_msg = false;
  2546	
  2547		/*
  2548		 * We only use the 'vmbus_proto_version', which was in use before
  2549		 * hibernation, to re-negotiate with the host.
  2550		 */
  2551		if (!vmbus_proto_version) {
  2552			pr_err("Invalid proto version = 0x%x\n", vmbus_proto_version);
  2553			return -EINVAL;
  2554		}
  2555	
  2556		msgsize = sizeof(*msginfo) +
  2557			  sizeof(struct vmbus_channel_initiate_contact);
  2558	
  2559		msginfo = kzalloc(msgsize, GFP_KERNEL);
  2560	
  2561		if (msginfo == NULL)
  2562			return -ENOMEM;
  2563	
  2564		ret = vmbus_negotiate_version(msginfo, vmbus_proto_version);
  2565	
  2566		kfree(msginfo);
  2567	
  2568		if (ret != 0)
  2569			return ret;
  2570	
  2571		WARN_ON(atomic_read(&vmbus_connection.nr_chan_fixup_on_resume) == 0);
  2572	
  2573		vmbus_request_offers();
  2574	
  2575		if (wait_for_completion_timeout(
  2576			&vmbus_connection.ready_for_resume_event, 10 * HZ) == 0)
  2577			pr_err("Some vmbus device is missing after suspending?\n");
  2578	
  2579		/* Reset the event for the next suspend. */
  2580		reinit_completion(&vmbus_connection.ready_for_suspend_event);
  2581	
  2582		return 0;
  2583	}
  2584	#else
  2585	#define vmbus_bus_suspend NULL
  2586	#define vmbus_bus_resume NULL
  2587	#endif /* CONFIG_PM_SLEEP */
  2588	

-- 
0-DAY CI Kernel Test Service
https://01.org/lkp

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2022-07-11  1:32 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-07-10 18:14 [PATCH v2] Drivers: hv: vm_bus: Handle vmbus rescind calls after vmbus is suspended Shradha Gupta
2022-07-11  1:31 ` kernel test robot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).