4.4-stable review patch.  If anyone has any objections, please let me know.

------------------

From: K. Y. Srinivasan <k...@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 <k...@microsoft.com>
Reported-by: Vitaly Kuznetsov <vkuzn...@redhat.com>
Signed-off-by: Dexuan Cui <de...@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gre...@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);


Reply via email to