Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlaf Hering <ohering@suse.de>2017-10-20 12:20:33 +0200
committerOlaf Hering <ohering@suse.de>2017-10-20 12:23:28 +0200
commit35b542f7643b794295a9de247eb0ecf4380bb6c5 (patch)
tree79dcdb18864dd763161668d73decb19cceb2142a
parentfb1fb2bc950c9079cec952b0927290dd088cf652 (diff)
Drivers: hv: vmbus: Fix rescind handling issues (fate#323887).
-rw-r--r--patches.suse/msft-hv-1442-Drivers-hv-vmbus-Fix-rescind-handling-issues.patch161
-rw-r--r--series.conf1
2 files changed, 162 insertions, 0 deletions
diff --git a/patches.suse/msft-hv-1442-Drivers-hv-vmbus-Fix-rescind-handling-issues.patch b/patches.suse/msft-hv-1442-Drivers-hv-vmbus-Fix-rescind-handling-issues.patch
new file mode 100644
index 0000000000..3b5d476cf7
--- /dev/null
+++ b/patches.suse/msft-hv-1442-Drivers-hv-vmbus-Fix-rescind-handling-issues.patch
@@ -0,0 +1,161 @@
+From: "K. Y. Srinivasan" <kys@microsoft.com>
+Date: Fri, 11 Aug 2017 10:03:59 -0700
+Patch-mainline: v4.14-rc1
+Subject: Drivers: hv: vmbus: Fix rescind handling issues
+Git-commit: 6f3d791f300618caf82a2be0c27456edd76d5164
+References: fate#323887
+
+This patch handles the following issues that were observed when we are
+handling racing channel offer message and rescind message for the same
+offer:
+
+1. Since the host does not respond to messages on a rescinded channel,
+in the current code, we could be indefinitely blocked on the vmbus_open() call.
+
+2. When a rescinded channel is being closed, if there is a pending interrupt on the
+channel, we could end up freeing the channel that the interrupt handler would run on.
+
+Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
+Reviewed-by: Dexuan Cui <decui@microsoft.com>
+Tested-by: Dexuan Cui <decui@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Acked-by: Olaf Hering <ohering@suse.de>
+---
+ drivers/hv/channel.c | 14 ++++++++++++++
+ drivers/hv/channel_mgmt.c | 29 ++++++++++++++++++++++++++---
+ drivers/hv/vmbus_drv.c | 3 +++
+ include/linux/hyperv.h | 2 ++
+ 4 files changed, 45 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
+--- a/drivers/hv/channel.c
++++ b/drivers/hv/channel.c
+@@ -177,6 +177,11 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
+ &vmbus_connection.chn_msg_list);
+ spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+
++ if (newchannel->rescind) {
++ err = -ENODEV;
++ goto error_free_gpadl;
++ }
++
+ ret = vmbus_post_msg(open_msg,
+ sizeof(struct vmbus_channel_open_channel), true);
+
+@@ -421,6 +426,11 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
+
+ spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+
++ if (channel->rescind) {
++ ret = -ENODEV;
++ goto cleanup;
++ }
++
+ ret = vmbus_post_msg(gpadlmsg, msginfo->msgsize -
+ sizeof(*msginfo), true);
+ if (ret != 0)
+@@ -494,6 +504,10 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)
+ list_add_tail(&info->msglistentry,
+ &vmbus_connection.chn_msg_list);
+ spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
++
++ if (channel->rescind)
++ goto post_msg_err;
++
+ ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_gpadl_teardown),
+ true);
+
+diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
+--- a/drivers/hv/channel_mgmt.c
++++ b/drivers/hv/channel_mgmt.c
+@@ -451,6 +451,12 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
+ /* Make sure this is a new offer */
+ mutex_lock(&vmbus_connection.channel_mutex);
+
++ /*
++ * Now that we have acquired the channel_mutex,
++ * we can release the potentially racing rescind thread.
++ */
++ atomic_dec(&vmbus_connection.offer_in_progress);
++
+ list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) {
+ if (!uuid_le_cmp(channel->offermsg.offer.if_type,
+ newchannel->offermsg.offer.if_type) &&
+@@ -481,7 +487,6 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
+ channel->num_sc++;
+ spin_unlock_irqrestore(&channel->lock, flags);
+ } else {
+- atomic_dec(&vmbus_connection.offer_in_progress);
+ goto err_free_chan;
+ }
+ }
+@@ -510,7 +515,6 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
+ if (!fnew) {
+ if (channel->sc_creation_callback != NULL)
+ channel->sc_creation_callback(newchannel);
+- atomic_dec(&vmbus_connection.offer_in_progress);
+ return;
+ }
+
+@@ -541,7 +545,7 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
+ goto err_deq_chan;
+ }
+
+- atomic_dec(&vmbus_connection.offer_in_progress);
++ newchannel->probe_done = true;
+ return;
+
+ err_deq_chan:
+@@ -882,8 +886,27 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
+ channel->rescind = true;
+ spin_unlock_irqrestore(&channel->lock, flags);
+
++ /*
++ * Now that we have posted the rescind state, perform
++ * rescind related cleanup.
++ */
+ vmbus_rescind_cleanup(channel);
+
++ /*
++ * Now wait for offer handling to complete.
++ */
++ while (READ_ONCE(channel->probe_done) == false) {
++ /*
++ * We wait here until any channel offer is currently
++ * being processed.
++ */
++ msleep(1);
++ }
++
++ /*
++ * At this point, the rescind handling can proceed safely.
++ */
++
+ if (channel->device_obj) {
+ if (channel->chn_rescind_callback) {
+ channel->chn_rescind_callback(channel);
+diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
+--- a/drivers/hv/vmbus_drv.c
++++ b/drivers/hv/vmbus_drv.c
+@@ -940,6 +940,9 @@ static void vmbus_chan_sched(struct hv_per_cpu_context *hv_cpu)
+ if (channel->offermsg.child_relid != relid)
+ continue;
+
++ if (channel->rescind)
++ continue;
++
+ switch (channel->callback_mode) {
+ case HV_CALL_ISR:
+ vmbus_channel_isr(channel);
+diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
+--- a/include/linux/hyperv.h
++++ b/include/linux/hyperv.h
+@@ -879,6 +879,8 @@ struct vmbus_channel {
+ */
+ enum hv_numa_policy affinity_policy;
+
++ bool probe_done;
++
+ };
+
+ static inline bool is_hvsock_channel(const struct vmbus_channel *c)
diff --git a/series.conf b/series.conf
index abe5dfa303..14743266b7 100644
--- a/series.conf
+++ b/series.conf
@@ -1692,6 +1692,7 @@
patches.suse/msft-hv-1439-Drivers-hv-kvp-Use-MAX_ADAPTER_ID_SIZE-for-translati.patch
patches.suse/msft-hv-1440-Tools-hv-fix-snprintf-warning-in-kvp_daemon.patch
patches.suse/msft-hv-1441-Tools-hv-update-buffer-handling-in-hv_fcopy_daemon.patch
+ patches.suse/msft-hv-1442-Drivers-hv-vmbus-Fix-rescind-handling-issues.patch
patches.suse/suse-hv-guest-os-id.patch
patches.suse/suse-hv-kvp_on_msg.dbg.patch