[DRBD-cvs] r1758 - in trunk/drbd: . linux

svn at svn.drbd.org svn at svn.drbd.org
Sat Feb 12 18:48:22 CET 2005


Author: phil
Date: 2005-02-12 18:48:17 +0100 (Sat, 12 Feb 2005)
New Revision: 1758

Modified:
   trunk/drbd/drbd_fs.c
   trunk/drbd/drbd_int.h
   trunk/drbd/drbd_main.c
   trunk/drbd/drbd_receiver.c
   trunk/drbd/drbd_sizeof_sanity_check.c
   trunk/drbd/linux/drbd.h
Log:
The implementation of the "allow-two-primaries" option
is now complete, but untested... might crash everywhere...


Modified: trunk/drbd/drbd_fs.c
===================================================================
--- trunk/drbd/drbd_fs.c	2005-02-11 15:59:06 UTC (rev 1757)
+++ trunk/drbd/drbd_fs.c	2005-02-12 17:48:17 UTC (rev 1758)
@@ -569,18 +569,18 @@
 
 
 	if (mdev->tl_hash_s != new_conf.max_epoch_size/8 ) {
-		new_tl_hash = kmalloc(mdev->tl_hash_s * sizeof(void*),
-				      GFP_KERNEL);
+		new_tl_hash=kmalloc((new_conf.max_epoch_size/8)*sizeof(void*),
+				    GFP_KERNEL);
 		if(!new_tl_hash) {
 			retcode=KMallocFailed;
 			goto fail_ioctl;
 		}
 	}
 
