[DRBD-cvs] r1937 - branches/drbd-0.7/drbd

drbd-cvs at lists.linbit.com drbd-cvs at lists.linbit.com
Wed Aug 31 19:04:26 CEST 2005


Author: phil
Date: 2005-08-31 19:04:25 +0200 (Wed, 31 Aug 2005)
New Revision: 1937

Modified:
   branches/drbd-0.7/drbd/drbd_receiver.c
Log:
This was really hard. 

In the kernel's API there are two variants of all bitops. The atomic
ones set_bit(), clear_bit(), test_bit() etc...  and the non atomic
ones __set_bit(), __clear_bit() ...

The race condition:
 CPU1 was in an IO completion handler and used the __set_bit(SYNC_STARTED,..)
 there. Non atomic means: First, it fetched the word from memory....
  ... CPU2 was exiting the _drbd_process_ee() function and did the clear bit 
 clear_bit(PROCESS_EE_RUNNING) atomic = fetch, modify and write...
  ... back on CPU1 we now do the modify and write...
  
So CPU2 sets the PROCESS_EE_RUNNING bit again, because it fetched
the word before CPU1 did it's atomic update.
  
So I conclude, that the rule is:
  
  If you use the atomic bitops on a word, you may never ever user the
  non atomic bitops on the same word anywhere in your code.

But it feels good, to understand what was going on!



Modified: branches/drbd-0.7/drbd/drbd_receiver.c
===================================================================
--- branches/drbd-0.7/drbd/drbd_receiver.c	2005-08-29 11:32:43 UTC (rev 1936)
+++ branches/drbd-0.7/drbd/drbd_receiver.c	2005-08-31 17:04:25 UTC (rev 1937)
@@ -934,7 +934,7 @@
 			 */
 		}
 		ok = drbd_send_ack(mdev,WriteAck,e);
-		__set_bit(SYNC_STARTED,&mdev->flags);
+		set_bit(SYNC_STARTED,&mdev->flags);
 	} else {
 		ok = drbd_send_ack(mdev,NegAck,e);
 		ok&= drbd_io_error(mdev);
@@ -2118,7 +2118,7 @@
 
 		if( is_syncer_blk(mdev,p->block_id)) {
 			drbd_set_in_sync(mdev,sector,blksize);
-			__set_bit(SYNC_STARTED,&mdev->flags);
+			set_bit(SYNC_STARTED,&mdev->flags);
 		} else {
 			req=(drbd_request_t*)(long)p->block_id;
 



More information about the drbd-cvs mailing list