From: Haiyang Zhang <haiyangz@xxxxxxxxxxxxx> 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@xxxxxxxxxxxxx> Signed-off-by: Hank Janssen <hjanssen@xxxxxxxxxxxxx> --- 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
Attachment:
0525-Fix-race-condition-on-IC-channel-initialization.patch
Description: 0525-Fix-race-condition-on-IC-channel-initialization.patch
_______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/devel