Re: [PATCH 1/1] staging: hv: Fix race condition on IC channel initialization (modified)

Previous thread: [PATCH]wireless:ath9k Fix ath_print in xmit.c by Justin P. Mattock on Wednesday, May 26, 2010 - 9:49 am. (9 messages)

Next thread: tsc reliability for Intel Core 2 Duo "Conroe" by Dan Magenheimer on Wednesday, May 26, 2010 - 10:41 am. (2 messages)
From: Haiyang Zhang
Date: Wednesday, May 26, 2010 - 9:54 am

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,
-						    ...
From: Greg KH
Date: Wednesday, May 26, 2010 - 1:51 pm

What is the mb() call for?  Why is it necessary?  (hint, if you need it,
something else is really wrong...)

Something wierd happened with your indentation here, it doesn't line up
properly.  That call to VmbusChannelOpen() needs to go in a full tab,
not 4 spaces.

Please always run your patch through the checkpatch.pl script before


As you are using this "ic_channel_ready variable only within the
vmbus_bus_init() call, why not just make it local to there?  Then
there's no need to do the create/init/wait/free sequence outside the
init call.

The init call should just do all of this for us, right?

thanks,

greg k-h
--

From: Haiyang Zhang
Date: Wednesday, May 26, 2010 - 2:25 pm

As discussed previously, I used atomic_t to handle more general case 

It ensures the channel assignment happens before the wakeup call: 
osd_WaitEventSet(ic_channel_ready), if the compiler optimization re-arrange 

Sure, I will replace it with TAB. I already ran checkpatch.pl on 
this patch -- no error:
staging-next-2.6> scripts/checkpatch.pl 0525-Fix-race-condition-on-IC-channel-initialization.patch
total: 0 errors, 0 warnings, 71 lines checked


IC stands for "integration components", such as Shutdown, Timesync, 

The ic_channel_ready variable is called by VmbusChannelProcessOffer /  osd_WaitEventSet(ic_channel_ready) to wake up vmbus_init(). So it's 
not a local variable.

Thanks,

- Haiyang

--

From: Greg KH
Date: Wednesday, May 26, 2010 - 2:48 pm

If you care about this, because some other thread is looking at it, then
you really need to protect it with a lock.  Don't rely on a mb() to get



But again, this logic should be within the init call, as it's part of
the proper init sequence.  So just put it in that call please.

thanks,

greg k-h
--

From: Hank Janssen
Date: Wednesday, May 26, 2010 - 3:03 pm

Marketing in the their infinite wisdom decided that going forward they 
should be called Linux Integration Service so IS. 

Sigh..............

We will change it to hv_  :)

Hank.

--

From: Haiyang Zhang
Date: Wednesday, May 26, 2010 - 3:23 pm

The VmbusChannelProcessOffer() is called from interrupt context, and initialize the channels, wake up vmbus_init when all channels are ready. If using local variable only, how to pass the channel ready info to vmbus_init() which is in a different context?

Thanks,

- Haiyang

--

From: Greg KH
Date: Wednesday, May 26, 2010 - 3:30 pm

How about a lock!

What's so scary about a pretty little semaphore?  They are all cute and
cuddley and don't bite anyone.  You should not be afraid to use them,

No, I mean move the logic you added here, into the vmbus_init() call.

thanks,

greg k-h
--

From: Haiyang Zhang
Date: Wednesday, May 26, 2010 - 3:52 pm

Do you mean:
Move the event creat/wait/free, which is currently in vmbus_init(), into vmbus_bus_init() function.  hv_channle_ready will still be a global variable. And, the wakeup call -- osd_WaitEventSet() --remains in VmbusChannelProcessOffer() ?

Thanks,

- Haiyang

--

From: Greg KH
Date: Thursday, May 27, 2010 - 4:22 pm

Yes.

And as Jiri pointed out, this should be a simple completion.

thanks,

greg k-h
--

From: Jiri Slaby
Date: Wednesday, May 26, 2010 - 11:16 pm

wake_up() is a barrier, you don't need the mb() there.

BTW osd_WaitEventSet et al. can be easily converted to completion.

-- 
js
--

Previous thread: [PATCH]wireless:ath9k Fix ath_print in xmit.c by Justin P. Mattock on Wednesday, May 26, 2010 - 9:49 am. (9 messages)

Next thread: tsc reliability for Intel Core 2 Duo "Conroe" by Dan Magenheimer on Wednesday, May 26, 2010 - 10:41 am. (2 messages)