-	if (mdev->conf.two_primaries &&
+	if (new_conf.two_primaries &&
 	    ( mdev->ee_hash_s != new_conf.max_buffers/8 ) ) {
-		new_ee_hash = kmalloc(mdev->ee_hash_s * sizeof(void*),
-				      GFP_KERNEL);
+		new_ee_hash=kmalloc((new_conf.max_buffers/8)*sizeof(void*),
+				    GFP_KERNEL);
 		if(!new_ee_hash) {
 			retcode=KMallocFailed;
 			goto fail_ioctl;

Modified: trunk/drbd/drbd_int.h
===================================================================
--- trunk/drbd/drbd_int.h	2005-02-11 15:59:06 UTC (rev 1757)
+++ trunk/drbd/drbd_int.h	2005-02-12 17:48:17 UTC (rev 1758)
@@ -307,6 +307,7 @@
 	NegDReply,    // Local disk is broken...
 	NegRSDReply,  // Local disk is broken...
 	BarrierAck,
+	DiscardNote,
 
 	MAX_CMD,
 	MayIgnore = 0x100, // Flag only to test if (cmd > MayIgnore) ...
@@ -345,7 +346,8 @@
 		[NegAck]           = "NegAck",
 		[NegDReply]        = "NegDReply",
 		[NegRSDReply]      = "NegRSDReply",
-		[BarrierAck]       = "BarrierAck"
+		[BarrierAck]       = "BarrierAck",
+		[DiscardNote]      = "DiscardNote"
 	};
 
 	if (cmd == HandShake) return "HandShake";
@@ -490,6 +492,13 @@
 	u32       bit_map_gen[5];
 } __attribute((packed)) Drbd06_Parameter_P;
 
+typedef struct {
+	Drbd_Header head;
+	u64         block_id;
+	u32         seq_num;
+	u32         pad;
+} __attribute((packed)) Drbd_Discard_Packet;
+
 typedef union {
 	Drbd_Header              head;
 	Drbd_HandShake_Packet    HandShake;
@@ -560,13 +569,14 @@
 struct drbd_barrier;
 struct drbd_request {
 	struct drbd_work w;
-	long magic;
-	int rq_status;
 	struct drbd_barrier *barrier; // The next barrier.
 	struct bio *master_bio;       // master bio pointer
 	struct bio *private_bio;
 	struct hlist_node colision;
 	drbd_dev *mdev;
+	long magic;
+	int rq_status;
+	int seq_num;
 };
 
 struct drbd_barrier {
@@ -790,9 +800,7 @@
 extern void tl_clear(drbd_dev *mdev);
 extern int tl_dependence(drbd_dev *mdev, drbd_request_t * item);
 extern int tl_verify(drbd_dev *mdev, drbd_request_t * item, sector_t sector);
-#define TLHW_FLAG_SENT   0x10000000
-#define TLHW_FLAG_RECVW  0x20000000
-extern int req_have_write(drbd_dev *mdev, struct Tl_epoch_entry *e, int flags);
+extern drbd_request_t * req_have_write(drbd_dev *, struct Tl_epoch_entry *);
 extern void drbd_free_sock(drbd_dev *mdev);
 extern int drbd_send(drbd_dev *mdev, struct socket *sock,
 		     void* buf, size_t size, unsigned msg_flags);
@@ -822,6 +830,7 @@
 			      sector_t sector,int size, u64 block_id);
 extern int drbd_send_bitmap(drbd_dev *mdev);
 extern int _drbd_send_bitmap(drbd_dev *mdev);
+extern int drbd_send_discard(drbd_dev *mdev, drbd_request_t *req);
 extern void drbd_free_ll_dev(drbd_dev *mdev);
 extern int drbd_io_error(drbd_dev* mdev);
 extern void drbd_mdev_cleanup(drbd_dev *mdev);

Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c	2005-02-11 15:59:06 UTC (rev 1757)
+++ trunk/drbd/drbd_main.c	2005-02-12 17:48:17 UTC (rev 1758)
@@ -375,20 +375,14 @@
 	return !( ( s1 + (l1>>9) <= s2 ) || ( s1 >= s2 + (l2>>9) ) );
 }
 
-/* Return values:
- *
- * 0 ... no conflicting write
- * 1 ... a conflicting write, have not got ack by now.
- * 2 ... a conflicting write, have got also got ack.
- */
-int req_have_write(drbd_dev *mdev, struct Tl_epoch_entry *e, int flags)
+drbd_request_t * req_have_write(drbd_dev *mdev, struct Tl_epoch_entry *e)
 {
 	struct hlist_head *slot;
 	struct hlist_node *n;
 	drbd_request_t * req;
 	sector_t sector = drbd_ee_get_sector(e);	
 	int size = drbd_ee_get_size(e);
-	int i, rv=0;
+	int i;
 
 	D_ASSERT(size <= 1<<(HT_SHIFT+9) );
 
@@ -401,20 +395,10 @@
 			if( overlaps(drbd_req_get_sector(req),
 				     drbd_req_get_size(req),
 				     sector,
-				     size) ) {
-				rv=1;
-				if( req->rq_status & RQ_DRBD_SENT ) rv++;
-				if( flags & TLHW_FLAG_SENT ) {
-					req->rq_status |= RQ_DRBD_SENT;
-				}
-				if( flags & TLHW_FLAG_RECVW ) {
-					req->rq_status |= RQ_DRBD_RECVW;
-				}
-				goto out;
-			} //overlaps()
+				     size) ) goto out;
 		} // hlist_for_each_entry()
 	}
-
+	req = NULL;
 	// Good, no conflict found
 	INIT_HLIST_NODE(&e->colision);
 	hlist_add_head( &e->colision, mdev->ee_hash + 
@@ -422,17 +406,18 @@
  out:
 	spin_unlock_irq(&mdev->tl_lock);
 
-	return rv;
+	return req;
 }
 
-STATIC int ee_have_write(drbd_dev *mdev, drbd_request_t * req)
+STATIC struct Tl_epoch_entry * ee_have_write(drbd_dev *mdev, 
+					     drbd_request_t * req)
 {
 	struct hlist_head *slot;
 	struct hlist_node *n;
 	struct Tl_epoch_entry *ee;
 	sector_t sector = drbd_req_get_sector(req);
 	int size = drbd_req_get_size(req);
-	int i, rv=0;
+	int i;
 
 	D_ASSERT(size <= 1<<(HT_SHIFT+9) );
 
@@ -445,19 +430,16 @@
 			if( overlaps(drbd_ee_get_sector(ee),
 				     drbd_ee_get_size(ee),
 				     sector,
-				     size) ) {
-				rv=1;
-				goto out;
-			} //overlaps()
+				     size) ) goto out;
 		} // hlist_for_each_entry()
 	}
