public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: "K. Y. Srinivasan" <kys@microsoft.com>
To: gregkh@linuxfoundation.org, linux-kernel@vger.kernel.org,
	devel@linuxdriverproject.org, olaf@aepfle.de, apw@canonical.com,
	vkuznets@redhat.com, jasowang@redhat.com
Cc: "K. Y. Srinivasan" <kys@microsoft.com>
Subject: [PATCH RESEND 02/27] Drivers: hv: utils: run polling callback always in interrupt context
Date: Fri, 11 Dec 2015 20:21:22 -0800	[thread overview]
Message-ID: <1449894107-3389-2-git-send-email-kys@microsoft.com> (raw)
In-Reply-To: <1449894107-3389-1-git-send-email-kys@microsoft.com>

From: Olaf Hering <olaf@aepfle.de>

All channel interrupts are bound to specific VCPUs in the guest
at the point channel is created. While currently, we invoke the
polling function on the correct CPU (the CPU to which the channel
is bound to) in some cases we may run the polling function in
a non-interrupt context. This  potentially can cause an issue as the
polling function can be interrupted by the channel callback function.
Fix the issue by running the polling function on the appropriate CPU
at interrupt level. Additional details of the issue being addressed by
this patch are given below:

Currently hv_fcopy_onchannelcallback is called from interrupts and also
via the ->write function of hv_utils. Since the used global variables to
maintain state are not thread safe the state can get out of sync.
This affects the variable state as well as the channel inbound buffer.

As suggested by KY adjust hv_poll_channel to always run the given
callback on the cpu which the channel is bound to. This avoids the need
for locking because all the util services are single threaded and only
one transaction is active at any given point in time.

Additionally, remove the context variable, they will always be the same as
recv_channel.

Signed-off-by: Olaf Hering <olaf@aepfle.de>
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
---
 drivers/hv/hv_fcopy.c     |   34 ++++++++++++----------------------
 drivers/hv/hv_kvp.c       |   28 ++++++++++------------------
 drivers/hv/hv_snapshot.c  |   29 +++++++++++------------------
 drivers/hv/hyperv_vmbus.h |    6 +-----
 4 files changed, 34 insertions(+), 63 deletions(-)

diff --git a/drivers/hv/hv_fcopy.c b/drivers/hv/hv_fcopy.c
index bbdec50..c37a71e 100644
--- a/drivers/hv/hv_fcopy.c
+++ b/drivers/hv/hv_fcopy.c
@@ -51,7 +51,6 @@ static struct {
 	struct hv_fcopy_hdr  *fcopy_msg; /* current message */
 	struct vmbus_channel *recv_channel; /* chn we got the request */
 	u64 recv_req_id; /* request ID. */
-	void *fcopy_context; /* for the channel callback */
 } fcopy_transaction;
 
 static void fcopy_respond_to_host(int error);
@@ -67,6 +66,13 @@ static struct hvutil_transport *hvt;
  */
 static int dm_reg_value;
 
+static void fcopy_poll_wrapper(void *channel)
+{
+	/* Transaction is finished, reset the state here to avoid races. */
+	fcopy_transaction.state = HVUTIL_READY;
+	hv_fcopy_onchannelcallback(channel);
+}
+
 static void fcopy_timeout_func(struct work_struct *dummy)
 {
 	/*
@@ -74,13 +80,7 @@ static void fcopy_timeout_func(struct work_struct *dummy)
 	 * process the pending transaction.
 	 */
 	fcopy_respond_to_host(HV_E_FAIL);
-
-	/* Transaction is finished, reset the state. */
-	if (fcopy_transaction.state > HVUTIL_READY)
-		fcopy_transaction.state = HVUTIL_READY;
-
-	hv_poll_channel(fcopy_transaction.fcopy_context,
-			hv_fcopy_onchannelcallback);
+	hv_poll_channel(fcopy_transaction.recv_channel, fcopy_poll_wrapper);
 }
 
 static int fcopy_handle_handshake(u32 version)
@@ -108,9 +108,7 @@ static int fcopy_handle_handshake(u32 version)
 		return -EINVAL;
 	}
 	pr_debug("FCP: userspace daemon ver. %d registered\n", version);
-	fcopy_transaction.state = HVUTIL_READY;
-	hv_poll_channel(fcopy_transaction.fcopy_context,
-			hv_fcopy_onchannelcallback);
+	hv_poll_channel(fcopy_transaction.recv_channel, fcopy_poll_wrapper);
 	return 0;
 }
 
