From: Greg Kroah-Hartman Date: Thu, 18 Oct 2018 17:13:29 +0000 (+0200) Subject: 4.4-stable patches X-Git-Tag: v4.18.16~3 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4961f96f7aab69800418546d0f5bfcacb3024882;p=thirdparty%2Fkernel%2Fstable-queue.git 4.4-stable patches added patches: drivers-hv-kvp-fix-ip-failover.patch drivers-hv-util-pass-the-channel-information-during-the-init-call.patch drivers-hv-utils-invoke-the-poll-function-after-handshake.patch hv-properly-delay-kvp-packets-when-negotiation-is-in-progress.patch --- diff --git a/queue-4.4/drivers-hv-kvp-fix-ip-failover.patch b/queue-4.4/drivers-hv-kvp-fix-ip-failover.patch new file mode 100644 index 00000000000..7d4abfbfe33 --- /dev/null +++ b/queue-4.4/drivers-hv-kvp-fix-ip-failover.patch @@ -0,0 +1,131 @@ +From 4dbfc2e68004c60edab7e8fd26784383dd3ee9bc Mon Sep 17 00:00:00 2001 +From: Vitaly Kuznetsov +Date: Sat, 30 Apr 2016 19:21:33 -0700 +Subject: Drivers: hv: kvp: fix IP Failover + +From: Vitaly Kuznetsov + +commit 4dbfc2e68004c60edab7e8fd26784383dd3ee9bc upstream. + +Hyper-V VMs can be replicated to another hosts and there is a feature to +set different IP for replicas, it is called 'Failover TCP/IP'. When +such guest starts Hyper-V host sends it KVP_OP_SET_IP_INFO message as soon +as we finish negotiation procedure. The problem is that it can happen (and +it actually happens) before userspace daemon connects and we reply with +HV_E_FAIL to the message. As there are no repetitions we fail to set the +requested IP. + +Solve the issue by postponing our reply to the negotiation message till +userspace daemon is connected. We can't wait too long as there is a +host-side timeout (cca. 75 seconds) and if we fail to reply in this time +frame the whole KVP service will become inactive. The solution is not +ideal - if it takes userspace daemon more than 60 seconds to connect +IP Failover will still fail but I don't see a solution with our current +separation between kernel and userspace parts. + +Other two modules (VSS and FCOPY) don't require such delay, leave them +untouched. + +Signed-off-by: Vitaly Kuznetsov +Signed-off-by: K. Y. Srinivasan +Signed-off-by: Dexuan Cui +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hv/hv_kvp.c | 31 +++++++++++++++++++++++++++++++ + drivers/hv/hyperv_vmbus.h | 5 +++++ + 2 files changed, 36 insertions(+) + +--- a/drivers/hv/hv_kvp.c ++++ b/drivers/hv/hv_kvp.c +@@ -78,9 +78,11 @@ static void kvp_send_key(struct work_str + + static void kvp_respond_to_host(struct hv_kvp_msg *msg, int error); + static void kvp_timeout_func(struct work_struct *dummy); ++static void kvp_host_handshake_func(struct work_struct *dummy); + static void kvp_register(int); + + static DECLARE_DELAYED_WORK(kvp_timeout_work, kvp_timeout_func); ++static DECLARE_DELAYED_WORK(kvp_host_handshake_work, kvp_host_handshake_func); + static DECLARE_WORK(kvp_sendkey_work, kvp_send_key); + + static const char kvp_devname[] = "vmbus/hv_kvp"; +@@ -131,6 +133,11 @@ static void kvp_timeout_func(struct work + hv_poll_channel(kvp_transaction.recv_channel, kvp_poll_wrapper); + } + ++static void kvp_host_handshake_func(struct work_struct *dummy) ++{ ++ hv_poll_channel(kvp_transaction.recv_channel, hv_kvp_onchannelcallback); ++} ++ + static int kvp_handle_handshake(struct hv_kvp_msg *msg) + { + switch (msg->kvp_hdr.operation) { +@@ -155,6 +162,12 @@ static int kvp_handle_handshake(struct h + pr_debug("KVP: userspace daemon ver. %d registered\n", + KVP_OP_REGISTER); + kvp_register(dm_reg_value); ++ ++ /* ++ * If we're still negotiating with the host cancel the timeout ++ * work to not poll the channel twice. ++ */ ++ cancel_delayed_work_sync(&kvp_host_handshake_work); + hv_poll_channel(kvp_transaction.recv_channel, kvp_poll_wrapper); + + return 0; +@@ -595,7 +608,22 @@ void hv_kvp_onchannelcallback(void *cont + struct icmsg_negotiate *negop = NULL; + int util_fw_version; + int kvp_srv_version; ++ static enum {NEGO_NOT_STARTED, ++ NEGO_IN_PROGRESS, ++ NEGO_FINISHED} host_negotiatied = NEGO_NOT_STARTED; + ++ if (host_negotiatied == NEGO_NOT_STARTED && ++ kvp_transaction.state < HVUTIL_READY) { ++ /* ++ * If userspace daemon is not connected and host is asking ++ * us to negotiate we need to delay to not lose messages. ++ * This is important for Failover IP setting. ++ */ ++ host_negotiatied = NEGO_IN_PROGRESS; ++ schedule_delayed_work(&kvp_host_handshake_work, ++ HV_UTIL_NEGO_TIMEOUT * HZ); ++ return; ++ } + if (kvp_transaction.state > HVUTIL_READY) + return; + +@@ -673,6 +701,8 @@ void hv_kvp_onchannelcallback(void *cont + vmbus_sendpacket(channel, recv_buffer, + recvlen, requestid, + VM_PKT_DATA_INBAND, 0); ++ ++ host_negotiatied = NEGO_FINISHED; + } + + } +@@ -711,6 +741,7 @@ hv_kvp_init(struct hv_util_service *srv) + void hv_kvp_deinit(void) + { + kvp_transaction.state = HVUTIL_DEVICE_DYING; ++ cancel_delayed_work_sync(&kvp_host_handshake_work); + cancel_delayed_work_sync(&kvp_timeout_work); + cancel_work_sync(&kvp_sendkey_work); + hvutil_transport_destroy(hvt); +--- a/drivers/hv/hyperv_vmbus.h ++++ b/drivers/hv/hyperv_vmbus.h +@@ -36,6 +36,11 @@ + #define HV_UTIL_TIMEOUT 30 + + /* ++ * Timeout for guest-host handshake for services. ++ */ ++#define HV_UTIL_NEGO_TIMEOUT 60 ++ ++/* + * The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent + * is set by CPUID(HVCPUID_VERSION_FEATURES). + */ diff --git a/queue-4.4/drivers-hv-util-pass-the-channel-information-during-the-init-call.patch b/queue-4.4/drivers-hv-util-pass-the-channel-information-during-the-init-call.patch new file mode 100644 index 00000000000..3def46ba4a7 --- /dev/null +++ b/queue-4.4/drivers-hv-util-pass-the-channel-information-during-the-init-call.patch @@ -0,0 +1,108 @@ +From b9830d120cbe155863399f25eaef6aa8353e767f Mon Sep 17 00:00:00 2001 +From: "K. Y. Srinivasan" +Date: Fri, 26 Feb 2016 15:13:19 -0800 +Subject: Drivers: hv: util: Pass the channel information during the init call + +From: K. Y. Srinivasan + +commit b9830d120cbe155863399f25eaef6aa8353e767f upstream. + +Pass the channel information to the util drivers that need to defer +reading the channel while they are processing a request. This would address +the following issue reported by Vitaly: + +Commit 3cace4a61610 ("Drivers: hv: utils: run polling callback always in +interrupt context") removed direct *_transaction.state = HVUTIL_READY +assignments from *_handle_handshake() functions introducing the following +race: if a userspace daemon connects before we get first non-negotiation +request from the server hv_poll_channel() won't set transaction state to +HVUTIL_READY as (!channel) condition will fail, we set it to non-NULL on +the first real request from the server. + +Signed-off-by: K. Y. Srinivasan +Reported-by: Vitaly Kuznetsov +Signed-off-by: Dexuan Cui +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hv/hv_fcopy.c | 2 +- + drivers/hv/hv_kvp.c | 2 +- + drivers/hv/hv_snapshot.c | 2 +- + drivers/hv/hv_util.c | 1 + + include/linux/hyperv.h | 1 + + 5 files changed, 5 insertions(+), 3 deletions(-) + +--- a/drivers/hv/hv_fcopy.c ++++ b/drivers/hv/hv_fcopy.c +@@ -256,7 +256,6 @@ void hv_fcopy_onchannelcallback(void *co + */ + + fcopy_transaction.recv_len = recvlen; +- fcopy_transaction.recv_channel = channel; + fcopy_transaction.recv_req_id = requestid; + fcopy_transaction.fcopy_msg = fcopy_msg; + +@@ -323,6 +322,7 @@ static void fcopy_on_reset(void) + int hv_fcopy_init(struct hv_util_service *srv) + { + recv_buffer = srv->recv_buffer; ++ fcopy_transaction.recv_channel = srv->channel; + + init_completion(&release_event); + /* +--- a/drivers/hv/hv_kvp.c ++++ b/drivers/hv/hv_kvp.c +@@ -640,7 +640,6 @@ void hv_kvp_onchannelcallback(void *cont + */ + + kvp_transaction.recv_len = recvlen; +- kvp_transaction.recv_channel = channel; + kvp_transaction.recv_req_id = requestid; + kvp_transaction.kvp_msg = kvp_msg; + +@@ -690,6 +689,7 @@ int + hv_kvp_init(struct hv_util_service *srv) + { + recv_buffer = srv->recv_buffer; ++ kvp_transaction.recv_channel = srv->channel; + + init_completion(&release_event); + /* +--- a/drivers/hv/hv_snapshot.c ++++ b/drivers/hv/hv_snapshot.c +@@ -264,7 +264,6 @@ void hv_vss_onchannelcallback(void *cont + */ + + vss_transaction.recv_len = recvlen; +- vss_transaction.recv_channel = channel; + vss_transaction.recv_req_id = requestid; + vss_transaction.msg = (struct hv_vss_msg *)vss_msg; + +@@ -340,6 +339,7 @@ hv_vss_init(struct hv_util_service *srv) + return -ENOTSUPP; + } + recv_buffer = srv->recv_buffer; ++ vss_transaction.recv_channel = srv->channel; + + /* + * When this driver loads, the user level daemon that +--- a/drivers/hv/hv_util.c ++++ b/drivers/hv/hv_util.c +@@ -326,6 +326,7 @@ static int util_probe(struct hv_device * + srv->recv_buffer = kmalloc(PAGE_SIZE * 4, GFP_KERNEL); + if (!srv->recv_buffer) + return -ENOMEM; ++ srv->channel = dev->channel; + if (srv->util_init) { + ret = srv->util_init(srv); + if (ret) { +--- a/include/linux/hyperv.h ++++ b/include/linux/hyperv.h +@@ -1179,6 +1179,7 @@ int vmbus_allocate_mmio(struct resource + + struct hv_util_service { + u8 *recv_buffer; ++ void *channel; + void (*util_cb)(void *); + int (*util_init)(struct hv_util_service *); + void (*util_deinit)(void); diff --git a/queue-4.4/drivers-hv-utils-invoke-the-poll-function-after-handshake.patch b/queue-4.4/drivers-hv-utils-invoke-the-poll-function-after-handshake.patch new file mode 100644 index 00000000000..9cd19778e99 --- /dev/null +++ b/queue-4.4/drivers-hv-utils-invoke-the-poll-function-after-handshake.patch @@ -0,0 +1,44 @@ +From 2d0c3b5ad739697a68dc8a444f5b9f4817cf8f8f Mon Sep 17 00:00:00 2001 +From: "K. Y. Srinivasan" +Date: Mon, 14 Dec 2015 16:01:57 -0800 +Subject: Drivers: hv: utils: Invoke the poll function after handshake + +From: K. Y. Srinivasan + +commit 2d0c3b5ad739697a68dc8a444f5b9f4817cf8f8f upstream. + +When the handshake with daemon is complete, we should poll the channel since +during the handshake, we will not be processing any messages. This is a +potential bug if the host is waiting for a response from the guest. +I would like to thank Dexuan for pointing this out. + +Signed-off-by: K. Y. Srinivasan +Signed-off-by: Dexuan Cui +Signed-off-by: Greg Kroah-Hartman +--- + drivers/hv/hv_kvp.c | 2 +- + drivers/hv/hv_snapshot.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/hv/hv_kvp.c ++++ b/drivers/hv/hv_kvp.c +@@ -155,7 +155,7 @@ static int kvp_handle_handshake(struct h + pr_debug("KVP: userspace daemon ver. %d registered\n", + KVP_OP_REGISTER); + kvp_register(dm_reg_value); +- kvp_transaction.state = HVUTIL_READY; ++ hv_poll_channel(kvp_transaction.recv_channel, kvp_poll_wrapper); + + return 0; + } +--- a/drivers/hv/hv_snapshot.c ++++ b/drivers/hv/hv_snapshot.c +@@ -114,7 +114,7 @@ static int vss_handle_handshake(struct h + default: + return -EINVAL; + } +- vss_transaction.state = HVUTIL_READY; ++ hv_poll_channel(vss_transaction.recv_channel, vss_poll_wrapper); + pr_debug("VSS: userspace daemon ver. %d registered\n", dm_reg_value); + return 0; + } diff --git a/queue-4.4/hv-properly-delay-kvp-packets-when-negotiation-is-in-progress.patch b/queue-4.4/hv-properly-delay-kvp-packets-when-negotiation-is-in-progress.patch new file mode 100644 index 00000000000..2125c7ac3a4 --- /dev/null +++ b/queue-4.4/hv-properly-delay-kvp-packets-when-negotiation-is-in-progress.patch @@ -0,0 +1,94 @@ +From a3ade8cc474d848676278660e65f5af1e9e094d9 Mon Sep 17 00:00:00 2001 +From: Long Li +Date: Sun, 30 Apr 2017 16:21:19 -0700 +Subject: HV: properly delay KVP packets when negotiation is in progress + +From: Long Li + +commit a3ade8cc474d848676278660e65f5af1e9e094d9 upstream. + +The host may send multiple negotiation packets +(due to timeout) before the KVP user-mode daemon +is connected. KVP user-mode daemon is connected. +We need to defer processing those packets +until the daemon is negotiated and connected. +It's okay for guest to respond +to all negotiation packets. + +In addition, the host may send multiple staged +KVP requests as soon as negotiation is done. +We need to properly process those packets using one +tasklet for exclusive access to ring buffer. + +This patch is based on the work of +Nick Meier . + +The above is the original changelog of +a3ade8cc474d ("HV: properly delay KVP packets when negotiation is in progress" + +Here I re-worked the original patch because the mainline version +can't work for the linux-4.4.y branch, on which channel->callback_event +doesn't exist yet. In the mainline, channel->callback_event was added by: +631e63a9f346 ("vmbus: change to per channel tasklet"). Here we don't want +to backport it to v4.4, as it requires extra supporting changes and fixes, +which are unnecessary as to the KVP bug we're trying to resolve. + +NOTE: before this patch is used, we should cherry-pick the other related +3 patches from the mainline first: + +The background of this backport request is that: recently Wang Jian reported +some KVP issues: https://github.com/LIS/lis-next/issues/593: +e.g. the /var/lib/hyperv/.kvp_pool_* files can not be updated, and sometimes +if the hv_kvp_daemon doesn't timely start, the host may not be able to query +the VM's IP address via KVP. + +Reported-by: Wang Jian +Tested-by: Wang Jian +Signed-off-by: Dexuan Cui +Signed-off-by: Long Li +Signed-off-by: K. Y. Srinivasan +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hv/hv_kvp.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +--- a/drivers/hv/hv_kvp.c ++++ b/drivers/hv/hv_kvp.c +@@ -612,21 +612,22 @@ void hv_kvp_onchannelcallback(void *cont + NEGO_IN_PROGRESS, + NEGO_FINISHED} host_negotiatied = NEGO_NOT_STARTED; + +- if (host_negotiatied == NEGO_NOT_STARTED && +- kvp_transaction.state < HVUTIL_READY) { ++ if (kvp_transaction.state < HVUTIL_READY) { + /* + * If userspace daemon is not connected and host is asking + * us to negotiate we need to delay to not lose messages. + * This is important for Failover IP setting. + */ +- host_negotiatied = NEGO_IN_PROGRESS; +- schedule_delayed_work(&kvp_host_handshake_work, ++ if (host_negotiatied == NEGO_NOT_STARTED) { ++ host_negotiatied = NEGO_IN_PROGRESS; ++ schedule_delayed_work(&kvp_host_handshake_work, + HV_UTIL_NEGO_TIMEOUT * HZ); ++ } + return; + } + if (kvp_transaction.state > HVUTIL_READY) + return; +- ++recheck: + vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE * 4, &recvlen, + &requestid); + +@@ -703,6 +704,8 @@ void hv_kvp_onchannelcallback(void *cont + VM_PKT_DATA_INBAND, 0); + + host_negotiatied = NEGO_FINISHED; ++ ++ goto recheck; + } + + } diff --git a/queue-4.4/series b/queue-4.4/series index 0e4bcf0ecf8..f71f62b7c63 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -42,3 +42,7 @@ powerpc-tm-fix-userspace-r13-corruption.patch powerpc-tm-avoid-possible-userspace-r1-corruption-on-reclaim.patch arc-build-get-rid-of-toolchain-check.patch usb-gadget-serial-fix-oops-when-data-rx-d-after-close.patch +drivers-hv-utils-invoke-the-poll-function-after-handshake.patch +drivers-hv-util-pass-the-channel-information-during-the-init-call.patch +drivers-hv-kvp-fix-ip-failover.patch +hv-properly-delay-kvp-packets-when-negotiation-is-in-progress.patch