-
+	ee = NULL;
 	// Good, no conflict found
 	_tl_add(mdev,req);
  out:
 	spin_unlock_irq(&mdev->tl_lock);
 
-	return rv;
+	return ee;
 }
 
 /**
@@ -1000,7 +982,17 @@
 	return ok;
 }
 
+int drbd_send_discard(drbd_dev *mdev, drbd_request_t *req)
+{
+	Drbd_Discard_Packet p;
 
+	p.block_id = (unsigned long)req;
+	p.seq_num  = cpu_to_be32(req->seq_num);
+
+	return drbd_send_cmd(mdev,mdev->meta.socket,DiscardNote,
+			     (Drbd_Header*)&p,sizeof(p));
+}
+
 int drbd_send_state(drbd_dev *mdev)
 {
 	Drbd_State_Packet p;
@@ -1307,7 +1299,8 @@
 
 	p.sector   = cpu_to_be64(drbd_req_get_sector(req));
 	p.block_id = (unsigned long)req;
-	p.seq_num  = cpu_to_be32(atomic_add_return(1,&mdev->packet_seq));
+	p.seq_num  = cpu_to_be32( req->seq_num =
+				  atomic_add_return(1,&mdev->packet_seq) );
 
 	/* About tl_add():
 	1. This must be within the semaphor,

Modified: trunk/drbd/drbd_receiver.c
===================================================================
--- trunk/drbd/drbd_receiver.c	2005-02-11 15:59:06 UTC (rev 1757)
+++ trunk/drbd/drbd_receiver.c	2005-02-12 17:48:17 UTC (rev 1758)
@@ -1011,21 +1011,26 @@
 	return ok;
 }
 
-STATIC int drbd_chk_discard(drbd_dev *mdev,u64 block_id,int seq_num)
+STATIC int drbd_chk_discard(drbd_dev *mdev,struct Tl_epoch_entry *e)
 {
 	struct drbd_discard_note *dn;
 	struct list_head *le;
 
 	MUST_HOLD(&mdev->peer_seq_lock);
-
+ start_over:
 	list_for_each(le,&mdev->discard) {
 		dn = list_entry(le, struct drbd_discard_note, list);
-		if( dn->seq_num == seq_num ) {
-			D_ASSERT( dn->block_id == block_id );
+		if( dn->seq_num == mdev->peer_seq ) {
+			D_ASSERT( dn->block_id == e->block_id );
 			list_del(le);
 			kfree(dn);
 			return 1;
-		} 
+		}
+		if( dn->seq_num < mdev->peer_seq ) {
+			list_del(le);
+			kfree(dn);
+			goto start_over;
+		}
 	}
 	return 0;
 }
@@ -1035,8 +1040,9 @@
 {
 	sector_t sector;
 	struct Tl_epoch_entry *e;
+	drbd_request_t * req;
 	Drbd_Data_Packet *p = (Drbd_Data_Packet*)h;
-	int header_size,data_size, packet_seq,discard=0;
+	int header_size, data_size, packet_seq, discard;
 
 	// FIXME merge this code dups into some helper function
 	header_size = sizeof(*p) - sizeof(*h);
@@ -1052,6 +1058,20 @@
 	if (drbd_recv(mdev, h->payload, header_size) != header_size)
 		return FALSE;
 
+	sector = be64_to_cpu(p->sector);
+	e = read_in_block(mdev,data_size);
+	if (!e) return FALSE;
+
+	if(!inc_local(mdev)) {
+		if (DRBD_ratelimit(5*HZ,5))
+			ERR("Can not write mirrored data block to local disk.\n");
+		drbd_send_ack(mdev,NegAck,e);
+		spin_lock_irq(&mdev->ee_lock);
+		drbd_put_ee(mdev,e);
+		spin_unlock_irq(&mdev->ee_lock);
+		return TRUE;
+	}
+
 	/* This wait_event is here to make sure that never ever an
 	   DATA packet traveling via sock can overtake an ACK packet
 	   traveling on msock 
@@ -1066,68 +1086,58 @@
 		spin_lock(&mdev->peer_seq_lock); 
 		mdev->peer_seq = max(mdev->peer_seq, packet_seq);
 		/* is update_peer_seq(mdev,packet_seq); */
