]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 18 Oct 2018 17:13:29 +0000 (19:13 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 18 Oct 2018 17:13:29 +0000 (19:13 +0200)
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

queue-4.4/drivers-hv-kvp-fix-ip-failover.patch [new file with mode: 0644]
queue-4.4/drivers-hv-util-pass-the-channel-information-during-the-init-call.patch [new file with mode: 0644]
queue-4.4/drivers-hv-utils-invoke-the-poll-function-after-handshake.patch [new file with mode: 0644]
queue-4.4/hv-properly-delay-kvp-packets-when-negotiation-is-in-progress.patch [new file with mode: 0644]
queue-4.4/series

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 (file)
index 0000000..7d4abfb
--- /dev/null
@@ -0,0 +1,131 @@
+From 4dbfc2e68004c60edab7e8fd26784383dd3ee9bc Mon Sep 17 00:00:00 2001
+From: Vitaly Kuznetsov <vkuznets@redhat.com>
+Date: Sat, 30 Apr 2016 19:21:33 -0700
+Subject: Drivers: hv: kvp: fix IP Failover
+
+From: Vitaly Kuznetsov <vkuznets@redhat.com>
+
+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 <vkuznets@redhat.com>
+Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
+Signed-off-by: Dexuan Cui <decui@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..3def46b
--- /dev/null
@@ -0,0 +1,108 @@
+From b9830d120cbe155863399f25eaef6aa8353e767f Mon Sep 17 00:00:00 2001
+From: "K. Y. Srinivasan" <kys@microsoft.com>
+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 <kys@microsoft.com>
+
+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 <kys@microsoft.com>
+Reported-by: Vitaly Kuznetsov <vkuznets@redhat.com>
+Signed-off-by: Dexuan Cui <decui@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..9cd1977
--- /dev/null
@@ -0,0 +1,44 @@
+From 2d0c3b5ad739697a68dc8a444f5b9f4817cf8f8f Mon Sep 17 00:00:00 2001
+From: "K. Y. Srinivasan" <kys@microsoft.com>
+Date: Mon, 14 Dec 2015 16:01:57 -0800
+Subject: Drivers: hv: utils: Invoke the poll function after handshake
+
+From: K. Y. Srinivasan <kys@microsoft.com>
+
+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 <kys@microsoft.com>
+Signed-off-by: Dexuan Cui <decui@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..2125c7a
--- /dev/null
@@ -0,0 +1,94 @@
+From a3ade8cc474d848676278660e65f5af1e9e094d9 Mon Sep 17 00:00:00 2001
+From: Long Li <longli@microsoft.com>
+Date: Sun, 30 Apr 2017 16:21:19 -0700
+Subject: HV: properly delay KVP packets when negotiation is in progress
+
+From: Long Li <longli@microsoft.com>
+
+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 <Nick.Meier@microsoft.com>.
+
+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 <jianjian.wang1@gmail.com>
+Tested-by: Wang Jian <jianjian.wang1@gmail.com>
+Signed-off-by: Dexuan Cui <decui@microsoft.com>
+Signed-off-by: Long Li <longli@microsoft.com>
+Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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;
+       }
+ }
index 0e4bcf0ecf8e5dd34a5203a0f3fa5fca69f9b418..f71f62b7c63ddd947fa0ffed990518680b23e339 100644 (file)
@@ -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