[DRBD-cvs] svn commit by phil - r2914 - branches/drbd-8.0/drbd -
Fixes a race condition in receive_state(), that was poi
drbd-cvs at lists.linbit.com
drbd-cvs at lists.linbit.com
Tue Jun 5 09:29:25 CEST 2007
Author: phil
Date: 2007-06-05 09:29:24 +0200 (Tue, 05 Jun 2007)
New Revision: 2914
Modified:
branches/drbd-8.0/drbd/drbd_receiver.c
Log:
Fixes a race condition in receive_state(), that was pointed out
by Ernest Montrose.
Modified: branches/drbd-8.0/drbd/drbd_receiver.c
===================================================================
--- branches/drbd-8.0/drbd/drbd_receiver.c 2007-06-04 11:22:39 UTC (rev 2913)
+++ branches/drbd-8.0/drbd/drbd_receiver.c 2007-06-05 07:29:24 UTC (rev 2914)
@@ -2390,7 +2390,7 @@
STATIC int receive_state(drbd_dev *mdev, Drbd_Header *h)
{
Drbd_State_Packet *p = (Drbd_State_Packet*)h;
- drbd_conns_t nconn;
+ drbd_conns_t nconn,oconn;
drbd_state_t os,ns,peer_state;
int rv;
@@ -2398,12 +2398,16 @@
if (drbd_recv(mdev, h->payload, h->length) != h->length)
return FALSE;
- nconn = mdev->state.conn;
+ peer_state.i = be32_to_cpu(p->state);
+
+ spin_lock_irq(&mdev->req_lock);
+ retry:
+ oconn = nconn = mdev->state.conn;
+ spin_unlock_irq(&mdev->req_lock);
+
if (nconn == WFReportParams ) nconn = Connected;
- peer_state.i = be32_to_cpu(p->state);
-
- if (mdev->p_uuid && mdev->state.conn <= Connected &&
+ if (mdev->p_uuid && oconn <= Connected &&
inc_local_if_state(mdev,Negotiating) &&
peer_state.disk >= Negotiating) {
nconn=drbd_sync_handshake(mdev,peer_state.role,peer_state.disk);
@@ -2412,19 +2416,8 @@
if(nconn == conn_mask) return FALSE;
}
- if (mdev->state.conn > WFReportParams ) {
- if( nconn > Connected && peer_state.conn <= Connected) {
- // we want resync, peer has not yet decided to sync...
- drbd_send_uuids(mdev);
- drbd_send_state(mdev);
- }
- else if (nconn == Connected && peer_state.disk == Negotiating) {
- // peer is waiting for us to respond...
- drbd_send_state(mdev);
- }
- }
-
spin_lock_irq(&mdev->req_lock);
+ if( mdev->state.conn != oconn ) goto retry;
os = mdev->state;
ns.i = mdev->state.i;
ns.conn = nconn;
@@ -2446,6 +2439,18 @@
return FALSE;
}
+ if (oconn > WFReportParams ) {
+ if( nconn > Connected && peer_state.conn <= Connected) {
+ // we want resync, peer has not yet decided to sync...
+ drbd_send_uuids(mdev);
+ drbd_send_state(mdev);
+ }
+ else if (nconn == Connected && peer_state.disk == Negotiating) {
+ // peer is waiting for us to respond...
+ drbd_send_state(mdev);
+ }
+ }
+
mdev->net_conf->want_lose = 0;
/* FIXME assertion for (gencounts do not diverge) */
More information about the drbd-cvs
mailing list