lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1427472614-32625-1-git-send-email-kys@microsoft.com>
Date:	Fri, 27 Mar 2015 09:10:08 -0700
From:	"K. Y. Srinivasan" <kys@...rosoft.com>
To:	gregkh@...uxfoundation.org, linux-kernel@...r.kernel.org,
	devel@...uxdriverproject.org, olaf@...fle.de, apw@...onical.com,
	vkuznets@...hat.com, jasowang@...hat.com
Cc:	Dexuan Cui <decui@...rosoft.com>,
	"K. Y. Srinivasan" <kys@...rosoft.com>
Subject: [PATCH 1/7] hv: run non-blocking message handlers in the dispatch tasklet

From: Dexuan Cui <decui@...rosoft.com>

A work item in vmbus_connection.work_queue can sleep, waiting for a new
host message (usually it is some kind of "completion" message). Currently
the new message will be handled in the same workqueue, but since work items
in the workqueue is serialized, we actually have no chance to handle
the new message if the current work item is sleeping -- as as result, the
current work item will hang forever.

K. Y. has posted the below fix to resolve the issue:
Drivers: hv: vmbus: Perform device register in the per-channel work element

Actually we can simplify the fix by directly running non-blocking message
handlers in the dispatch tasklet (inspired by K. Y.).

This patch is the fundamental change. The following 2 patches will simplify
the message offering and rescind-offering handling a lot.

Signed-off-by: Dexuan Cui <decui@...rosoft.com>
Cc: K. Y. Srinivasan <kys@...rosoft.com>
Signed-off-by: K. Y. Srinivasan <kys@...rosoft.com>
---
 drivers/hv/channel_mgmt.c |   41 ++++++++++++++++++-----------------------
 drivers/hv/hyperv_vmbus.h |   17 +++++++++++++++++
 drivers/hv/vmbus_drv.c    |   21 ++++++++++++++++++---
 3 files changed, 53 insertions(+), 26 deletions(-)

diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index bb39705..287f07b 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -33,11 +33,6 @@
 
 #include "hyperv_vmbus.h"
 
