lkml.org 
[lkml]   [2010]   [May]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH 1/1] staging: hv: Fix race condition on IC channel initialization (modified)
Date
From: Haiyang Zhang <haiyangz@microsoft.com>

Subject: [PATCH] staging: hv: Fix race condition on IC channel initialization
There is a possible race condition when hv_utils starts to load immediately
after hv_vmbus is loading - null pointer error could happen.
This patch added an event waiting to ensure all channels are ready before
vmbus_init() returns. So another module won't have any uninitialized channel.

Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>

---
drivers/staging/hv/channel_mgmt.c | 23 +++++++++++++----------
drivers/staging/hv/vmbus_drv.c | 10 ++++++++++
drivers/staging/hv/vmbus_private.h | 1 +
3 files changed, 24 insertions(+), 10 deletions(-)
diff --git a/drivers/staging/hv/channel_mgmt.c b/drivers/staging/hv/channel_mgmt.c
index 3f53b4d..f99db1b 100644
--- a/drivers/staging/hv/channel_mgmt.c
+++ b/drivers/staging/hv/channel_mgmt.c
@@ -305,6 +305,7 @@ static void VmbusChannelProcessOffer(void *context)
int ret;
int cnt;
unsigned long flags;
+ static atomic_t ic_channel_initcnt = ATOMIC_INIT(0);

DPRINT_ENTER(VMBUS);

@@ -373,22 +374,24 @@ static void VmbusChannelProcessOffer(void *context)
* can cleanup properly
*/
newChannel->State = CHANNEL_OPEN_STATE;
- cnt = 0;

- while (cnt != MAX_MSG_TYPES) {
+ /* Open IC channels */
+ for (cnt = 0; cnt < MAX_MSG_TYPES; cnt++) {
if (memcmp(&newChannel->OfferMsg.Offer.InterfaceType,
&hv_cb_utils[cnt].data,
- sizeof(struct hv_guid)) == 0) {
+ sizeof(struct hv_guid)) == 0 &&
+ VmbusChannelOpen(newChannel, 2 * PAGE_SIZE,
+ 2 * PAGE_SIZE, NULL, 0,
+ hv_cb_utils[cnt].callback,
+ newChannel) == 0) {
+ hv_cb_utils[cnt].channel = newChannel;
+ mb();
DPRINT_INFO(VMBUS, "%s",
hv_cb_utils[cnt].log_msg);
-
- if (VmbusChannelOpen(newChannel, 2 * PAGE_SIZE,
- 2 * PAGE_SIZE, NULL, 0,
- hv_cb_utils[cnt].callback,
- newChannel) == 0)
- hv_cb_utils[cnt].channel = newChannel;
+ if (atomic_inc_return(&ic_channel_initcnt) ==
+ MAX_MSG_TYPES)
+ osd_WaitEventSet(ic_channel_ready);
}
- cnt++;
}
}
DPRINT_EXIT(VMBUS);
diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c
index c21731a..3ae8981 100644
--- a/drivers/staging/hv/vmbus_drv.c
+++ b/drivers/staging/hv/vmbus_drv.c
@@ -989,6 +989,8 @@ static struct dmi_system_id __initdata microsoft_hv_dmi_table[] = {
};
MODULE_DEVICE_TABLE(dmi, microsoft_hv_dmi_table);

+struct osd_waitevent *ic_channel_ready;
+
static int __init vmbus_init(void)
{
int ret = 0;
@@ -1003,8 +1005,16 @@ static int __init vmbus_init(void)
if (!dmi_check_system(microsoft_hv_dmi_table))
return -ENODEV;

+ ic_channel_ready = osd_WaitEventCreate();
+ if (ic_channel_ready == NULL)
+ return -ENOMEM;
+
ret = vmbus_bus_init(VmbusInitialize);

+ /* Wait until all IC channels are initialized */
+ osd_WaitEventWait(ic_channel_ready);
+
+ kfree(ic_channel_ready);
DPRINT_EXIT(VMBUS_DRV);
return ret;
}
diff --git a/drivers/staging/hv/vmbus_private.h b/drivers/staging/hv/vmbus_private.h
index 588c667..3fb8dad 100644
--- a/drivers/staging/hv/vmbus_private.h
+++ b/drivers/staging/hv/vmbus_private.h
@@ -130,5 +130,6 @@ int VmbusSetEvent(u32 childRelId);

void VmbusOnEvents(void);

+extern struct osd_waitevent *ic_channel_ready;

#endif /* _VMBUS_PRIVATE_H_ */
--
1.6.3.2
[unhandled content-type:application/octet-stream]
\
 
 \ /
  Last update: 2010-05-26 18:57    [from the cache]
©2003-2011 Jasper Spaans