-		discard = drbd_chk_discard(mdev,p->block_id,packet_seq);
+		discard = drbd_chk_discard(mdev,e);
 		spin_unlock(&mdev->peer_seq_lock);
-	}
 
-	sector = be64_to_cpu(p->sector);
-	e = read_in_block(mdev,data_size);
-	if (!e) return FALSE;
-
-	if(!inc_local(mdev)) {
-		if (DRBD_ratelimit(5*HZ,5))
-			ERR("Can not write mirrored data block to local disk.\n");
-		drbd_send_ack(mdev,NegAck,e);
-		spin_lock_irq(&mdev->ee_lock);
-		drbd_put_ee(mdev,e);
-		spin_unlock_irq(&mdev->ee_lock);
-		return TRUE;
-	}
-
-	if(discard) {
-		spin_lock_irq(&mdev->ee_lock);
-		drbd_put_ee(mdev,e);
-		spin_unlock_irq(&mdev->ee_lock);
-		WARN("Concurrent write! [DISCARD BY LIST] sec=%lu\n",
-		     (unsigned long)sector);
-		return TRUE;
-	}
-
-	switch( req_have_write(mdev, e, 0) ) {
-	case 2: /* Conflicting write, got ACK */
-		/* write afterwards ...*/
-		WARN("Concurrent write! [W AFTERWARDS] sec=%lu\n",
-		     (unsigned long)sector);
-		if( wait_event_interruptible(mdev->cstate_wait,
-		     !req_have_write(mdev,e,TLHW_FLAG_RECVW))) {
+		if(discard) {
 			spin_lock_irq(&mdev->ee_lock);
 			drbd_put_ee(mdev,e);
 			spin_unlock_irq(&mdev->ee_lock);
-			return FALSE;
-		}
-	case 1: /* Conflicting write, no ACK by now*/
-		if (test_bit(UNIQUE,&mdev->flags)) {
-			spin_lock_irq(&mdev->ee_lock);
-			drbd_put_ee(mdev,e);
-			spin_unlock_irq(&mdev->ee_lock);
-			WARN("Concurrent write! [DISCARD BY FLAG] sec=%lu\n",
+			WARN("Concurrent write! [DISCARD BY LIST] sec=%lu\n",
 			     (unsigned long)sector);
 			return TRUE;
-		} else {
-			/* write afterwards, do not expect ACK */
-			WARN("Concurrent write! [W AFTERWARDS] sec=%lu\n",
-			     (unsigned long)sector);
-			if( wait_event_interruptible(mdev->cstate_wait,
-			      !req_have_write(mdev,e,
-				            TLHW_FLAG_RECVW|TLHW_FLAG_SENT))) {
-				spin_lock_irq(&mdev->ee_lock);
-				drbd_put_ee(mdev,e);
-				spin_unlock_irq(&mdev->ee_lock);
-				return FALSE;
+		}
+
+		req = req_have_write(mdev, e);
+		
+		if(req) {
+			if( req->rq_status & RQ_DRBD_SENT ) {
+				/* Conflicting write, got ACK */
+				/* write afterwards ...*/
+				WARN("Concurrent write! [W AFTERWARDS] "
+				     "sec=%lu\n",(unsigned long)sector);
+				if( wait_event_interruptible(mdev->cstate_wait,
+					       !req_have_write(mdev,e))) {
+					spin_lock_irq(&mdev->ee_lock);
+					drbd_put_ee(mdev,e);
+					spin_unlock_irq(&mdev->ee_lock);
+					return FALSE;
+				}
+			} else {
+				/* Conflicting write, no ACK by now*/
+				if (test_bit(UNIQUE,&mdev->flags)) {
+					spin_lock_irq(&mdev->ee_lock);
+					drbd_put_ee(mdev,e);
+					spin_unlock_irq(&mdev->ee_lock);
+					WARN("Concurrent write! [DISCARD BY FLAG] sec=%lu\n",
+					     (unsigned long)sector);
+					return TRUE;
+				} else {
+					/* write afterwards do not exp ACK */
+					WARN("Concurrent write! [W AFTERWARDS] sec=%lu\n",
+					     (unsigned long)sector);
+					drbd_send_discard(mdev,req);
+					drbd_end_req(req, RQ_DRBD_SENT, 1, sector);
+					if( wait_event_interruptible(mdev->cstate_wait,
+								     !req_have_write(mdev,e))) {
+						spin_lock_irq(&mdev->ee_lock);
+						drbd_put_ee(mdev,e);
+						spin_unlock_irq(&mdev->ee_lock);
+						return FALSE;
+					}
+				}
 			}
 		}
-		/* case 0:   no conflicting write. */
-		/* write it to disk now... */
 	}
 
 	e->block_id = p->block_id; // no meaning on this side, e* on partner
@@ -2265,6 +2275,27 @@
 	return TRUE;
 }
 
+STATIC int got_Discard(drbd_dev *mdev, Drbd_Header* h)
+{
+	Drbd_Discard_Packet *p = (Drbd_Discard_Packet*)h;
+	struct drbd_discard_note *dn;
+
+	dn = kmalloc(sizeof(struct drbd_discard_note),GFP_KERNEL);
+	if(!dn) {
+		ERR("kmalloc(drbd_discard_note) failed.");
+		return FALSE;
+	}
+
+	dn->block_id = (long)p->block_id;
+	dn->seq_num = be32_to_cpu(p->seq_num);
+
+	spin_lock(&mdev->peer_seq_lock);
+	list_add(&dn->list,&mdev->discard);
+	spin_unlock(&mdev->peer_seq_lock);
+
+	return TRUE;
+}
+
 struct asender_cmd {
 	size_t pkt_size;
 	int (*process)(drbd_dev *mdev, Drbd_Header* h);
@@ -2290,6 +2321,7 @@
 		[NegDReply] ={ sizeof(Drbd_BlockAck_Packet),  got_NegDReply },
 		[NegRSDReply]={sizeof(Drbd_BlockAck_Packet),  got_NegRSDReply},
 		[BarrierAck]={ sizeof(Drbd_BarrierAck_Packet),got_BarrierAck },
+		[DiscardNote]={sizeof(Drbd_Discard_Packet),   got_Discard },
 	};
 
 	sprintf(current->comm, "drbd%d_asender", (int)(mdev-drbd_conf));

Modified: trunk/drbd/drbd_sizeof_sanity_check.c
===================================================================
--- trunk/drbd/drbd_sizeof_sanity_check.c	2005-02-11 15:59:06 UTC (rev 1757)
+++ trunk/drbd/drbd_sizeof_sanity_check.c	2005-02-12 17:48:17 UTC (rev 1758)
@@ -15,10 +15,10 @@
 int sizeof_drbd_structs_sanity_check(void)
 {
 	int err = 0, s = 0;
-	SZO(struct disk_config,		 24)
+	SZO(struct disk_config,		 32)
 	SZO(struct net_config,		432)
 	SZO(struct syncer_config,	 24)
-	SZO(struct ioctl_disk_config,	 32)
+	SZO(struct ioctl_disk_config,	 40)
 	SZO(struct ioctl_net_config,	440)
 	SZO(struct ioctl_syncer_config,	 32)
 	SZO(struct ioctl_wait,		 16)

Modified: trunk/drbd/linux/drbd.h
===================================================================
--- trunk/drbd/linux/drbd.h	2005-02-11 15:59:06 UTC (rev 1757)
+++ trunk/drbd/linux/drbd.h	2005-02-12 17:48:17 UTC (rev 1758)
@@ -77,6 +77,7 @@
 	IN int      meta_device;
 	IN int      meta_index;
 	IN int      split_brain_fix;
+	const int   _pad;
 };
 
 enum disconnect_handler {



More information about the drbd-cvs mailing list