-struct vmbus_channel_message_table_entry {
-	enum vmbus_channel_message_type message_type;
-	void (*message_handler)(struct vmbus_channel_message_header *msg);
-};
-
 struct vmbus_rescind_work {
 	struct work_struct work;
 	struct vmbus_channel *channel;
@@ -827,25 +822,25 @@ static void vmbus_onversion_response(
 }
 
 /* Channel message dispatch table */
-static struct vmbus_channel_message_table_entry
+struct vmbus_channel_message_table_entry
 	channel_message_table[CHANNELMSG_COUNT] = {
-	{CHANNELMSG_INVALID,			NULL},
-	{CHANNELMSG_OFFERCHANNEL,		vmbus_onoffer},
-	{CHANNELMSG_RESCIND_CHANNELOFFER,	vmbus_onoffer_rescind},
-	{CHANNELMSG_REQUESTOFFERS,		NULL},
-	{CHANNELMSG_ALLOFFERS_DELIVERED,	vmbus_onoffers_delivered},
-	{CHANNELMSG_OPENCHANNEL,		NULL},
-	{CHANNELMSG_OPENCHANNEL_RESULT,	vmbus_onopen_result},
-	{CHANNELMSG_CLOSECHANNEL,		NULL},
-	{CHANNELMSG_GPADL_HEADER,		NULL},
-	{CHANNELMSG_GPADL_BODY,		NULL},
-	{CHANNELMSG_GPADL_CREATED,		vmbus_ongpadl_created},
-	{CHANNELMSG_GPADL_TEARDOWN,		NULL},
-	{CHANNELMSG_GPADL_TORNDOWN,		vmbus_ongpadl_torndown},
-	{CHANNELMSG_RELID_RELEASED,		NULL},
-	{CHANNELMSG_INITIATE_CONTACT,		NULL},
-	{CHANNELMSG_VERSION_RESPONSE,		vmbus_onversion_response},
-	{CHANNELMSG_UNLOAD,			NULL},
+	{CHANNELMSG_INVALID,			0, NULL},
+	{CHANNELMSG_OFFERCHANNEL,		0, vmbus_onoffer},
+	{CHANNELMSG_RESCIND_CHANNELOFFER,	0, vmbus_onoffer_rescind},
+	{CHANNELMSG_REQUESTOFFERS,		0, NULL},
+	{CHANNELMSG_ALLOFFERS_DELIVERED,	1, vmbus_onoffers_delivered},
+	{CHANNELMSG_OPENCHANNEL,		0, NULL},
+	{CHANNELMSG_OPENCHANNEL_RESULT,		1, vmbus_onopen_result},
+	{CHANNELMSG_CLOSECHANNEL,		0, NULL},
+	{CHANNELMSG_GPADL_HEADER,		0, NULL},
+	{CHANNELMSG_GPADL_BODY,			0, NULL},
+	{CHANNELMSG_GPADL_CREATED,		1, vmbus_ongpadl_created},
+	{CHANNELMSG_GPADL_TEARDOWN,		0, NULL},
+	{CHANNELMSG_GPADL_TORNDOWN,		1, vmbus_ongpadl_torndown},
+	{CHANNELMSG_RELID_RELEASED,		0, NULL},
+	{CHANNELMSG_INITIATE_CONTACT,		0, NULL},
+	{CHANNELMSG_VERSION_RESPONSE,		1, vmbus_onversion_response},
+	{CHANNELMSG_UNLOAD,			0, NULL},
 };
 
 /*
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
index c8e27e0..f40a5a9 100644
--- a/drivers/hv/hyperv_vmbus.h
+++ b/drivers/hv/hyperv_vmbus.h
@@ -685,6 +685,23 @@ struct vmbus_msginfo {
 
 extern struct vmbus_connection vmbus_connection;
 
+enum vmbus_message_handler_type {
+	/* The related handler can sleep. */
+	VMHT_BLOCKING = 0,
+
+	/* The related handler must NOT sleep. */
+	VMHT_NON_BLOCKING = 1,
+};
+
+struct vmbus_channel_message_table_entry {
+	enum vmbus_channel_message_type message_type;
+	enum vmbus_message_handler_type handler_type;
+	void (*message_handler)(struct vmbus_channel_message_header *msg);
+};
+
+extern struct vmbus_channel_message_table_entry
+	channel_message_table[CHANNELMSG_COUNT];
+
 /* General vmbus interface */
 
 struct hv_device *vmbus_device_create(const uuid_le *type,
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index 8313e25..c85235e 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -657,21 +657,36 @@ static void vmbus_on_msg_dpc(unsigned long data)
 	void *page_addr = hv_context.synic_message_page[cpu];
 	struct hv_message *msg = (struct hv_message *)page_addr +
 				  VMBUS_MESSAGE_SINT;
+	struct vmbus_channel_message_header *hdr;
+	struct vmbus_channel_message_table_entry *entry;
 	struct onmessage_work_context *ctx;
 
 	while (1) {
-		if (msg->header.message_type == HVMSG_NONE) {
+		if (msg->header.message_type == HVMSG_NONE)
 			/* no msg */
 			break;
-		} else {
+
+		hdr = (struct vmbus_channel_message_header *)msg->u.payload;
+
+		if (hdr->msgtype >= CHANNELMSG_COUNT) {
+			WARN_ONCE(1, "unknown msgtype=%d\n", hdr->msgtype);
+			goto msg_handled;
+		}
+
+		entry = &channel_message_table[hdr->msgtype];
+		if (entry->handler_type	== VMHT_BLOCKING) {
 			ctx = kmalloc(sizeof(*ctx), GFP_ATOMIC);
 			if (ctx == NULL)
 				continue;
+
 			INIT_WORK(&ctx->work, vmbus_onmessage_work);
 			memcpy(&ctx->msg, msg, sizeof(*msg));
+
 			queue_work(vmbus_connection.work_queue, &ctx->work);
-		}
+		} else
+			entry->message_handler(hdr);
 
+msg_handled:
 		msg->header.message_type = HVMSG_NONE;
 
 		/*
-- 
1.7.4.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