@@ -227,15 +225,8 @@ void hv_fcopy_onchannelcallback(void *context)
 	int util_fw_version;
 	int fcopy_srv_version;
 
-	if (fcopy_transaction.state > HVUTIL_READY) {
-		/*
-		 * We will defer processing this callback once
-		 * the current transaction is complete.
-		 */
-		fcopy_transaction.fcopy_context = context;
+	if (fcopy_transaction.state > HVUTIL_READY)
 		return;
-	}
-	fcopy_transaction.fcopy_context = NULL;
 
 	vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE * 2, &recvlen,
 			 &requestid);
@@ -305,9 +296,8 @@ static int fcopy_on_msg(void *msg, int len)
 	if (cancel_delayed_work_sync(&fcopy_timeout_work)) {
 		fcopy_transaction.state = HVUTIL_USERSPACE_RECV;
 		fcopy_respond_to_host(*val);
-		fcopy_transaction.state = HVUTIL_READY;
-		hv_poll_channel(fcopy_transaction.fcopy_context,
-				hv_fcopy_onchannelcallback);
+		hv_poll_channel(fcopy_transaction.recv_channel,
+				fcopy_poll_wrapper);
 	}
 
 	return 0;
diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
index e6aa33a..2a3420c 100644
--- a/drivers/hv/hv_kvp.c
+++ b/drivers/hv/hv_kvp.c
@@ -66,7 +66,6 @@ static struct {
 	struct hv_kvp_msg  *kvp_msg; /* current message */
 	struct vmbus_channel *recv_channel; /* chn we got the request */
 	u64 recv_req_id; /* request ID. */
-	void *kvp_context; /* for the channel callback */
 } kvp_transaction;
 
 /*
@@ -94,6 +93,13 @@ static struct hvutil_transport *hvt;
  */
 #define HV_DRV_VERSION           "3.1"
 
+static void kvp_poll_wrapper(void *channel)
+{
+	/* Transaction is finished, reset the state here to avoid races. */
+	kvp_transaction.state = HVUTIL_READY;
+	hv_kvp_onchannelcallback(channel);
+}
+
 static void
 kvp_register(int reg_value)
 {
@@ -121,12 +127,7 @@ static void kvp_timeout_func(struct work_struct *dummy)
 	 */
 	kvp_respond_to_host(NULL, HV_E_FAIL);
 
-	/* Transaction is finished, reset the state. */
-	if (kvp_transaction.state > HVUTIL_READY)
-		kvp_transaction.state = HVUTIL_READY;
-
-	hv_poll_channel(kvp_transaction.kvp_context,
-			hv_kvp_onchannelcallback);
+	hv_poll_channel(kvp_transaction.recv_channel, kvp_poll_wrapper);
 }
 
 static int kvp_handle_handshake(struct hv_kvp_msg *msg)
@@ -218,9 +219,7 @@ static int kvp_on_msg(void *msg, int len)
 	 */
 	if (cancel_delayed_work_sync(&kvp_timeout_work)) {
 		kvp_respond_to_host(message, error);
-		kvp_transaction.state = HVUTIL_READY;
-		hv_poll_channel(kvp_transaction.kvp_context,
-				hv_kvp_onchannelcallback);
+		hv_poll_channel(kvp_transaction.recv_channel, kvp_poll_wrapper);
 	}
 
 	return 0;
@@ -596,15 +595,8 @@ void hv_kvp_onchannelcallback(void *context)
 	int util_fw_version;
 	int kvp_srv_version;
 
-	if (kvp_transaction.state > HVUTIL_READY) {
-		/*
-		 * We will defer processing this callback once
-		 * the current transaction is complete.
-		 */
-		kvp_transaction.kvp_context = context;
+	if (kvp_transaction.state > HVUTIL_READY)
 		return;
-	}
-	kvp_transaction.kvp_context = NULL;
 
 	vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE * 4, &recvlen,
 			 &requestid);
diff --git a/drivers/hv/hv_snapshot.c b/drivers/hv/hv_snapshot.c
index 815405f..a548ae4 100644
--- a/drivers/hv/hv_snapshot.c
+++ b/drivers/hv/hv_snapshot.c
@@ -53,7 +53,6 @@ static struct {
 	struct vmbus_channel *recv_channel; /* chn we got the request */
 	u64 recv_req_id; /* request ID. */
 	struct hv_vss_msg  *msg; /* current message */
-	void *vss_context; /* for the channel callback */
 } vss_transaction;
 
 
