[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