mirror of
https://github.com/linuxkit/linuxkit.git
synced 2025-07-19 09:16:29 +00:00
kernel: Add patches to fix VMBus channel ID re-use
On some hv_sock workloads which quickly open/close many connections occasionally, channel IDs would get re-used while still having work pending. This can cause a kernel crash on a NULL pointer exception. The three patches added to the 4.9.x and 4.10.x kernels fixes these bugs. The patches are being prepared to be upstreamed, but for now we cherry-picked them from the developers tree. Signed-off-by: Rolf Neugebauer <rolf.neugebauer@docker.com>
This commit is contained in:
parent
eaef1ca8fb
commit
87c4092b26
@ -1,7 +1,7 @@
|
||||
From f8892ad868fdcd96ccf6edc93ed61d8a97af88e4 Mon Sep 17 00:00:00 2001
|
||||
From: Dexuan Cui <decui@microsoft.com>
|
||||
Date: Thu, 21 Jul 2016 16:04:38 -0600
|
||||
Subject: [PATCH 1/3] hv_sock: introduce Hyper-V Sockets
|
||||
Subject: [PATCH 1/6] hv_sock: introduce Hyper-V Sockets
|
||||
|
||||
Hyper-V Sockets (hv_sock) supplies a byte-stream based communication
|
||||
mechanism between the host and the guest. It's somewhat like TCP over
|
||||
|
@ -1,7 +1,7 @@
|
||||
From 268b402c42c140328224ff994d1d76053f3113f9 Mon Sep 17 00:00:00 2001
|
||||
From: Alex Ng <alexng@messages.microsoft.com>
|
||||
Date: Sat, 28 Jan 2017 12:37:17 -0700
|
||||
Subject: [PATCH 2/3] Drivers: hv: vmbus: Use all supported IC versions to
|
||||
Subject: [PATCH 2/6] Drivers: hv: vmbus: Use all supported IC versions to
|
||||
negotiate
|
||||
|
||||
Previously, we were assuming that each IC protocol version was tied to a
|
||||
|
@ -1,7 +1,7 @@
|
||||
From 1dc474194b72f224081c90311887317415f987dc Mon Sep 17 00:00:00 2001
|
||||
From: Alex Ng <alexng@messages.microsoft.com>
|
||||
Date: Sat, 28 Jan 2017 12:37:18 -0700
|
||||
Subject: [PATCH 3/3] Drivers: hv: Log the negotiated IC versions.
|
||||
Subject: [PATCH 3/6] Drivers: hv: Log the negotiated IC versions.
|
||||
|
||||
Log the negotiated IC versions.
|
||||
|
||||
|
@ -0,0 +1,56 @@
|
||||
From 686f341e764920ada0163bedf354924250ed32d8 Mon Sep 17 00:00:00 2001
|
||||
From: Dexuan Cui <decui@microsoft.com>
|
||||
Date: Sun, 26 Mar 2017 16:42:20 +0800
|
||||
Subject: [PATCH 4/6] vmbus: fix missed ring events on boot
|
||||
|
||||
During initialization, the channel initialization code schedules the
|
||||
tasklet to scan the VMBUS receive event page (i.e. simulates an
|
||||
interrupt). The problem was that it invokes the tasklet on a different
|
||||
CPU from where it normally runs and therefore if an event is present,
|
||||
it will clear the bit but not find the associated channel.
|
||||
|
||||
This can lead to missed events, typically stuck tasks, during bootup
|
||||
when sub channels are being initialized. Typically seen as stuck
|
||||
boot with 8 or more CPU's.
|
||||
|
||||
This patch is not necessary for upstream (4.11 and later) since
|
||||
commit 631e63a9f346 ("vmbus: change to per channel tasklet").
|
||||
This changed vmbus code to get rid of common tasklet which
|
||||
caused the problem.
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Fixes: 638fea33aee8 ("Drivers: hv: vmbus: fix the race when querying & updating the percpu list")
|
||||
Signed-off-by: Stephen Hemminger <sthemmin@microsoft.com>
|
||||
Origin: git@github.com:dcui/linux.git
|
||||
(cherry picked from commit 5cf3a72a111cecc7da759542c56560ce509159d7)
|
||||
---
|
||||
drivers/hv/channel_mgmt.c | 13 +++++++++++--
|
||||
1 file changed, 11 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
|
||||
index feca5d2e7b25..3fda63bf60ab 100644
|
||||
--- a/drivers/hv/channel_mgmt.c
|
||||
+++ b/drivers/hv/channel_mgmt.c
|
||||
@@ -389,8 +389,17 @@ void hv_event_tasklet_enable(struct vmbus_channel *channel)
|
||||
tasklet = hv_context.event_dpc[channel->target_cpu];
|
||||
tasklet_enable(tasklet);
|
||||
|
||||
- /* In case there is any pending event */
|
||||
- tasklet_schedule(tasklet);
|
||||
+ /*
|
||||
+ * In case there is any pending event schedule a rescan
|
||||
+ * but must be on the correct CPU for the channel.
|
||||
+ */
|
||||
+ if (channel->target_cpu == get_cpu())
|
||||
+ tasklet_schedule(tasklet);
|
||||
+ else
|
||||
+ smp_call_function_single(channel->target_cpu,
|
||||
+ (smp_call_func_t)tasklet_schedule,
|
||||
+ tasklet, false);
|
||||
+ put_cpu();
|
||||
}
|
||||
|
||||
void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid)
|
||||
--
|
||||
2.11.0
|
||||
|
@ -0,0 +1,59 @@
|
||||
From e3de49b1a6a80b33f792caf62cc33048dcbaed91 Mon Sep 17 00:00:00 2001
|
||||
From: Dexuan Cui <decui@microsoft.com>
|
||||
Date: Wed, 29 Mar 2017 18:37:10 +0800
|
||||
Subject: [PATCH 5/6] vmbus: remove "goto error_clean_msglist" in vmbus_open()
|
||||
|
||||
This is just a cleanup patch to simplify the code a little.
|
||||
No semantic change.
|
||||
|
||||
Signed-off-by: Dexuan Cui <decui@microsoft.com>
|
||||
Origin: git@github.com:dcui/linux.git
|
||||
(cherry picked from commit 2c89f21cbdfd39299482cd6068094097a45f13b3)
|
||||
---
|
||||
drivers/hv/channel.c | 18 +++++++-----------
|
||||
1 file changed, 7 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
|
||||
index 1606e7f08f4b..1caed01954f6 100644
|
||||
--- a/drivers/hv/channel.c
|
||||
+++ b/drivers/hv/channel.c
|
||||
@@ -184,17 +184,18 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
|
||||
ret = vmbus_post_msg(open_msg,
|
||||
sizeof(struct vmbus_channel_open_channel), true);
|
||||
|
||||
- if (ret != 0) {
|
||||
- err = ret;
|
||||
- goto error_clean_msglist;
|
||||
- }
|
||||
-
|
||||
- wait_for_completion(&open_info->waitevent);
|
||||
+ if (ret == 0)
|
||||
+ wait_for_completion(&open_info->waitevent);
|
||||
|
||||
spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
|
||||
list_del(&open_info->msglistentry);
|
||||
spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
|
||||
|
||||
+ if (ret != 0) {
|
||||
+ err = ret;
|
||||
+ goto error_free_gpadl;
|
||||
+ }
|
||||
+
|
||||
if (newchannel->rescind) {
|
||||
err = -ENODEV;
|
||||
goto error_free_gpadl;
|
||||
@@ -209,11 +210,6 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
|
||||
kfree(open_info);
|
||||
return 0;
|
||||
|
||||
-error_clean_msglist:
|
||||
- spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
|
||||
- list_del(&open_info->msglistentry);
|
||||
- spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
|
||||
-
|
||||
error_free_gpadl:
|
||||
vmbus_teardown_gpadl(newchannel, newchannel->ringbuffer_gpadlhandle);
|
||||
kfree(open_info);
|
||||
--
|
||||
2.11.0
|
||||
|
@ -0,0 +1,177 @@
|
||||
From e609da809e493b72eb28c0ad215edea8ddf54fb5 Mon Sep 17 00:00:00 2001
|
||||
From: Dexuan Cui <decui@microsoft.com>
|
||||
Date: Fri, 24 Mar 2017 20:53:18 +0800
|
||||
Subject: [PATCH 6/6] vmbus: dynamically enqueue/dequeue the channel on
|
||||
vmbus_open/close
|
||||
|
||||
Signed-off-by: Dexuan Cui <decui@microsoft.com>
|
||||
Origin: git@github.com:dcui/linux.git
|
||||
(cherry picked from commit bee4910daa4aed57ce60d2e2350e3cc120c383ca)
|
||||
---
|
||||
drivers/hv/channel.c | 16 ++++++++++---
|
||||
drivers/hv/channel_mgmt.c | 58 ++++++++++++++++++++---------------------------
|
||||
include/linux/hyperv.h | 3 +++
|
||||
3 files changed, 40 insertions(+), 37 deletions(-)
|
||||
|
||||
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
|
||||
index 1caed01954f6..5bbcc964dbf7 100644
|
||||
--- a/drivers/hv/channel.c
|
||||
+++ b/drivers/hv/channel.c
|
||||
@@ -181,6 +181,10 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
|
||||
&vmbus_connection.chn_msg_list);
|
||||
spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
|
||||
|
||||
+ hv_event_tasklet_disable(newchannel);
|
||||
+ hv_percpu_channel_enq(newchannel);
|
||||
+ hv_event_tasklet_enable(newchannel);
|
||||
+
|
||||
ret = vmbus_post_msg(open_msg,
|
||||
sizeof(struct vmbus_channel_open_channel), true);
|
||||
|
||||
@@ -193,23 +197,27 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
|
||||
|
||||
if (ret != 0) {
|
||||
err = ret;
|
||||
- goto error_free_gpadl;
|
||||
+ goto error_deq_channel;
|
||||
}
|
||||
|
||||
if (newchannel->rescind) {
|
||||
err = -ENODEV;
|
||||
- goto error_free_gpadl;
|
||||
+ goto error_deq_channel;
|
||||
}
|
||||
|
||||
if (open_info->response.open_result.status) {
|
||||
err = -EAGAIN;
|
||||
- goto error_free_gpadl;
|
||||
+ goto error_deq_channel;
|
||||
}
|
||||
|
||||
newchannel->state = CHANNEL_OPENED_STATE;
|
||||
kfree(open_info);
|
||||
return 0;
|
||||
|
||||
+error_deq_channel:
|
||||
+ hv_event_tasklet_disable(newchannel);
|
||||
+ hv_percpu_channel_deq(newchannel);
|
||||
+ hv_event_tasklet_enable(newchannel);
|
||||
error_free_gpadl:
|
||||
vmbus_teardown_gpadl(newchannel, newchannel->ringbuffer_gpadlhandle);
|
||||
kfree(open_info);
|
||||
@@ -555,6 +563,8 @@ static int vmbus_close_internal(struct vmbus_channel *channel)
|
||||
goto out;
|
||||
}
|
||||
|
||||
+ hv_percpu_channel_deq(channel);
|
||||
+
|
||||
channel->state = CHANNEL_OPEN_STATE;
|
||||
channel->sc_creation_callback = NULL;
|
||||
/* Stop callback and cancel the timer asap */
|
||||
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
|
||||
index 3fda63bf60ab..e2fbfa290f1c 100644
|
||||
--- a/drivers/hv/channel_mgmt.c
|
||||
+++ b/drivers/hv/channel_mgmt.c
|
||||
@@ -376,6 +376,30 @@ static void vmbus_release_relid(u32 relid)
|
||||
true);
|
||||
}
|
||||
|
||||
+void hv_percpu_channel_enq(struct vmbus_channel *channel)
|
||||
+{
|
||||
+ if (channel->target_cpu != get_cpu())
|
||||
+ smp_call_function_single(channel->target_cpu,
|
||||
+ percpu_channel_enq,
|
||||
+ channel, true);
|
||||
+ else
|
||||
+ percpu_channel_enq(channel);
|
||||
+ put_cpu();
|
||||
+
|
||||
+}
|
||||
+
|
||||
+void hv_percpu_channel_deq(struct vmbus_channel *channel)
|
||||
+{
|
||||
+ if (channel->target_cpu != get_cpu())
|
||||
+ smp_call_function_single(channel->target_cpu,
|
||||
+ percpu_channel_deq,
|
||||
+ channel, true);
|
||||
+ else
|
||||
+ percpu_channel_deq(channel);
|
||||
+ put_cpu();
|
||||
+
|
||||
+}
|
||||
+
|
||||
void hv_event_tasklet_disable(struct vmbus_channel *channel)
|
||||
{
|
||||
struct tasklet_struct *tasklet;
|
||||
@@ -410,17 +434,6 @@ void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid)
|
||||
BUG_ON(!channel->rescind);
|
||||
BUG_ON(!mutex_is_locked(&vmbus_connection.channel_mutex));
|
||||
|
||||
- hv_event_tasklet_disable(channel);
|
||||
- if (channel->target_cpu != get_cpu()) {
|
||||
- put_cpu();
|
||||
- smp_call_function_single(channel->target_cpu,
|
||||
- percpu_channel_deq, channel, true);
|
||||
- } else {
|
||||
- percpu_channel_deq(channel);
|
||||
- put_cpu();
|
||||
- }
|
||||
- hv_event_tasklet_enable(channel);
|
||||
-
|
||||
if (channel->primary_channel == NULL) {
|
||||
list_del(&channel->listentry);
|
||||
|
||||
@@ -513,18 +526,6 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
|
||||
|
||||
init_vp_index(newchannel, dev_type);
|
||||
|
||||
- hv_event_tasklet_disable(newchannel);
|
||||
- if (newchannel->target_cpu != get_cpu()) {
|
||||
- put_cpu();
|
||||
- smp_call_function_single(newchannel->target_cpu,
|
||||
- percpu_channel_enq,
|
||||
- newchannel, true);
|
||||
- } else {
|
||||
- percpu_channel_enq(newchannel);
|
||||
- put_cpu();
|
||||
- }
|
||||
- hv_event_tasklet_enable(newchannel);
|
||||
-
|
||||
/*
|
||||
* This state is used to indicate a successful open
|
||||
* so that when we do close the channel normally, we
|
||||
@@ -573,17 +574,6 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
|
||||
list_del(&newchannel->listentry);
|
||||
mutex_unlock(&vmbus_connection.channel_mutex);
|
||||
|
||||
- hv_event_tasklet_disable(newchannel);
|
||||
- if (newchannel->target_cpu != get_cpu()) {
|
||||
- put_cpu();
|
||||
- smp_call_function_single(newchannel->target_cpu,
|
||||
- percpu_channel_deq, newchannel, true);
|
||||
- } else {
|
||||
- percpu_channel_deq(newchannel);
|
||||
- put_cpu();
|
||||
- }
|
||||
- hv_event_tasklet_enable(newchannel);
|
||||
-
|
||||
vmbus_release_relid(newchannel->offermsg.child_relid);
|
||||
|
||||
err_free_chan:
|
||||
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
|
||||
index 41e5ed87f833..0792d16f4b3e 100644
|
||||
--- a/include/linux/hyperv.h
|
||||
+++ b/include/linux/hyperv.h
|
||||
@@ -1467,6 +1467,9 @@ extern bool vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, u8 *buf,
|
||||
void hv_event_tasklet_disable(struct vmbus_channel *channel);
|
||||
void hv_event_tasklet_enable(struct vmbus_channel *channel);
|
||||
|
||||
+void hv_percpu_channel_enq(struct vmbus_channel *channel);
|
||||
+void hv_percpu_channel_deq(struct vmbus_channel *channel);
|
||||
+
|
||||
void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid);
|
||||
|
||||
void vmbus_setevent(struct vmbus_channel *channel);
|
||||
--
|
||||
2.11.0
|
||||
|
@ -1,7 +1,7 @@
|
||||
From 687435d249d10985e1c6d6d6cc143e8004e8b976 Mon Sep 17 00:00:00 2001
|
||||
From: Dexuan Cui <decui@microsoft.com>
|
||||
Date: Sat, 23 Jul 2016 01:35:51 +0000
|
||||
Subject: [PATCH 1/7] hv_sock: introduce Hyper-V Sockets
|
||||
Subject: [PATCH 01/10] hv_sock: introduce Hyper-V Sockets
|
||||
|
||||
Hyper-V Sockets (hv_sock) supplies a byte-stream based communication
|
||||
mechanism between the host and the guest. It's somewhat like TCP over
|
||||
|
@ -1,7 +1,7 @@
|
||||
From 554ba8b0c4d9aa719d239b2f97eb59075c6c33d9 Mon Sep 17 00:00:00 2001
|
||||
From: Rolf Neugebauer <rolf.neugebauer@gmail.com>
|
||||
Date: Mon, 23 May 2016 18:55:45 +0100
|
||||
Subject: [PATCH 2/7] vmbus: Don't spam the logs with unknown GUIDs
|
||||
Subject: [PATCH 02/10] vmbus: Don't spam the logs with unknown GUIDs
|
||||
|
||||
With Hyper-V sockets device types are introduced on the fly. The pr_info()
|
||||
then prints a message on every connection, which is way too verbose. Since
|
||||
|
@ -1,8 +1,8 @@
|
||||
From a9c848779876b7b98a6c588494cd20010894fbf1 Mon Sep 17 00:00:00 2001
|
||||
From: Alex Ng <alexng@messages.microsoft.com>
|
||||
Date: Sun, 6 Nov 2016 13:14:07 -0800
|
||||
Subject: [PATCH 3/7] Drivers: hv: utils: Fix the mapping between host version
|
||||
and protocol to use
|
||||
Subject: [PATCH 03/10] Drivers: hv: utils: Fix the mapping between host
|
||||
version and protocol to use
|
||||
|
||||
We should intentionally declare the protocols to use for every known host
|
||||
and default to using the latest protocol if the host is unknown or new.
|
||||
|
@ -1,7 +1,7 @@
|
||||
From ccab2062a98a38bd5ff2d57e184229345ff057ff Mon Sep 17 00:00:00 2001
|
||||
From: Alex Ng <alexng@messages.microsoft.com>
|
||||
Date: Sun, 6 Nov 2016 13:14:10 -0800
|
||||
Subject: [PATCH 4/7] Drivers: hv: vss: Improve log messages.
|
||||
Subject: [PATCH 04/10] Drivers: hv: vss: Improve log messages.
|
||||
|
||||
Adding log messages to help troubleshoot error cases and transaction
|
||||
handling.
|
||||
|
@ -1,7 +1,7 @@
|
||||
From d303deabd611b45b7574015c06ad2d7408235e77 Mon Sep 17 00:00:00 2001
|
||||
From: Alex Ng <alexng@messages.microsoft.com>
|
||||
Date: Sun, 6 Nov 2016 13:14:11 -0800
|
||||
Subject: [PATCH 5/7] Drivers: hv: vss: Operation timeouts should match host
|
||||
Subject: [PATCH 05/10] Drivers: hv: vss: Operation timeouts should match host
|
||||
expectation
|
||||
|
||||
Increase the timeout of backup operations. When system is under I/O load,
|
||||
|
@ -1,7 +1,7 @@
|
||||
From bd8b51edd59a3326bf6457fd939e5503ff3f8efb Mon Sep 17 00:00:00 2001
|
||||
From: Alex Ng <alexng@messages.microsoft.com>
|
||||
Date: Sat, 28 Jan 2017 12:37:17 -0700
|
||||
Subject: [PATCH 6/7] Drivers: hv: vmbus: Use all supported IC versions to
|
||||
Subject: [PATCH 06/10] Drivers: hv: vmbus: Use all supported IC versions to
|
||||
negotiate
|
||||
|
||||
Previously, we were assuming that each IC protocol version was tied to a
|
||||
|
@ -1,7 +1,7 @@
|
||||
From d692ce39b600298e6c60481d46c284c3c1bf975f Mon Sep 17 00:00:00 2001
|
||||
From: Alex Ng <alexng@messages.microsoft.com>
|
||||
Date: Sat, 28 Jan 2017 12:37:18 -0700
|
||||
Subject: [PATCH 7/7] Drivers: hv: Log the negotiated IC versions.
|
||||
Subject: [PATCH 07/10] Drivers: hv: Log the negotiated IC versions.
|
||||
|
||||
Log the negotiated IC versions.
|
||||
|
||||
|
@ -0,0 +1,56 @@
|
||||
From c68a516460f877753f6617d81455f42911d4bf66 Mon Sep 17 00:00:00 2001
|
||||
From: Dexuan Cui <decui@microsoft.com>
|
||||
Date: Sun, 26 Mar 2017 16:42:20 +0800
|
||||
Subject: [PATCH 08/10] vmbus: fix missed ring events on boot
|
||||
|
||||
During initialization, the channel initialization code schedules the
|
||||
tasklet to scan the VMBUS receive event page (i.e. simulates an
|
||||
interrupt). The problem was that it invokes the tasklet on a different
|
||||
CPU from where it normally runs and therefore if an event is present,
|
||||
it will clear the bit but not find the associated channel.
|
||||
|
||||
This can lead to missed events, typically stuck tasks, during bootup
|
||||
when sub channels are being initialized. Typically seen as stuck
|
||||
boot with 8 or more CPU's.
|
||||
|
||||
This patch is not necessary for upstream (4.11 and later) since
|
||||
commit 631e63a9f346 ("vmbus: change to per channel tasklet").
|
||||
This changed vmbus code to get rid of common tasklet which
|
||||
caused the problem.
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Fixes: 638fea33aee8 ("Drivers: hv: vmbus: fix the race when querying & updating the percpu list")
|
||||
Signed-off-by: Stephen Hemminger <sthemmin@microsoft.com>
|
||||
Origin: git@github.com:dcui/linux.git
|
||||
(cherry picked from commit 5cf3a72a111cecc7da759542c56560ce509159d7)
|
||||
---
|
||||
drivers/hv/channel_mgmt.c | 13 +++++++++++--
|
||||
1 file changed, 11 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
|
||||
index e7949b64bfbc..2fe024e86209 100644
|
||||
--- a/drivers/hv/channel_mgmt.c
|
||||
+++ b/drivers/hv/channel_mgmt.c
|
||||
@@ -388,8 +388,17 @@ void hv_event_tasklet_enable(struct vmbus_channel *channel)
|
||||
tasklet = hv_context.event_dpc[channel->target_cpu];
|
||||
tasklet_enable(tasklet);
|
||||
|
||||
- /* In case there is any pending event */
|
||||
- tasklet_schedule(tasklet);
|
||||
+ /*
|
||||
+ * In case there is any pending event schedule a rescan
|
||||
+ * but must be on the correct CPU for the channel.
|
||||
+ */
|
||||
+ if (channel->target_cpu == get_cpu())
|
||||
+ tasklet_schedule(tasklet);
|
||||
+ else
|
||||
+ smp_call_function_single(channel->target_cpu,
|
||||
+ (smp_call_func_t)tasklet_schedule,
|
||||
+ tasklet, false);
|
||||
+ put_cpu();
|
||||
}
|
||||
|
||||
void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid)
|
||||
--
|
||||
2.11.0
|
||||
|
@ -0,0 +1,60 @@
|
||||
From 55ddc3b37ec5d311e5fff71cacb224d5c87803f3 Mon Sep 17 00:00:00 2001
|
||||
From: Dexuan Cui <decui@microsoft.com>
|
||||
Date: Wed, 29 Mar 2017 18:37:10 +0800
|
||||
Subject: [PATCH 09/10] vmbus: remove "goto error_clean_msglist" in
|
||||
vmbus_open()
|
||||
|
||||
This is just a cleanup patch to simplify the code a little.
|
||||
No semantic change.
|
||||
|
||||
Signed-off-by: Dexuan Cui <decui@microsoft.com>
|
||||
Origin: git@github.com:dcui/linux.git
|
||||
(cherry picked from commit 2c89f21cbdfd39299482cd6068094097a45f13b3)
|
||||
---
|
||||
drivers/hv/channel.c | 18 +++++++-----------
|
||||
1 file changed, 7 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
|
||||
index 1606e7f08f4b..1caed01954f6 100644
|
||||
--- a/drivers/hv/channel.c
|
||||
+++ b/drivers/hv/channel.c
|
||||
@@ -184,17 +184,18 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
|
||||
ret = vmbus_post_msg(open_msg,
|
||||
sizeof(struct vmbus_channel_open_channel), true);
|
||||
|
||||
- if (ret != 0) {
|
||||
- err = ret;
|
||||
- goto error_clean_msglist;
|
||||
- }
|
||||
-
|
||||
- wait_for_completion(&open_info->waitevent);
|
||||
+ if (ret == 0)
|
||||
+ wait_for_completion(&open_info->waitevent);
|
||||
|
||||
spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
|
||||
list_del(&open_info->msglistentry);
|
||||
spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
|
||||
|
||||
+ if (ret != 0) {
|
||||
+ err = ret;
|
||||
+ goto error_free_gpadl;
|
||||
+ }
|
||||
+
|
||||
if (newchannel->rescind) {
|
||||
err = -ENODEV;
|
||||
goto error_free_gpadl;
|
||||
@@ -209,11 +210,6 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
|
||||
kfree(open_info);
|
||||
return 0;
|
||||
|
||||
-error_clean_msglist:
|
||||
- spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
|
||||
- list_del(&open_info->msglistentry);
|
||||
- spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
|
||||
-
|
||||
error_free_gpadl:
|
||||
vmbus_teardown_gpadl(newchannel, newchannel->ringbuffer_gpadlhandle);
|
||||
kfree(open_info);
|
||||
--
|
||||
2.11.0
|
||||
|
@ -0,0 +1,177 @@
|
||||
From 83ba0bff619dc73f2aa6385ed3e039bb7641550a Mon Sep 17 00:00:00 2001
|
||||
From: Dexuan Cui <decui@microsoft.com>
|
||||
Date: Fri, 24 Mar 2017 20:53:18 +0800
|
||||
Subject: [PATCH 10/10] vmbus: dynamically enqueue/dequeue the channel on
|
||||
vmbus_open/close
|
||||
|
||||
Signed-off-by: Dexuan Cui <decui@microsoft.com>
|
||||
Origin: git@github.com:dcui/linux.git
|
||||
(cherry picked from commit bee4910daa4aed57ce60d2e2350e3cc120c383ca)
|
||||
---
|
||||
drivers/hv/channel.c | 16 ++++++++++---
|
||||
drivers/hv/channel_mgmt.c | 58 ++++++++++++++++++++---------------------------
|
||||
include/linux/hyperv.h | 3 +++
|
||||
3 files changed, 40 insertions(+), 37 deletions(-)
|
||||
|
||||
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
|
||||
index 1caed01954f6..5bbcc964dbf7 100644
|
||||
--- a/drivers/hv/channel.c
|
||||
+++ b/drivers/hv/channel.c
|
||||
@@ -181,6 +181,10 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
|
||||
&vmbus_connection.chn_msg_list);
|
||||
spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
|
||||
|
||||
+ hv_event_tasklet_disable(newchannel);
|
||||
+ hv_percpu_channel_enq(newchannel);
|
||||
+ hv_event_tasklet_enable(newchannel);
|
||||
+
|
||||
ret = vmbus_post_msg(open_msg,
|
||||
sizeof(struct vmbus_channel_open_channel), true);
|
||||
|
||||
@@ -193,23 +197,27 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
|
||||
|
||||
if (ret != 0) {
|
||||
err = ret;
|
||||
- goto error_free_gpadl;
|
||||
+ goto error_deq_channel;
|
||||
}
|
||||
|
||||
if (newchannel->rescind) {
|
||||
err = -ENODEV;
|
||||
- goto error_free_gpadl;
|
||||
+ goto error_deq_channel;
|
||||
}
|
||||
|
||||
if (open_info->response.open_result.status) {
|
||||
err = -EAGAIN;
|
||||
- goto error_free_gpadl;
|
||||
+ goto error_deq_channel;
|
||||
}
|
||||
|
||||
newchannel->state = CHANNEL_OPENED_STATE;
|
||||
kfree(open_info);
|
||||
return 0;
|
||||
|
||||
+error_deq_channel:
|
||||
+ hv_event_tasklet_disable(newchannel);
|
||||
+ hv_percpu_channel_deq(newchannel);
|
||||
+ hv_event_tasklet_enable(newchannel);
|
||||
error_free_gpadl:
|
||||
vmbus_teardown_gpadl(newchannel, newchannel->ringbuffer_gpadlhandle);
|
||||
kfree(open_info);
|
||||
@@ -555,6 +563,8 @@ static int vmbus_close_internal(struct vmbus_channel *channel)
|
||||
goto out;
|
||||
}
|
||||
|
||||
+ hv_percpu_channel_deq(channel);
|
||||
+
|
||||
channel->state = CHANNEL_OPEN_STATE;
|
||||
channel->sc_creation_callback = NULL;
|
||||
/* Stop callback and cancel the timer asap */
|
||||
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
|
||||
index 2fe024e86209..b2bdcfb49144 100644
|
||||
--- a/drivers/hv/channel_mgmt.c
|
||||
+++ b/drivers/hv/channel_mgmt.c
|
||||
@@ -375,6 +375,30 @@ static void vmbus_release_relid(u32 relid)
|
||||
true);
|
||||
}
|
||||
|
||||
+void hv_percpu_channel_enq(struct vmbus_channel *channel)
|
||||
+{
|
||||
+ if (channel->target_cpu != get_cpu())
|
||||
+ smp_call_function_single(channel->target_cpu,
|
||||
+ percpu_channel_enq,
|
||||
+ channel, true);
|
||||
+ else
|
||||
+ percpu_channel_enq(channel);
|
||||
+ put_cpu();
|
||||
+
|
||||
+}
|
||||
+
|
||||
+void hv_percpu_channel_deq(struct vmbus_channel *channel)
|
||||
+{
|
||||
+ if (channel->target_cpu != get_cpu())
|
||||
+ smp_call_function_single(channel->target_cpu,
|
||||
+ percpu_channel_deq,
|
||||
+ channel, true);
|
||||
+ else
|
||||
+ percpu_channel_deq(channel);
|
||||
+ put_cpu();
|
||||
+
|
||||
+}
|
||||
+
|
||||
void hv_event_tasklet_disable(struct vmbus_channel *channel)
|
||||
{
|
||||
struct tasklet_struct *tasklet;
|
||||
@@ -409,17 +433,6 @@ void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid)
|
||||
BUG_ON(!channel->rescind);
|
||||
BUG_ON(!mutex_is_locked(&vmbus_connection.channel_mutex));
|
||||
|
||||
- hv_event_tasklet_disable(channel);
|
||||
- if (channel->target_cpu != get_cpu()) {
|
||||
- put_cpu();
|
||||
- smp_call_function_single(channel->target_cpu,
|
||||
- percpu_channel_deq, channel, true);
|
||||
- } else {
|
||||
- percpu_channel_deq(channel);
|
||||
- put_cpu();
|
||||
- }
|
||||
- hv_event_tasklet_enable(channel);
|
||||
-
|
||||
if (channel->primary_channel == NULL) {
|
||||
list_del(&channel->listentry);
|
||||
|
||||
@@ -512,18 +525,6 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
|
||||
|
||||
init_vp_index(newchannel, dev_type);
|
||||
|
||||
- hv_event_tasklet_disable(newchannel);
|
||||
- if (newchannel->target_cpu != get_cpu()) {
|
||||
- put_cpu();
|
||||
- smp_call_function_single(newchannel->target_cpu,
|
||||
- percpu_channel_enq,
|
||||
- newchannel, true);
|
||||
- } else {
|
||||
- percpu_channel_enq(newchannel);
|
||||
- put_cpu();
|
||||
- }
|
||||
- hv_event_tasklet_enable(newchannel);
|
||||
-
|
||||
/*
|
||||
* This state is used to indicate a successful open
|
||||
* so that when we do close the channel normally, we
|
||||
@@ -572,17 +573,6 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
|
||||
list_del(&newchannel->listentry);
|
||||
mutex_unlock(&vmbus_connection.channel_mutex);
|
||||
|
||||
- hv_event_tasklet_disable(newchannel);
|
||||
- if (newchannel->target_cpu != get_cpu()) {
|
||||
- put_cpu();
|
||||
- smp_call_function_single(newchannel->target_cpu,
|
||||
- percpu_channel_deq, newchannel, true);
|
||||
- } else {
|
||||
- percpu_channel_deq(newchannel);
|
||||
- put_cpu();
|
||||
- }
|
||||
- hv_event_tasklet_enable(newchannel);
|
||||
-
|
||||
vmbus_release_relid(newchannel->offermsg.child_relid);
|
||||
|
||||
err_free_chan:
|
||||
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
|
||||
index 956acfc93487..9ee292b28e41 100644
|
||||
--- a/include/linux/hyperv.h
|
||||
+++ b/include/linux/hyperv.h
|
||||
@@ -1461,6 +1461,9 @@ extern bool vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, u8 *buf,
|
||||
void hv_event_tasklet_disable(struct vmbus_channel *channel);
|
||||
void hv_event_tasklet_enable(struct vmbus_channel *channel);
|
||||
|
||||
+void hv_percpu_channel_enq(struct vmbus_channel *channel);
|
||||
+void hv_percpu_channel_deq(struct vmbus_channel *channel);
|
||||
+
|
||||
void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid);
|
||||
|
||||
void vmbus_setevent(struct vmbus_channel *channel);
|
||||
--
|
||||
2.11.0
|
||||
|
Loading…
Reference in New Issue
Block a user