@@ -74,6 +73,13 @@ static void vss_timeout_func(struct work_struct *dummy);
 static DECLARE_DELAYED_WORK(vss_timeout_work, vss_timeout_func);
 static DECLARE_WORK(vss_send_op_work, vss_send_op);
 
+static void vss_poll_wrapper(void *channel)
+{
+	/* Transaction is finished, reset the state here to avoid races. */
+	vss_transaction.state = HVUTIL_READY;
+	hv_vss_onchannelcallback(channel);
+}
+
 /*
  * Callback when data is received from user mode.
  */
@@ -86,12 +92,7 @@ static void vss_timeout_func(struct work_struct *dummy)
 	pr_warn("VSS: timeout waiting for daemon to reply\n");
 	vss_respond_to_host(HV_E_FAIL);
 
-	/* Transaction is finished, reset the state. */
-	if (vss_transaction.state > HVUTIL_READY)
-		vss_transaction.state = HVUTIL_READY;
-
-	hv_poll_channel(vss_transaction.vss_context,
-			hv_vss_onchannelcallback);
+	hv_poll_channel(vss_transaction.recv_channel, vss_poll_wrapper);
 }
 
 static int vss_handle_handshake(struct hv_vss_msg *vss_msg)
@@ -138,9 +139,8 @@ static int vss_on_msg(void *msg, int len)
 		if (cancel_delayed_work_sync(&vss_timeout_work)) {
 			vss_respond_to_host(vss_msg->error);
 			/* Transaction is finished, reset the state. */
-			vss_transaction.state = HVUTIL_READY;
-			hv_poll_channel(vss_transaction.vss_context,
-					hv_vss_onchannelcallback);
+			hv_poll_channel(vss_transaction.recv_channel,
+					vss_poll_wrapper);
 		}
 	} else {
 		/* This is a spurious call! */
@@ -238,15 +238,8 @@ void hv_vss_onchannelcallback(void *context)
 	struct icmsg_hdr *icmsghdrp;
 	struct icmsg_negotiate *negop = NULL;
 
-	if (vss_transaction.state > HVUTIL_READY) {
-		/*
-		 * We will defer processing this callback once
-		 * the current transaction is complete.
-		 */
-		vss_transaction.vss_context = context;
+	if (vss_transaction.state > HVUTIL_READY)
 		return;
-	}
-	vss_transaction.vss_context = NULL;
 
 	vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE * 2, &recvlen,
 			 &requestid);
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
index 225b96b..12156db 100644
--- a/drivers/hv/hyperv_vmbus.h
+++ b/drivers/hv/hyperv_vmbus.h
@@ -764,11 +764,7 @@ static inline void hv_poll_channel(struct vmbus_channel *channel,
 	if (!channel)
 		return;
 
-	if (channel->target_cpu != smp_processor_id())
-		smp_call_function_single(channel->target_cpu,
-					 cb, channel, true);
-	else
-		cb(channel);
+	smp_call_function_single(channel->target_cpu, cb, channel, true);
 }
 
 enum hvutil_device_state {
-- 
1.7.4.1


  reply	other threads:[~2015-12-12  2:49 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-12-12  4:21 [PATCH RESEND 00/27] Drivers: hv: Miscellaneous fixes K. Y. Srinivasan
2015-12-12  4:21 ` [PATCH RESEND 01/27] Drivers: hv: util: Increase the timeout for util services K. Y. Srinivasan
2015-12-12  4:21   ` K. Y. Srinivasan [this message]
2015-12-12  4:21   ` [PATCH RESEND 03/27] tools: hv: report ENOSPC errors in hv_fcopy_daemon K. Y. Srinivasan
2015-12-12  4:21   ` [PATCH RESEND 04/27] tools: hv: remove repeated HV_FCOPY string K. Y. Srinivasan
2015-12-12  4:21   ` [PATCH RESEND 05/27] Drivers: hv: util: catch allocation errors K. Y. Srinivasan
2015-12-12  4:21   ` [PATCH RESEND 06/27] Drivers: hv: utils: use memdup_user in hvt_op_write K. Y. Srinivasan
2015-12-12  4:21   ` [PATCH RESEND 07/27] drivers/hv: cleanup synic msrs if vmbus connect failed K. Y. Srinivasan
2015-12-12  4:21   ` [PATCH RESEND 08/27] drivers:hv: Export a function that maps Linux CPU num onto Hyper-V proc num K. Y. Srinivasan
2015-12-12  4:21   ` [PATCH RESEND 09/27] drivers:hv: Export the API to invoke a hypercall on Hyper-V K. Y. Srinivasan
2015-12-12  4:21   ` [PATCH RESEND 10/27] drivers:hv: Define the channel type for Hyper-V PCI Express pass-through K. Y. Srinivasan
2015-12-12  4:21   ` [PATCH RESEND 11/27] Drivers: hv: vss: run only on supported host versions K. Y. Srinivasan
2015-12-12  4:21   ` [PATCH RESEND 12/27] Drivers: hv: vmbus: Use uuid_le type consistently K. Y. Srinivasan
2015-12-12  4:21   ` [PATCH RESEND 13/27] Drivers: hv: vmbus: Use uuid_le_cmp() for comparing GUIDs K. Y. Srinivasan
2015-12-12  4:21   ` [PATCH RESEND 14/27] Drivers: hv: vmbus: Get rid of the unused macro K. Y. Srinivasan
2015-12-12  4:21   ` [PATCH RESEND 15/27] Drivers: hv: vmbus: Get rid of the unused irq variable K. Y. Srinivasan
2015-12-12  4:21   ` [PATCH RESEND 16/27] Drivers: hv: vmbus: serialize process_chn_event() and vmbus_close_internal() K. Y. Srinivasan
2015-12-12  4:21   ` [PATCH RESEND 17/27] Drivers: hv: vmbus: do sanity check of channel state in vmbus_close_internal() K. Y. Srinivasan
2015-12-12  4:21   ` [PATCH RESEND 18/27] Drivers: hv: vmbus: fix rescind-offer handling for device without a driver K. Y. Srinivasan
2015-12-12  4:21   ` [PATCH RESEND 19/27] Drivers: hv: vmbus: release relid on error in vmbus_process_offer() K. Y. Srinivasan
2015-12-12  4:21   ` [PATCH RESEND 20/27] Drivers: hv: vmbus: channge vmbus_connection.channel_lock to mutex K. Y. Srinivasan
2015-12-12  4:21   ` [PATCH RESEND 21/27] drivers:hv: Allow for MMIO claims that span ACPI _CRS records K. Y. Srinivasan
2015-12-12  4:21   ` [PATCH RESEND 22/27] tools/hv: Use include/uapi with __EXPORTED_HEADERS__ K. Y. Srinivasan
2015-12-12  4:21   ` [PATCH RESEND 23/27] Drivers: hv: vmbus: Fix a Host signaling bug K. Y. Srinivasan
2015-12-12  4:21   ` [PATCH RESEND 24/27] drivers/hv: correct tsc page sequence invalid value K. Y. Srinivasan
2015-12-12  4:21   ` [PATCH 25/27] Drivers: hv: vmbus: Force all channel messages to be delivered on CPU 0 K. Y. Srinivasan
2015-12-12  4:21   ` [PATCH 26/27] Drivers: hv: utils: Invoke the poll function after handshake K. Y. Srinivasan
2015-12-12  4:21   ` [PATCH 27/27] tools: hv: vss: fix the write()'s argument: error -> vss_msg K. Y. Srinivasan
2015-12-14 18:59 ` [PATCH RESEND 00/27] Drivers: hv: Miscellaneous fixes Greg KH
2015-12-14 22:21   ` KY Srinivasan
  -- strict thread matches above, loose matches on Subject: below --
2015-12-15  0:01 K. Y. Srinivasan
2015-12-15  0:01 ` [PATCH RESEND 01/27] Drivers: hv: util: Increase the timeout for util services K. Y. Srinivasan
2015-12-15  0:01   ` [PATCH RESEND 02/27] Drivers: hv: utils: run polling callback always in interrupt context K. Y. Srinivasan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1449894107-3389-2-git-send-email-kys@microsoft.com \
    --to=kys@microsoft.com \
    --cc=apw@canonical.com \
    --cc=devel@linuxdriverproject.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=jasowang@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=olaf@aepfle.de \
    --cc=vkuznets@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox