[azure][PATCH 13/14] UBUNTU: SAUCE: vmbus: add vmbus onoffer/onoffer_rescind sync.

Marcelo Henrique Cerri marcelo.cerri at canonical.com
Tue Jun 20 17:27:33 UTC 2017


From: Dexuan Cui <decui at microsoft.com>

BugLink: http://bugs.launchpad.net/bugs/1698425

Signed-off-by: Dexuan Cui <decui at microsoft.com>
Signed-off-by: Marcelo Henrique Cerri <marcelo.cerri at canonical.com>
---
 drivers/hv/channel_mgmt.c | 25 +++++++++++++++++++------
 drivers/hv/hyperv_vmbus.h |  1 +
 drivers/hv/vmbus_drv.c    |  1 +
 3 files changed, 21 insertions(+), 6 deletions(-)

diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index 19ad79099492..a12b1eabc15e 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -467,6 +467,7 @@ void vmbus_free_channels(void)
 static void vmbus_process_offer(struct vmbus_channel *newchannel)
 {
 	struct vmbus_channel *channel;
+	struct hv_device *device_obj;
 	bool fnew = true;
 	unsigned long flags;
 	u16 dev_type;
@@ -524,6 +525,7 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
 		if (channel->sc_creation_callback != NULL)
 			channel->sc_creation_callback(newchannel);
 		atomic_dec(&vmbus_connection.offer_in_progress);
+		atomic_dec(&vmbus_connection.register_in_progress);
 		return;
 	}
 
@@ -532,33 +534,36 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
 	 * We need to set the DeviceObject field before calling
 	 * vmbus_child_dev_add()
 	 */
-	newchannel->device_obj = vmbus_device_create(
+	device_obj = vmbus_device_create(
 		&newchannel->offermsg.offer.if_type,
 		&newchannel->offermsg.offer.if_instance,
 		newchannel);
-	if (!newchannel->device_obj)
+	if (!device_obj)
 		goto err_deq_chan;
 
-	newchannel->device_obj->device_id = dev_type;
+	device_obj->device_id = dev_type;
 	/*
 	 * Add the new device to the bus. This will kick off device-driver
 	 * binding which eventually invokes the device driver's AddDevice()
 	 * method.
 	 */
-	ret = vmbus_device_register(newchannel->device_obj);
+	atomic_dec(&vmbus_connection.offer_in_progress);
+	ret = vmbus_device_register(device_obj);
 
 	if (ret != 0) {
 		pr_err("unable to add child device object (relid %d)\n",
 			newchannel->offermsg.child_relid);
-		kfree(newchannel->device_obj);
+		kfree(device_obj);
 		goto err_deq_chan;
 	}
+	newchannel->device_obj = device_obj;
+	atomic_dec(&vmbus_connection.register_in_progress);
 
-	atomic_dec(&vmbus_connection.offer_in_progress);
 	return;
 
 err_deq_chan:
 	atomic_dec(&vmbus_connection.offer_in_progress);
+	atomic_dec(&vmbus_connection.register_in_progress);
 	mutex_lock(&vmbus_connection.channel_mutex);
 	list_del(&newchannel->listentry);
 	mutex_unlock(&vmbus_connection.channel_mutex);
@@ -889,6 +894,14 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
 
 	vmbus_rescind_cleanup(channel);
 
+	while (atomic_read(&vmbus_connection.register_in_progress) != 0) {
+		/*
+		 * We wait here until any channel offer is currently
+		 * being processed.
+		 */
+		msleep(1);
+	}
+
 	if (channel->device_obj) {
 		if (channel->chn_rescind_callback) {
 			channel->chn_rescind_callback(channel);
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
index 7b8603a00555..30ae1d291527 100644
--- a/drivers/hv/hyperv_vmbus.h
+++ b/drivers/hv/hyperv_vmbus.h
@@ -309,6 +309,7 @@ struct vmbus_connection {
 	int connect_cpu;
 
 	atomic_t offer_in_progress;
+	atomic_t register_in_progress;
 
 	enum vmbus_connect_state conn_state;
 
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index fd221cffeb4d..fc6a5893d54c 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -871,6 +871,7 @@ static void vmbus_dispatch_msg_work(struct work_struct *work)
 		flush_workqueue(vmbus_connection.work_queue_rescind);
 
 		atomic_inc(&vmbus_connection.offer_in_progress);
+		atomic_inc(&vmbus_connection.register_in_progress);
 		queue_work_on(vmbus_connection.connect_cpu,
 			      vmbus_connection.work_queue,
 			      &context->work);
-- 
2.7.4




More information about the kernel-team mailing list