From drbd-cvs at lists.linbit.com  Sat Jan  7 20:27:28 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Sat Jan  7 20:27:29 2006
Subject: [DRBD-cvs] svn commit by phil - r2044 - in trunk: . drbd drbd/linux
	user - * Removed a bug that was introduced with the big code m
Message-ID: <20060107192728.A96C015E23@mail.linbit.com>

Author: phil
Date: 2006-01-07 20:27:25 +0100 (Sat, 07 Jan 2006)
New Revision: 2044

Modified:
   trunk/ROADMAP
   trunk/drbd/drbd_bitmap.c
   trunk/drbd/drbd_fs.c
   trunk/drbd/drbd_int.h
   trunk/drbd/drbd_main.c
   trunk/drbd/drbd_receiver.c
   trunk/drbd/drbd_strings.c
   trunk/drbd/drbd_worker.c
   trunk/drbd/linux/drbd.h
   trunk/user/Makefile
   trunk/user/drbdadm_main.c
   trunk/user/drbdsetup.c
Log:
* Removed a bug that was introduced with the big code merge in drbdadm
* Replaced the nummeric error codes of drbd_set_state() with symbolic ones.
* Removed an erronous check of drbd_set_state()


Modified: trunk/ROADMAP
===================================================================
--- trunk/ROADMAP	2005-12-29 21:58:57 UTC (rev 2043)
+++ trunk/ROADMAP	2006-01-07 19:27:25 UTC (rev 2044)
@@ -646,9 +646,7 @@
    99% DONE
 
 24 Make it possible to hot-add disk drives == Atomic configuration changes.
-   Missing: Rewrite size determination code. It needs to fail in case
-            there is already a primary node in the cluster, and the
-            to attached device is smaller than the current size.
+   Missing: Think about and test detach/attach of the primary's disk.
 
    80% DONE [ The net and disk config changes are atomic by now ]
 

Modified: trunk/drbd/drbd_bitmap.c
===================================================================
--- trunk/drbd/drbd_bitmap.c	2005-12-29 21:58:57 UTC (rev 2043)
+++ trunk/drbd/drbd_bitmap.c	2006-01-07 19:27:25 UTC (rev 2044)
@@ -596,7 +596,6 @@
  */
 int drbd_bm_read_sect(drbd_dev *mdev,unsigned long enr)
 {
-#warning check outcome of addition of sector_t/u64/s32
 	sector_t on_disk_sector = mdev->bc->md.md_offset + mdev->bc->md.bm_offset + enr;
 	int bm_words, num_words, offset, err  = 0;
 

Modified: trunk/drbd/drbd_fs.c
===================================================================
--- trunk/drbd/drbd_fs.c	2005-12-29 21:58:57 UTC (rev 2043)
+++ trunk/drbd/drbd_fs.c	2006-01-07 19:27:25 UTC (rev 2044)
@@ -48,6 +48,46 @@
 char *drbd_sec_holder = "Secondary DRBD cannot be bd_claimed ;)";
 char *drbd_m_holder = "Hands off! this is DRBD's meta data device.";
 
+
+
+/* initializes the md.*_offset members, so we are able to find
+ * the on disk meta data */
+STATIC void drbd_md_set_sector_offsets(drbd_dev *mdev,
+				       struct drbd_backing_dev *bdev)
+{
+	sector_t md_size_sect = 0;
+	switch(bdev->md_index) {
+	default:
+	case DRBD_MD_INDEX_FLEX_EXT:
+		/* just occupy the full device; unit: sectors */
+		bdev->md.md_size_sect = drbd_get_capacity(bdev->md_bdev);
+		bdev->md.md_offset = 0;
+		bdev->md.al_offset = MD_AL_OFFSET;
+		bdev->md.bm_offset = MD_BM_OFFSET;
+		break;
+	case DRBD_MD_INDEX_INTERNAL:
+	case DRBD_MD_INDEX_FLEX_INT:
+		bdev->md.md_offset = drbd_md_ss__(mdev,bdev);
+		/* al size is still fixed */
+		bdev->md.al_offset = -MD_AL_MAX_SIZE;
+                //LGE FIXME max size check missing.
+		/* we need (slightly less than) ~ this much bitmap sectors: */
+		md_size_sect = drbd_get_capacity(bdev->backing_bdev);
+		md_size_sect = ALIGN(md_size_sect,BM_SECT_PER_EXT);
+		md_size_sect = BM_SECT_TO_EXT(md_size_sect);
+		md_size_sect = ALIGN(md_size_sect,8);
+
+		/* plus the "drbd meta data super block",
+		 * and the activity log; */
+		md_size_sect += MD_BM_OFFSET;
+
+		bdev->md.md_size_sect = md_size_sect;
+		/* bitmap offset is adjusted by 'super' block size */
+		bdev->md.bm_offset   = -md_size_sect + MD_AL_OFFSET;
+		break;
+	}
+}
+
 STATIC int do_determin_dev_size(struct Drbd_Conf* mdev);
 int drbd_determin_dev_size(struct Drbd_Conf* mdev)
 {
@@ -69,7 +109,7 @@
 
 	la_size_changed = (la_size != mdev->bc->md.la_size_sect);
 
-#warning flexible device size!! is this the right thing to test?
+	//LGE: flexible device size!! is this the right thing to test?
 	md_moved = prev_first_sect != drbd_md_first_sector(mdev->bc)
 		|| prev_size       != mdev->bc->md.md_size_sect;
 
@@ -390,7 +430,7 @@
 		goto release_bdev2_fail_ioctl;
 	}
 
-	if(drbd_request_state(mdev,NS(disk,Attaching)) <= 0 ) {
+	if(drbd_request_state(mdev,NS(disk,Attaching)) < SS_Success ) {
 		retcode = StateNotAllowed;
 		goto release_bdev2_fail_ioctl;
 	}
@@ -475,7 +515,7 @@
 			nds = Inconsistent;
 		}
 		
-		if(drbd_request_state(mdev,NS(disk,nds)) > 0) {
+		if(drbd_request_state(mdev,NS(disk,nds)) >= SS_Success ) {
 			drbd_thread_start(&mdev->worker);
 		}
 	}
@@ -680,7 +720,7 @@
 	mdev->cram_hmac_tfm = tfm;
 
 	drbd_thread_start(&mdev->worker);
-	if( drbd_request_state(mdev,NS(conn,Unconnected)) > 0) {
+	if( drbd_request_state(mdev,NS(conn,Unconnected)) >= SS_Success ) {
 		drbd_thread_start(&mdev->receiver);
 	}
 
@@ -781,7 +821,7 @@
 	if(nps != disk_mask) rs.pdsk = nps;
 	r = _drbd_set_state(mdev, rs, 0);
 
-	if ( r == -2 ) {
+	if ( r == SS_NoConsistnetDisk ) {
 		if ( newstate & DontBlameDrbd && mdev->state.disk<UpToDate) {
 			rs.disk = UpToDate;
 			forced = 1;
@@ -792,8 +832,8 @@
 	ns = mdev->state;
 	spin_unlock_irq(&mdev->req_lock);
 
-	if ( r == 2 ) { rv = 0; goto fail; }
-	if ( r == -7 && nps == disk_mask ) {
+	if ( r == SS_NothingToDo ) { rv = 0; goto fail; }
+	if ( r == SS_PrimaryNOP && nps == disk_mask ) {
 		nps = drbd_try_outdate_peer(mdev);
 		if ( newstate & DontBlameDrbd && nps > Outdated ) {
 			WARN("Forced into split brain situation!\n");
@@ -801,7 +841,7 @@
 		}
 		goto retry;
 	}
-	if ( r <= 0 ) {
+	if ( r < SS_Success ) {
 		print_st_err(mdev,os,rs,r);
 		*arg = r;
 		rv = -EIO;
@@ -967,8 +1007,8 @@
 	ns = mdev->state;
 	spin_unlock_irq(&mdev->req_lock);
 
-	if( r == 2 ) { return 0; }
-	if( r <= 0 ) {
+	if( r == SS_NothingToDo ) { return 0; }
+	if( r < SS_Success ) {
 		return -ENETRESET;
 	}
 
@@ -1007,13 +1047,13 @@
 	ns = mdev->state;
 	spin_unlock_irq(&mdev->req_lock);
 
-	if( r == 2 ) return 0;
+	if( r == SS_NothingToDo ) return 0;
 	if( r == -999 ) {
 		return -EINVAL;
 	}
 	after_state_ch(mdev,os,ns); // TODO decide if neccesarry.
 
-	if( r <= 0 ) {
+	if( r < SS_Success ) {
 		err = put_user(r, reason);
 		if(!err) err=-EIO;
 		return err;
@@ -1062,8 +1102,8 @@
 	spin_unlock_irq(&mdev->req_lock);
 	after_state_ch(mdev,os,ns);
 
-	if ( r == 2 )  return 0;
-	if ( r == -7 ) {
+	if ( r == SS_NothingToDo )  return 0;
+	if ( r == SS_PrimaryNOP ) {
 		drbd_send_short_cmd(mdev, OutdateRequest);
 		wait_event(mdev->cstate_wait,
 			   mdev->state.pdsk <= Outdated ||
@@ -1073,7 +1113,7 @@
 		r = drbd_request_state(mdev,NS(conn,StandAlone));
 	}
 
-	if( r <= 0 ) return -ENODATA;
+	if( r < SS_Success ) return -ENODATA;
 
 	if ( mdev->cram_hmac_tfm ) {
 		crypto_free_tfm(mdev->cram_hmac_tfm);
@@ -1292,8 +1332,8 @@
 		r = drbd_request_state(mdev,NS2(disk,Inconsistent,
 					        conn,WFBitMapT));
 
-		if( r == 2 ) { break; }
-		if( r <= 0 ) {
+		if( r == SS_NothingToDo ) { break; }
+		if( r < SS_Success ) {
 			err = -EINPROGRESS;
 			break;
 		}
@@ -1332,8 +1372,8 @@
 		r = drbd_request_state(mdev,NS2(pdsk,Inconsistent,
 					        conn,WFBitMapS));
 
-		if( r == 2 ) { break; }
-		if( r <= 0 ) {
+		if( r == SS_NothingToDo ) { break; }
+		if( r < SS_Success ) {
 			err = -EINPROGRESS;
 			break;
 		}

Modified: trunk/drbd/drbd_int.h
===================================================================
--- trunk/drbd/drbd_int.h	2005-12-29 21:58:57 UTC (rev 2043)
+++ trunk/drbd/drbd_int.h	2006-01-07 19:27:25 UTC (rev 2044)
@@ -1310,44 +1310,7 @@
 	}
 }
 
-/* initializes the md.*_offset members, so we are able to find
- * the on disk meta data */
-static inline void drbd_md_set_sector_offsets(drbd_dev *mdev,
-					      struct drbd_backing_dev *bdev)
-{
-	sector_t md_size_sect = 0;
-	bdev->md.md_offset = drbd_md_ss__(mdev,bdev);
-	switch(bdev->md_index) {
-	default:
-	case DRBD_MD_INDEX_FLEX_EXT:
-		/* just occupy the full device; unit: sectors */
-		bdev->md.md_size_sect = drbd_get_capacity(bdev->md_bdev);
-		bdev->md.md_offset = 0;
-		bdev->md.al_offset = MD_AL_OFFSET;
-		bdev->md.bm_offset = MD_BM_OFFSET;
-		break;
-	case DRBD_MD_INDEX_INTERNAL:
-	case DRBD_MD_INDEX_FLEX_INT:
-		/* al size is still fixed */
-		bdev->md.al_offset = -MD_AL_MAX_SIZE;
-#warning FIXME max size check missing.
-		/* we need (slightly less than) ~ this much bitmap sectors: */
-		md_size_sect = drbd_get_capacity(bdev->backing_bdev);
-		md_size_sect = ALIGN(md_size_sect,BM_SECT_PER_EXT);
-		md_size_sect = BM_SECT_TO_EXT(md_size_sect);
-		md_size_sect = ALIGN(md_size_sect,8);
 
-		/* plus the "drbd meta data super block",
-		 * and the activity log; */
-		md_size_sect += MD_BM_OFFSET;
-
-		bdev->md.md_size_sect = md_size_sect;
-		/* bitmap offset is adjusted by 'super' block size */
-		bdev->md.bm_offset   = -md_size_sect + MD_AL_OFFSET;
-		break;
-	}
-}
-
 static inline void
 _drbd_queue_work(struct drbd_work_queue *q, struct drbd_work *w)
 {

Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c	2005-12-29 21:58:57 UTC (rev 2043)
+++ trunk/drbd/drbd_main.c	2006-01-07 19:27:25 UTC (rev 2044)
@@ -563,13 +563,14 @@
 /* PRE TODO: Should return ernno numbers from the pre-state-change checks. */
 int _drbd_set_state(drbd_dev* mdev, drbd_state_t ns,enum chg_state_flags flags)
 {
-	MUST_HOLD(&mdev->req_lock);
 	drbd_state_t os;
-	int rv=1,warn_sync_abort=0;
+	int rv=SS_Success, warn_sync_abort=0;
 
+	MUST_HOLD(&mdev->req_lock);
+
 	os = mdev->state;
 
-	if( ns.i == os.i ) return 2;
+	if( ns.i == os.i ) return SS_NothingToDo;
 
 	/*  State sanitising  */
 	if( ns.conn < Connected ) {
@@ -643,40 +644,39 @@
 
 		if(inc_net(mdev)) {
 			if( !mdev->net_conf->two_primaries &&
-			    ns.role == Primary && ns.peer == Primary ) rv=-1;
+			    ns.role == Primary && ns.peer == Primary ) 
+				rv=SS_TowPrimaries;
 			dec_net(mdev);
 		}
 
 		if( rv <= 0 ) /* already found a reason to abort */;
 		else if( ns.role == Primary && ns.conn < Connected &&
-			 ns.disk <= Outdated ) rv=-2;
+			 ns.disk <= Outdated ) rv=SS_NoConsistnetDisk;
 
 		else if( test_bit(SPLIT_BRAIN_FIX,&mdev->flags) &&
 			 ns.role == Primary && ns.conn < Connected &&
-			 ns.pdsk >= DUnknown ) rv=-7;
+			 ns.pdsk >= DUnknown ) rv=SS_PrimaryNOP;
 
 		else if( ns.role == Primary && ns.disk <= Inconsistent &&
-			 ns.pdsk <= Inconsistent ) rv=-2;
+			 ns.pdsk <= Inconsistent ) rv=SS_NoConsistnetDisk;
 
-		else if( ns.peer == Primary && ns.pdsk <= Inconsistent )
-			rv=-3;
-
 		else if( ns.conn > Connected &&
-			 ns.disk < UpToDate && ns.pdsk < UpToDate ) rv=-4;
+			 ns.disk < UpToDate && ns.pdsk < UpToDate ) 
+			rv=SS_BothInconsistent;
 
 		else if( ns.conn > Connected &&
 			 (ns.disk == Diskless || ns.pdsk == Diskless ) )
-			rv=-5;
+			rv=SS_SyncingDiskless;
 
 		else if( (ns.conn == Connected ||
 			  ns.conn == SkippedSyncS ||
 			  ns.conn == WFBitMapS ||
 			  ns.conn == SyncSource ||
 			  ns.conn == PausedSyncS) &&
-			 ns.disk == Outdated ) rv=-6;
+			 ns.disk == Outdated ) rv=SS_ConnectedOutdates;
 	}
 
-	if(rv <= 0) {
+	if(rv < SS_Success) {
 		if( flags & ChgStateVerbose ) print_st_err(mdev,os,ns,rv);
 		return rv;
 	}
@@ -2148,6 +2148,10 @@
 	printk(KERN_ERR "DRBD_MAX_SECTORS_FLEX = %llu\n",DRBD_MAX_SECTORS_FLEX);
 	return -EBUSY;
 #endif
+#ifdef __arch_um__
+	printk(KERN_INFO "drbd_module = 0x%p core = 0x%p\n",
+	       THIS_MODULE,THIS_MODULE->module_core);
+#endif
 
 	if (sizeof(Drbd_HandShake_Packet) != 80) {
 		printk(KERN_ERR DEVICE_NAME
@@ -2383,6 +2387,9 @@
 	sector_t sector;
 	int i;
 
+	if(!mdev->bc) return; // because of drbd_check_al_size(mdev) in 
+			      // drbd_ioctl_set_disk() should be removed....
+
 	ERR_IF(!inc_md_only(mdev,Attaching)) return;
 
 	down(&mdev->md_io_mutex);

Modified: trunk/drbd/drbd_receiver.c
===================================================================
--- trunk/drbd/drbd_receiver.c	2005-12-29 21:58:57 UTC (rev 2043)
+++ trunk/drbd/drbd_receiver.c	2006-01-07 19:27:25 UTC (rev 2044)
@@ -635,7 +635,7 @@
 	D_ASSERT(mdev->state.conn > StandAlone);
 	D_ASSERT(!mdev->data.socket);
 
-	if(drbd_request_state(mdev,NS(conn,WFConnection)) <= 0 ) return 0;
+	if(drbd_request_state(mdev,NS(conn,WFConnection)) < SS_Success ) return 0;
 
 	clear_bit(UNIQUE, &mdev->flags);
 	while(1) {
@@ -705,7 +705,7 @@
 	mdev->meta.socket = msock;
 	mdev->last_received = jiffies;
 
-	if(drbd_request_state(mdev,NS(conn,WFReportParams)) <= 0) return 0;
+	if(drbd_request_state(mdev,NS(conn,WFReportParams)) < SS_Success) return 0;
 	D_ASSERT(mdev->asender.task == NULL);
 
 	h = drbd_do_handshake(mdev);
@@ -1875,7 +1875,7 @@
 
 		if(nconn == conn_mask) return FALSE;
 
-		if(drbd_request_state(mdev,NS(conn,nconn)) <= 0) {
+		if(drbd_request_state(mdev,NS(conn,nconn)) < SS_Success) {
 			drbd_force_state(mdev,NS(conn,StandAlone));
 			drbd_thread_stop_nowait(&mdev->receiver);
 			return FALSE;
@@ -1970,7 +1970,7 @@
 	spin_unlock_irq(&mdev->req_lock);
 	after_state_ch(mdev,os,ns);
 
-	if(rv <= 0) {
+	if(rv < SS_Success) {
 		drbd_force_state(mdev,NS(conn,StandAlone));
 		drbd_thread_stop_nowait(&mdev->receiver);
 		return FALSE;
@@ -2044,7 +2044,7 @@
 		ok = drbd_send_bitmap(mdev);
 		if (!ok) goto out;
 		ok = drbd_request_state(mdev,NS(conn,WFSyncUUID));
-		D_ASSERT( ok == 1 );
+		D_ASSERT( ok == SS_Success );
 	} else {
 		ERR("unexpected cstate (%s) in receive_bitmap\n",
 		    conns_to_name(mdev->state.conn));
@@ -2130,9 +2130,9 @@
 	drbd_bm_set_all(mdev);
 	drbd_bm_write(mdev);
 	ok = drbd_request_state(mdev,NS(conn,WFSyncUUID));
-	D_ASSERT( ok == 1 );
+	D_ASSERT( ok == SS_Success );
 	drbd_bm_unlock(mdev);
-	return ok == 1 ? TRUE : FALSE;
+	return ok == SS_Success ? TRUE : FALSE;
 }
 
 STATIC int receive_BecomeSyncSource(drbd_dev *mdev, Drbd_Header *h)
@@ -2198,7 +2198,7 @@
 
 	r = drbd_request_state(mdev,NS2(pdsk,Outdated,conn,TearDown));
 	WARN("r=%d\n",r);
-	D_ASSERT(r >= 0);
+	D_ASSERT(r >= SS_Success);
 	drbd_md_write(mdev); // because drbd_request_state created a new UUID.
 
 	return TRUE;

Modified: trunk/drbd/drbd_strings.c
===================================================================
--- trunk/drbd/drbd_strings.c	2005-12-29 21:58:57 UTC (rev 2043)
+++ trunk/drbd/drbd_strings.c	2006-01-07 19:27:25 UTC (rev 2044)
@@ -61,13 +61,14 @@
 };
 
 static const char *drbd_state_sw_errors[] = {
-	[1] = "Multiple primaries now allowed by config",
-	[2] = "Refusing to be Primary without at least one consistent disk",
-	[3] = "Refusing to make peer Primary without disk",
-	[4] = "Refusing to be inconsistent on both nodes",
-	[5] = "Refusing to be syncing and diskless",
-	[6] = "Refusing to be Outdated while Connected",
-	[7] = "Refusing to be Primary while peer is not outdated",
+	[-SS_TowPrimaries] = "Multiple primaries now allowed by config",
+	[-SS_NoConsistnetDisk] = 
+		"Refusing to be Primary without at least one consistent disk",
+	[-SS_REMOVE_ME] = "Refusing to make peer Primary without disk",
+	[-SS_BothInconsistent] = "Refusing to be inconsistent on both nodes",
+	[-SS_SyncingDiskless] = "Refusing to be syncing and diskless",
+	[-SS_ConnectedOutdates] = "Refusing to be Outdated while Connected",
+	[-SS_PrimaryNOP] = "Refusing to be Primary while peer is not outdated",
 };
 
 const char* conns_to_name(drbd_conns_t s) {
@@ -86,8 +87,8 @@
 		               : drbd_disk_s_names[s];
 }
 
-const char* set_st_err_name(int err) {
-	return err < -7 ? "TOO_SMALL" :
-	       err > -1 ? "TOO_LARGE"
+const char* set_st_err_name(set_st_err_t err) {
+	return err < SS_PrimaryNOP ? "TOO_SMALL" :
+	       err > SS_TowPrimaries ? "TOO_LARGE"
 		        : drbd_state_sw_errors[-err];
 }

Modified: trunk/drbd/drbd_worker.c
===================================================================
--- trunk/drbd/drbd_worker.c	2005-12-29 21:58:57 UTC (rev 2043)
+++ trunk/drbd/drbd_worker.c	2006-01-07 19:27:25 UTC (rev 2044)
@@ -596,7 +596,7 @@
 			mod_timer(&mdev->resync_timer,jiffies);
 		}
 	}
-	return r != 2;
+	return r != SS_NothingToDo;
 }
 
 /** 
@@ -639,7 +639,7 @@
 		INFO("Resync suspended by %s.\n",reason_txt[reason]);
 	}
 
-	return r != 2;
+	return r != SS_NothingToDo;
 }
 
 STATIC int _drbd_may_sync_now(drbd_dev *mdev)
@@ -794,7 +794,7 @@
 
 	r = _drbd_set_state(mdev,ns,ChgStateVerbose);
 
-	if ( r==1 ) {
+	if ( r == SS_Success ) {
 		mdev->rs_total     =
 		mdev->rs_mark_left = drbd_bm_total_weight(mdev);
 		mdev->rs_paused    = 0;
@@ -804,7 +804,7 @@
 	}
 	drbd_global_unlock();
 
-	if ( r==1 ) {
+	if ( r == SS_Success ) {
 		after_state_ch(mdev,os,ns);
 
 		INFO("Began resync as %s (will sync %lu KB [%lu bits set]).\n",

Modified: trunk/drbd/linux/drbd.h
===================================================================
--- trunk/drbd/linux/drbd.h	2005-12-29 21:58:57 UTC (rev 2043)
+++ trunk/drbd/linux/drbd.h	2006-01-07 19:27:25 UTC (rev 2044)
@@ -254,11 +254,24 @@
 	unsigned int i;
 } drbd_state_t;
 
+typedef enum {
+	SS_NothingToDo=2,
+	SS_Success=1,
+	SS_UnknownError=0,
+	SS_TowPrimaries=-1,
+	SS_NoConsistnetDisk=-2,
+	SS_REMOVE_ME=-3,
+	SS_BothInconsistent=-4,
+	SS_SyncingDiskless=-5,
+	SS_ConnectedOutdates=-6,
+	SS_PrimaryNOP=-7
+} set_st_err_t;
+
 /* from drbd_strings.c */
 extern const char* conns_to_name(drbd_conns_t);
 extern const char* roles_to_name(drbd_role_t);
 extern const char* disks_to_name(drbd_disks_t);
-extern const char* set_st_err_name(int);
+extern const char* set_st_err_name(set_st_err_t);
 
 #ifndef BDEVNAME_SIZE
 # define BDEVNAME_SIZE 32

Modified: trunk/user/Makefile
===================================================================
--- trunk/user/Makefile	2005-12-29 21:58:57 UTC (rev 2043)
+++ trunk/user/Makefile	2006-01-07 19:27:25 UTC (rev 2044)
@@ -17,7 +17,7 @@
 # the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 #
 
-CFLAGS = -g -O2 -c -W -Wall -I../drbd -Werror
+CFLAGS = -g -O2 -c -W -Wall -I../drbd
 CC = gcc
 
 drbdadm-obj = drbdadm_scanner.o drbdadm_parser.o drbdadm_main.o \

Modified: trunk/user/drbdadm_main.c
===================================================================
--- trunk/user/drbdadm_main.c	2005-12-29 21:58:57 UTC (rev 2043)
+++ trunk/user/drbdadm_main.c	2006-01-07 19:27:25 UTC (rev 2044)
@@ -458,11 +458,6 @@
 {
   char **path;
 
-  if (drbdsetup) {
-    free(drbdsetup);
-    drbdsetup = NULL;
-  }
-
   path=pathes;
   while(*path) {
     if(access(*path,X_OK)==0) {
@@ -1301,6 +1296,7 @@
   struct d_resource *res,*tmp;
   char *env_drbd_nodename = NULL;
 
+  drbdsetup=NULL;
   drbdmeta=NULL;
   dry_run=0;
   yyin=NULL;

Modified: trunk/user/drbdsetup.c
===================================================================
--- trunk/user/drbdsetup.c	2005-12-29 21:58:57 UTC (rev 2043)
+++ trunk/user/drbdsetup.c	2006-01-07 19:27:25 UTC (rev 2044)
@@ -1047,7 +1047,7 @@
       if(err==EIO) 
 	{
 	  fprintf(stderr,"%s\n",set_st_err_name(reason));
-	  if(reason == -2) return 17;
+	  if(reason == SS_NoConsistnetDisk) return 17;
 	}
       return 20;
     }

From drbd-cvs at lists.linbit.com  Mon Jan  9 21:29:28 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Mon Jan  9 21:29:30 2006
Subject: [DRBD-cvs] svn commit by phil - r2045 - trunk/drbd - missing commit
Message-ID: <20060109202928.EEC4416275@mail.linbit.com>

Author: phil
Date: 2006-01-09 21:29:28 +0100 (Mon, 09 Jan 2006)
New Revision: 2045

Modified:
   trunk/drbd/drbd_receiver.c
Log:
missing commit


Modified: trunk/drbd/drbd_receiver.c
===================================================================
--- trunk/drbd/drbd_receiver.c	2006-01-07 19:27:25 UTC (rev 2044)
+++ trunk/drbd/drbd_receiver.c	2006-01-09 20:29:28 UTC (rev 2045)
@@ -1951,13 +1951,15 @@
 			// we want resync, peer has not yet decided to sync...
 			drbd_send_uuids(mdev);
 			drbd_send_state(mdev);
-		} else if ( peer_state.disk == Attaching ) {
-			// Peer should promote from Attaching to UpToDate.
-			drbd_send_state(mdev);
-			peer_state.disk = UpToDate;
 		}
 	}
 
+        if ( peer_state.disk == Attaching ) {
+		// Peer should promote from Attaching to UpToDate.
+		drbd_send_state(mdev);
+		peer_state.disk = UpToDate;
+	}
+
 	spin_lock_irq(&mdev->req_lock);
 	os = mdev->state;
 	ns.i = mdev->state.i;

From drbd-cvs at lists.linbit.com  Mon Jan  9 23:06:31 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Mon Jan  9 23:06:33 2006
Subject: [DRBD-cvs] svn commit by phil - r2046 - trunk/drbd - Worked on the
	following scenario: Secondary / Secondary
Message-ID: <20060109220631.679D216275@mail.linbit.com>

Author: phil
Date: 2006-01-09 23:06:29 +0100 (Mon, 09 Jan 2006)
New Revision: 2046

Modified:
   trunk/drbd/drbd_fs.c
   trunk/drbd/drbd_main.c
   trunk/drbd/drbd_receiver.c
Log:
Worked on the following scenario:
   Secondary / Secondary

1 The disk of the right node gets removed by 'drbdadm detach'
2 The left node gets promoted to primary and devoted to secondary again.
  (=new UUID)
3 The right node gets it disk again with 'drbdadm attach'

Now, this causes a resync, just as expected.


Modified: trunk/drbd/drbd_fs.c
===================================================================
--- trunk/drbd/drbd_fs.c	2006-01-09 20:29:28 UTC (rev 2045)
+++ trunk/drbd/drbd_fs.c	2006-01-09 22:06:29 UTC (rev 2046)
@@ -880,8 +880,9 @@
 		bd_release(mdev->this_bdev);
 		mdev->this_bdev->bd_disk = mdev->vdisk;
 
-		if ( (mdev->state.conn < WFReportParams &&
-		      mdev->bc->md.uuid[Bitmap] == 0) || forced ) {
+		if ( ( ( mdev->state.conn < Connected ||
+			 mdev->state.pdsk <= Attaching ) &&
+		       mdev->bc->md.uuid[Bitmap] == 0) || forced ) {
 			drbd_uuid_new_current(mdev);
 		}
 	}

Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c	2006-01-09 20:29:28 UTC (rev 2045)
+++ trunk/drbd/drbd_main.c	2006-01-09 22:06:29 UTC (rev 2046)
@@ -764,10 +764,13 @@
 	}
 
 	/*  Lost contact to peer's copy of the data  */
-	if (ns.role == Primary &&
-	    os.pdsk > DUnknown && ns.pdsk <= DUnknown ) {
-		/* Only do it if we have not yet done it... */
-		if ( mdev->bc->md.uuid[Bitmap] == 0 ) {
+	if ( os.pdsk > DUnknown && ns.pdsk <= DUnknown ) {
+		if ( mdev->p_uuid ) {
+			kfree(mdev->p_uuid);
+			mdev->p_uuid = NULL;
+		}
+		if (ns.role == Primary && mdev->bc->md.uuid[Bitmap] == 0 ) {
+			/* Only do it if we have not yet done it... */
 			INFO("Creating new current UUID\n");
 			drbd_uuid_new_current(mdev);
 		}

Modified: trunk/drbd/drbd_receiver.c
===================================================================
--- trunk/drbd/drbd_receiver.c	2006-01-09 20:29:28 UTC (rev 2045)
+++ trunk/drbd/drbd_receiver.c	2006-01-09 22:06:29 UTC (rev 2046)
@@ -1870,8 +1870,9 @@
 	drbd_determin_dev_size(mdev);
 	drbd_bm_unlock(mdev); // }
 
-	if (mdev->p_uuid && mdev->state.conn <= Connected ) {
+	if (mdev->p_uuid && mdev->state.conn <= Connected && inc_local(mdev)) {
 		nconn=drbd_sync_handshake(mdev,mdev->state.peer);
+		dec_local(mdev);
 
 		if(nconn == conn_mask) return FALSE;
 
@@ -1940,8 +1941,10 @@
 
 	peer_state.i = be32_to_cpu(p->state);
 
-	if (mdev->p_uuid && mdev->state.conn <= Connected ) {
+	if (mdev->p_uuid && mdev->state.conn <= Connected && 
+	    inc_md_only(mdev,Attaching) ) {
 		nconn=drbd_sync_handshake(mdev,peer_state.role);
+		dec_local(mdev);
 
 		if(nconn == conn_mask) return FALSE;
 	}
@@ -1954,7 +1957,7 @@
 		}
 	}
 
-        if ( peer_state.disk == Attaching ) {
+        if ( peer_state.disk == Attaching && nconn == Connected ) {
 		// Peer should promote from Attaching to UpToDate.
 		drbd_send_state(mdev);
 		peer_state.disk = UpToDate;

From drbd-cvs at lists.linbit.com  Tue Jan 10 15:30:20 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Tue Jan 10 15:30:22 2006
Subject: [DRBD-cvs] svn commit by phil - r2047 - in trunk: drbd user - * Two
	fixes for the manual recovery after a split-brain
Message-ID: <20060110143021.15EEA16116@mail.linbit.com>

Author: phil
Date: 2006-01-10 15:30:17 +0100 (Tue, 10 Jan 2006)
New Revision: 2047

Modified:
   trunk/drbd/drbd_main.c
   trunk/drbd/drbd_receiver.c
   trunk/user/drbdadm_main.c
Log:

* Two fixes for the manual recovery after a split-brain-situation
  * drbdadm does now pass the "--discard-my-data" to drbdsetup.
  * the "mdev->net_conf->want_lose" flags get honoured now.
    
* Various fixes to make detach/attach of the pimarie's disk possible.
  * The secondary creates a new current-UUID in that case.
  * The primary may go into Primary-SyncTarget state in that case



Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c	2006-01-09 22:06:29 UTC (rev 2046)
+++ trunk/drbd/drbd_main.c	2006-01-10 14:30:17 UTC (rev 2047)
@@ -773,7 +773,21 @@
 			/* Only do it if we have not yet done it... */
 			INFO("Creating new current UUID\n");
 			drbd_uuid_new_current(mdev);
+			drbd_md_write(mdev);
 		}
+		if (ns.peer == Primary ) { 
+ 			/* Note: The condition ns.peer == Primary implies
+			         that we are connected. Otherwise it would
+				 be ns.peer == Unknown. */
+ 			/* Our peer lost its disk.
+			   Not rotation into BitMap-UUID! A FullSync is 
+			   required after a primary detached from it disk! */
+			u64 uuid;
+			INFO("Creating new current UUID [no BitMap]\n");
+			get_random_bytes(&uuid, sizeof(u64));
+			drbd_uuid_set(mdev, Current, uuid);
+			drbd_md_write(mdev);
+		}
 	}
 
 	/*  Removed disk, tell peer.  */

Modified: trunk/drbd/drbd_receiver.c
===================================================================
--- trunk/drbd/drbd_receiver.c	2006-01-09 22:06:29 UTC (rev 2046)
+++ trunk/drbd/drbd_receiver.c	2006-01-10 14:30:17 UTC (rev 2047)
@@ -1655,18 +1655,24 @@
 		} else {
 			hg = drbd_asb_recover_1p(mdev);
 		}
-		if ( hg == -100 ) {
-			if(mdev->net_conf->want_lose && !mdev->p_uuid[UUID_FLAGS]){
-				hg = -1;
-			}
-			if(!mdev->net_conf->want_lose && mdev->p_uuid[UUID_FLAGS]){
-				hg = 1;
-			}
-		} else {
+		if ( abs(hg) < 100 ) {
 			WARN("Split-Brain detected, automatically solved.\n");
 		}
 	}
 
+	if ( hg == -100 ) {
+		if(mdev->net_conf->want_lose && !mdev->p_uuid[UUID_FLAGS]) {
+			hg = -1;
+		}
+		if(!mdev->net_conf->want_lose && mdev->p_uuid[UUID_FLAGS]) {
+			hg = 1;
+		}
+
+		if ( abs(hg) < 100 ) {
+			WARN("Split-Brain detected, manually solved.\n");
+		}
+	}
+
 	if (hg == -1000) {
 		ALERT("Unrelated data, dropping connection!\n");
 		drbd_force_state(mdev,NS(conn,StandAlone));
@@ -1687,7 +1693,8 @@
 		drbd_thread_stop_nowait(&mdev->receiver);
 		return conn_mask;
 	}
-	if (hg < 0 && mdev->state.role == Primary ) {
+	if (hg < 0 && 
+	    mdev->state.role == Primary && mdev->state.disk != Attaching ) {
 		ERR("I shall become SyncTarget, but I am primary!\n");
 		drbd_force_state(mdev,NS(conn,StandAlone));
 		drbd_thread_stop_nowait(&mdev->receiver);

Modified: trunk/user/drbdadm_main.c
===================================================================
--- trunk/user/drbdadm_main.c	2006-01-09 22:06:29 UTC (rev 2046)
+++ trunk/user/drbdadm_main.c	2006-01-10 14:30:17 UTC (rev 2047)
@@ -719,7 +719,7 @@
 {
   char* argv[20];
   struct d_option* opt;
-
+  int i;
   int argc=0;
 
   argv[argc++]=drbdsetup;
@@ -742,6 +742,11 @@
 
   opt=res->net_options;
   make_options(opt);
+
+  for(i=0;i<soi;i++) {
+    argv[argc++]=setup_opts[i];
+  }
+
   argv[argc++]=0;
 
   return m_system(argv,SLEEPS_SHORT);

From drbd-cvs at lists.linbit.com  Sat Jan 14 18:28:04 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Sat Jan 14 18:28:07 2006
Subject: [DRBD-cvs] svn commit by phil - r2048 - in trunk: . drbd -
	Implemented item 27 of the ROADMAP, removed drbd_md_wri
Message-ID: <20060114172804.1B03116563@mail.linbit.com>

Author: phil
Date: 2006-01-14 18:28:02 +0100 (Sat, 14 Jan 2006)
New Revision: 2048

Modified:
   trunk/ROADMAP
   trunk/drbd/drbd_fs.c
   trunk/drbd/drbd_int.h
   trunk/drbd/drbd_main.c
   trunk/drbd/drbd_receiver.c
   trunk/drbd/drbd_worker.c
Log:
Implemented item 27 of the ROADMAP, removed drbd_md_write() and replaced
this with drbd_md_sync(). I guess this was Lars' idea when he created
the MD_DIRTY flag.

In case something is modified that is should be writeen to the meta-data
super block later, we mark this by calling drbd_md_mark_dirty(). 

A timer ensures that latest one second later it is synced to this. The
timer is intended as debugging aid, to find the code pathes where the call
to drbd_md_sync() is missing.



Modified: trunk/ROADMAP
===================================================================
--- trunk/ROADMAP	2006-01-10 14:30:17 UTC (rev 2047)
+++ trunk/ROADMAP	2006-01-14 17:28:02 UTC (rev 2048)
@@ -660,6 +660,25 @@
    that always keeps the on disk-metadata up-to-date implicit. 
    Calling drbd_md_write() explicit is too errorprone.
 
+   90% DONE [ Needs testing, drbd_md_sync() is the new call ]
+
+28 Implement a kind of 'call home', a single HTTP get request, that
+   gets counted in a data base. The initiator calculates a simple
+   hash over the machine and resource names. Each time a meta-data
+   set gets generated, the 'call home' is initiated. The user might
+   of course opt out of this.
+
+29 Make all the commands to have 'expert' switches to also show
+   the hidden sub-commands in the ussage.
+
+30 The current drbdadm_scanner is 1MB in source and as binary.
+   Use a _basic_ flex scanner, and a hand written parser for superb
+   errror reporting.
+
+31 Resizing several GB results in ko-count timeouts, maybe since the
+   secondary node does the enlargement of the bitmap in the receiver (?)
+
+
 plus-banches:
 ----------------------
 

Modified: trunk/drbd/drbd_fs.c
===================================================================
--- trunk/drbd/drbd_fs.c	2006-01-10 14:30:17 UTC (rev 2047)
+++ trunk/drbd/drbd_fs.c	2006-01-14 17:28:02 UTC (rev 2048)
@@ -87,7 +87,8 @@
 		break;
 	}
 }
-
+/* You should call drbd_md_sync() after calling this.
+ */
 STATIC int do_determin_dev_size(struct Drbd_Conf* mdev);
 int drbd_determin_dev_size(struct Drbd_Conf* mdev)
 {
@@ -122,7 +123,7 @@
 		drbd_al_shrink(mdev); // All extents inactive.
 		drbd_bm_write(mdev);  // write bitmap
 		// Write mdev->bc->md.la_size_sect to [possibly new position on] disk.
-		drbd_md_write(mdev);
+		drbd_md_mark_dirty(mdev);
 	}
   out:
 	lc_unlock(mdev->act_log);
@@ -230,7 +231,8 @@
  * drbd_check_al_size:
  * checks that the al lru is of requested size, and if neccessary tries to
  * allocate a new one. returns -EBUSY if current al lru is still used,
- * -ENOMEM when allocation failed, and 0 on success.
+ * -ENOMEM when allocation failed, and 0 on success. You should call
+ * drbd_md_sync() after you called this function.
  */
 STATIC int drbd_check_al_size(drbd_dev *mdev)
 {
@@ -276,7 +278,7 @@
 	} else {
 		if (t) lc_free(t);
 	}
-	drbd_md_write(mdev);
+	drbd_md_mark_dirty(mdev);	//we changed mdev->act_log->nr_elemens
 	return 0;
 }
 
@@ -478,7 +480,6 @@
 		drbd_bm_set_all(mdev);
 		drbd_bm_write(mdev);
 		drbd_md_clear_flag(mdev,MDF_FullSync);
-		drbd_md_write(mdev);
 	} else {
 		/* FIXME this still does not propagate io errors! */
 		drbd_bm_read(mdev);
@@ -521,6 +522,8 @@
 	}
 
 	drbd_bm_unlock(mdev);
+	drbd_md_sync(mdev);
+
 	return 0;
 
  release_bdev3_fail_ioctl:
@@ -866,8 +869,6 @@
 	 * but that means someone is misusing DRBD...
 	 * */
 
-	set_bit(MD_DIRTY,&mdev->flags); // we are changing state!
-
 	if (newstate & Secondary) {
 		set_disk_ro(mdev->vdisk, TRUE );
 	} else {
@@ -890,8 +891,6 @@
 	if(mdev->state.disk > Diskless && (newstate & Secondary)) {
 		drbd_al_to_on_disk_bm(mdev);
 	}
-	/* Primary indicator has changed in any case. */
-	drbd_md_write(mdev);
 
 	if (mdev->state.conn >= WFReportParams) {
 		/* if this was forced, we should consider sync */
@@ -987,6 +986,7 @@
 	mdev->sync_conf.al_extents = sc.al_extents;
 
 	err = drbd_check_al_size(mdev);
+	drbd_md_sync(mdev);
 	if (err) return err;
 
 	if (mdev->state.conn >= Connected)
@@ -1052,7 +1052,7 @@
 	if( r == -999 ) {
 		return -EINVAL;
 	}
-	after_state_ch(mdev,os,ns); // TODO decide if neccesarry.
+	after_state_ch(mdev,os,ns);
 
 	if( r < SS_Success ) {
 		err = put_user(r, reason);
@@ -1060,8 +1060,6 @@
 		return err;
 	}
 
-	drbd_md_write(mdev);
-
 	return 0;
 }
 
@@ -1230,7 +1228,7 @@
 		mdev->bc->u_size = (sector_t)(u64)arg;
 		drbd_bm_lock(mdev);
 		drbd_determin_dev_size(mdev);
-		drbd_md_write(mdev); // Write mdev->bc->md.la_size_sect to disk.
+		drbd_md_sync(mdev);
 		drbd_bm_unlock(mdev);
 		if (mdev->state.conn == Connected) {
 			drbd_send_uuids(mdev); // to start sync...
@@ -1348,13 +1346,13 @@
 		drbd_bm_lock(mdev); // racy...
 
 		drbd_md_set_flag(mdev,MDF_FullSync);
-		drbd_md_write(mdev);
+		drbd_md_sync(mdev);
 
 		drbd_bm_set_all(mdev);
 		drbd_bm_write(mdev);
 
 		drbd_md_clear_flag(mdev,MDF_FullSync);
-		drbd_md_write(mdev);
+		drbd_md_sync(mdev);
 
 		if (drbd_send_short_cmd(mdev,BecomeSyncSource)) {
 			int ok;
@@ -1380,7 +1378,7 @@
 		}
 
 		drbd_md_set_flag(mdev,MDF_FullSync);
-		drbd_md_write(mdev);
+		drbd_md_sync(mdev);
 
 		/* avoid races with set_in_sync
 		 * for successfull mirrored writes
@@ -1394,7 +1392,6 @@
 		drbd_bm_write(mdev);
 
 		drbd_md_clear_flag(mdev,MDF_FullSync);
-		drbd_md_write(mdev);
 
 		drbd_send_uuids(mdev);
 		drbd_send_short_cmd(mdev,BecomeSyncTarget);

Modified: trunk/drbd/drbd_int.h
===================================================================
--- trunk/drbd/drbd_int.h	2006-01-10 14:30:17 UTC (rev 2047)
+++ trunk/drbd/drbd_int.h	2006-01-14 17:28:02 UTC (rev 2048)
@@ -680,7 +680,7 @@
 
 	u64 la_size_sect;	/* last agreed size, unit sectors */
 	u64 uuid[UUID_SIZE];
-	unsigned long flags;
+	u32 flags;
 	u32 md_size_sect;
 
 	s32 al_offset;	/* signed relative sector offset to al area */
@@ -729,8 +729,10 @@
 	volatile unsigned int ko_count;
 	struct drbd_work  resync_work,
 			  barrier_work,
-			  unplug_work;
+			  unplug_work,
+	                  md_sync_work;
 	struct timer_list resync_timer;
+	struct timer_list md_sync_timer;
 
 	drbd_state_t state;
 	wait_queue_head_t cstate_wait; // TODO Rename into "misc_wait".
@@ -862,7 +864,7 @@
 extern void drbd_mdev_cleanup(drbd_dev *mdev);
 
 // drbd_meta-data.c (still in drbd_main.c)
-extern void drbd_md_write(drbd_dev *mdev);
+extern void drbd_md_sync(drbd_dev *mdev);
 extern int  drbd_md_read(drbd_dev *mdev, struct drbd_backing_dev * bdev);
 // maybe define them below as inline?
 extern void drbd_uuid_set(drbd_dev *mdev,int idx, u64 val);
@@ -872,6 +874,7 @@
 extern void drbd_md_set_flag(drbd_dev *mdev, int flags);
 extern void drbd_md_clear_flag(drbd_dev *mdev, int flags);
 extern int drbd_md_test_flag(drbd_dev *mdev, int flag);
+extern void drbd_md_mark_dirty(drbd_dev *mdev);
 
 /* Meta data layout
    We reserve a 128MB Block (4k aligned)

Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c	2006-01-10 14:30:17 UTC (rev 2047)
+++ trunk/drbd/drbd_main.c	2006-01-14 17:28:02 UTC (rev 2048)
@@ -91,6 +91,8 @@
 STATIC int drbd_open(struct inode *inode, struct file *file);
 STATIC int drbd_close(struct inode *inode, struct file *file);
 STATIC int w_after_state_ch(drbd_dev *mdev, struct drbd_work *w, int unused);
+STATIC int w_md_sync(drbd_dev *mdev, struct drbd_work *w, int unused);
+STATIC void md_sync_timer_fn(unsigned long data);
 
 MODULE_AUTHOR("Philipp Reisner <phil@linbit.com>, Lars Ellenberg <lars@linbit.com>");
 MODULE_DESCRIPTION("drbd - Distributed Replicated Block Device v" REL_VERSION);
@@ -504,10 +506,7 @@
 
 	D_ASSERT(drbd_md_test_flag(mdev,MDF_FullSync));
 	D_ASSERT(!drbd_md_test_flag(mdev,MDF_Consistent));
-	if (test_bit(MD_DIRTY,&mdev->flags)) {
-		// try to get "inconsistent, need full sync" to MD
-		drbd_md_write(mdev);
-	}
+	drbd_md_sync(mdev);
 
 	if ( wait_event_interruptible_timeout(mdev->cstate_wait,
 		     atomic_read(&mdev->local_cnt) == 0 , HZ ) <= 0) {
@@ -753,6 +752,20 @@
 
 void after_state_ch(drbd_dev* mdev, drbd_state_t os, drbd_state_t ns)
 {
+	u32 mdf;
+
+	mdf = mdev->bc->md.flags & ~(MDF_Consistent|MDF_PrimaryInd|
+				     MDF_ConnectedInd|MDF_WasUpToDate);
+	if (mdev->state.role == Primary)        mdf |= MDF_PrimaryInd;
+	if (mdev->state.conn >= WFReportParams) mdf |= MDF_ConnectedInd;
+	if (mdev->state.disk >  Inconsistent)   mdf |= MDF_Consistent;
+	if (mdev->state.disk >  Outdated)       mdf |= MDF_WasUpToDate;
+
+	if( mdf != mdev->bc->md.flags) {
+		mdev->bc->md.flags = mdf;
+		drbd_md_mark_dirty(mdev);
+	}
+
 	/* Here we have the actions that are performed after a
 	   state change. This function might sleep */
 
@@ -773,7 +786,6 @@
 			/* Only do it if we have not yet done it... */
 			INFO("Creating new current UUID\n");
 			drbd_uuid_new_current(mdev);
-			drbd_md_write(mdev);
 		}
 		if (ns.peer == Primary ) { 
  			/* Note: The condition ns.peer == Primary implies
@@ -786,7 +798,6 @@
 			INFO("Creating new current UUID [no BitMap]\n");
 			get_random_bytes(&uuid, sizeof(u64));
 			drbd_uuid_set(mdev, Current, uuid);
-			drbd_md_write(mdev);
 		}
 	}
 
@@ -807,6 +818,7 @@
 	        ns.aftr_isp == 0 && ns.user_isp == 0   ) {
 		drbd_send_short_cmd(mdev,ResumeResync);
 	}
+	drbd_md_sync(mdev);
 }
 
 
@@ -1159,7 +1171,7 @@
 			goto out;
 		}
 		drbd_md_clear_flag(mdev,MDF_FullSync);
-		drbd_md_write(mdev);
+		drbd_md_sync(mdev);
 	}
 
 	/*
@@ -1791,13 +1803,18 @@
 	INIT_LIST_HEAD(&mdev->resync_work.list);
 	INIT_LIST_HEAD(&mdev->barrier_work.list);
 	INIT_LIST_HEAD(&mdev->unplug_work.list);
+	INIT_LIST_HEAD(&mdev->md_sync_work.list);
 	INIT_LIST_HEAD(&mdev->discard);
 	mdev->resync_work.cb  = w_resync_inactive;
 	mdev->barrier_work.cb = w_try_send_barrier;
 	mdev->unplug_work.cb  = w_send_write_hint;
+	mdev->md_sync_work.cb = w_md_sync;
 	init_timer(&mdev->resync_timer);
+	init_timer(&mdev->md_sync_timer);
 	mdev->resync_timer.function = resync_timer_fn;
 	mdev->resync_timer.data = (unsigned long) mdev;
+	mdev->md_sync_timer.function = md_sync_timer_fn;
+	mdev->md_sync_timer.data = (unsigned long) mdev;
 
 	init_waitqueue_head(&mdev->cstate_wait);
 	init_waitqueue_head(&mdev->ee_wait);
@@ -2392,20 +2409,18 @@
 	u32 bm_offset;         // offset to the bitmap, from here
 } __attribute((packed));
 
-/*
-
-FIXME md_io might fail unnoticed sometimes ...
-
-*/
-void drbd_md_write(drbd_dev *mdev)
+/** 
+ * drbd_md_sync:
+ * Writes the meta data super block if the MD_DIRTY flag bit is set.
+ */ 
+void drbd_md_sync(drbd_dev *mdev)
 {
 	struct meta_data_on_disk * buffer;
-	u32 flags;
 	sector_t sector;
 	int i;
 
-	if(!mdev->bc) return; // because of drbd_check_al_size(mdev) in 
-			      // drbd_ioctl_set_disk() should be removed....
+	if (!test_and_clear_bit(MD_DIRTY,&mdev->flags)) return;
+	del_timer(&mdev->resync_timer);
 
 	ERR_IF(!inc_md_only(mdev,Attaching)) return;
 
@@ -2413,18 +2428,10 @@
 	buffer = (struct meta_data_on_disk *)page_address(mdev->md_io_page);
 	memset(buffer,0,512);
 
-	flags = mdev->bc->md.flags & ~(MDF_Consistent|MDF_PrimaryInd|
-				   MDF_ConnectedInd|MDF_WasUpToDate);
-	if (mdev->state.role == Primary)        flags |= MDF_PrimaryInd;
-	if (mdev->state.conn >= WFReportParams) flags |= MDF_ConnectedInd;
-	if (mdev->state.disk >  Inconsistent)   flags |= MDF_Consistent;
-	if (mdev->state.disk >  Outdated)       flags |= MDF_WasUpToDate;
-	mdev->bc->md.flags = flags;
-
 	buffer->la_size=cpu_to_be64(drbd_get_capacity(mdev->this_bdev));
 	for (i = Current; i < UUID_SIZE; i++)
 		buffer->uuid[i]=cpu_to_be64(mdev->bc->md.uuid[i]);
-	buffer->flags = cpu_to_be32(flags);
+	buffer->flags = cpu_to_be32(mdev->bc->md.flags);
 	buffer->magic = cpu_to_be32(DRBD_MD_MAGIC);
 
 	buffer->md_size_sect  = cpu_to_be32(mdev->bc->md.md_size_sect);
@@ -2533,6 +2540,18 @@
 	return rv;
 }
 
+/** 
+ * drbd_md_mark_dirty:
+ * Call this function if you change enything that should be written to
+ * the meta-data super block. This function sets MD_DIRTY, and starts a 
+ * timer that ensures that within one second you have to call drbd_md_sync().
+ */
+void drbd_md_mark_dirty(drbd_dev *mdev)
+{
+	set_bit(MD_DIRTY,&mdev->flags);
+	mod_timer(&mdev->resync_timer,jiffies + HZ );
+}
+
 static void drbd_uuid_move_history(drbd_dev *mdev)
 {
 	int i;
@@ -2549,6 +2568,7 @@
 	} else {
 		mdev->bc->md.uuid[idx] = val & ~((u64)1);
 	}
+	drbd_md_mark_dirty(mdev);
 }
 
 
@@ -2571,6 +2591,7 @@
 	} else {
 		mdev->bc->md.uuid[Current] &= ~((u64)1);
 	}
+	drbd_md_mark_dirty(mdev);
 }
 
 void drbd_uuid_set_bm(drbd_dev *mdev, u64 val)
@@ -2587,6 +2608,7 @@
 		mdev->bc->md.uuid[Bitmap] = val;
 		mdev->bc->md.uuid[Bitmap] &= ~((u64)1);
 	}
+	drbd_md_mark_dirty(mdev);
 }
 
 
@@ -2594,7 +2616,7 @@
 {
 	MUST_HOLD(mdev->req_lock);
 	if ( (mdev->bc->md.flags & flag) != flag) {
-		set_bit(MD_DIRTY,&mdev->flags);
+		drbd_md_mark_dirty(mdev);
 		mdev->bc->md.flags |= flag;
 	}
 }
@@ -2602,7 +2624,7 @@
 {
 	MUST_HOLD(mdev->req_lock);
 	if ( (mdev->bc->md.flags & flag) != 0 ) {
-		set_bit(MD_DIRTY,&mdev->flags);
+		drbd_md_mark_dirty(mdev);
 		mdev->bc->md.flags &= ~flag;
 	}
 }
@@ -2612,5 +2634,21 @@
 	return ((mdev->bc->md.flags & flag) != 0);
 }
 
+STATIC void md_sync_timer_fn(unsigned long data)
+{
+	drbd_dev* mdev = (drbd_dev*) data;
+
+	WARN("md_sync_timer expired!\n");
+	drbd_queue_work_front(mdev,&mdev->data.work,&mdev->md_sync_work);
+}
+
+STATIC int w_md_sync(drbd_dev *mdev, struct drbd_work *w, int unused)
+{
+	WARN("Worker calls drbd_md_sync() now.\n");
+	drbd_md_sync(mdev);
+
+	return 1;
+}
+
 module_init(drbd_init)
 module_exit(drbd_cleanup)

Modified: trunk/drbd/drbd_receiver.c
===================================================================
--- trunk/drbd/drbd_receiver.c	2006-01-10 14:30:17 UTC (rev 2047)
+++ trunk/drbd/drbd_receiver.c	2006-01-14 17:28:02 UTC (rev 2048)
@@ -1703,13 +1703,13 @@
 
 	if (abs(hg) >= 2) {
 		drbd_md_set_flag(mdev,MDF_FullSync);
-		drbd_md_write(mdev);
+		drbd_md_sync(mdev);
 
 		drbd_bm_set_all(mdev);
 		drbd_bm_write(mdev);
 
 		drbd_md_clear_flag(mdev,MDF_FullSync);
-		drbd_md_write(mdev);
+		drbd_md_sync(mdev);
 	}
 
 	if (hg > 0) { // become sync source.
@@ -1991,7 +1991,7 @@
 	mdev->net_conf->want_lose = 0;
 
 	/* FIXME assertion for (gencounts do not diverge) */
-	drbd_md_write(mdev); // update connected indicator, la_size, ...
+	drbd_md_sync(mdev); // update connected indicator, la_size, ...
 
 	return TRUE;
 }
@@ -2196,7 +2196,7 @@
 	after_state_ch(mdev,os,ns);
 
 	if( r >= 0 ) {
-		drbd_md_write(mdev);
+		drbd_md_sync(mdev);
 		drbd_send_short_cmd(mdev, OutdatedReply);
 		return TRUE;
 	}
@@ -2211,7 +2211,7 @@
 	r = drbd_request_state(mdev,NS2(pdsk,Outdated,conn,TearDown));
 	WARN("r=%d\n",r);
 	D_ASSERT(r >= SS_Success);
-	drbd_md_write(mdev); // because drbd_request_state created a new UUID.
+	drbd_md_sync(mdev); // because drbd_request_state created a new UUID.
 
 	return TRUE;
 }
@@ -2418,7 +2418,7 @@
 			drbd_disks_t nps = drbd_try_outdate_peer(mdev);
 			drbd_request_state(mdev,NS(pdsk,nps));
 		}
-		drbd_md_write(mdev);
+		drbd_md_sync(mdev);
 	}
 
 	INFO("Connection lost.\n");

Modified: trunk/drbd/drbd_worker.c
===================================================================
--- trunk/drbd/drbd_worker.c	2006-01-10 14:30:17 UTC (rev 2047)
+++ trunk/drbd/drbd_worker.c	2006-01-14 17:28:02 UTC (rev 2048)
@@ -433,9 +433,6 @@
 	drbd_request_state(mdev,NS3(conn,Connected,
 				    disk,UpToDate,
 				    pdsk,UpToDate));
-
-	drbd_md_write(mdev);
-
 	return 1;
 }
 
@@ -817,8 +814,6 @@
 			return;
 		}
 
-		drbd_md_write(mdev);
-
 		if( ns.conn == SyncTarget ) {
 			D_ASSERT(!test_bit(STOP_SYNC_TIMER,&mdev->flags));
 			mod_timer(&mdev->resync_timer,jiffies);

From drbd-cvs at lists.linbit.com  Wed Jan 18 15:13:29 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Wed Jan 18 15:13:36 2006
Subject: [DRBD-cvs] svn commit by phil - r2049 - in trunk: . drbd - * There
	was a bug with the new mdev->bc way of storing 
Message-ID: <20060118141329.DE903160AF@mail.linbit.com>

Author: phil
Date: 2006-01-18 15:13:28 +0100 (Wed, 18 Jan 2006)
New Revision: 2049

Modified:
   trunk/ROADMAP
   trunk/drbd/drbd_fs.c
   trunk/drbd/drbd_main.c
   trunk/drbd/drbd_receiver.c
   trunk/drbd/drbd_req.c
   trunk/drbd/drbd_worker.c
Log:
* There was a bug with the new mdev->bc way of storing the
  backing_bdev's informations. It crashed the kernel when 
  trying IO on a diskless device. FIXED.

* Tested and fixed the new drbd_md_sync() code, and the md_sync...
  timer mechanism.

* Made writing of the meta data super block verbose.

* Fixed the logic to set the MDF_ConnectedInd.

* Began to reduce the number of writes to the meta data super block.   


Modified: trunk/ROADMAP
===================================================================
--- trunk/ROADMAP	2006-01-14 17:28:02 UTC (rev 2048)
+++ trunk/ROADMAP	2006-01-18 14:13:28 UTC (rev 2049)
@@ -646,9 +646,8 @@
    99% DONE
 
 24 Make it possible to hot-add disk drives == Atomic configuration changes.
-   Missing: Think about and test detach/attach of the primary's disk.
 
-   80% DONE [ The net and disk config changes are atomic by now ]
+   99% DONE
 
 25 Add reserved fields to DRBD-meta-data, add a bytes per bit field to
    metadata.
@@ -660,7 +659,7 @@
    that always keeps the on disk-metadata up-to-date implicit. 
    Calling drbd_md_write() explicit is too errorprone.
 
-   90% DONE [ Needs testing, drbd_md_sync() is the new call ]
+   99% DONE
 
 28 Implement a kind of 'call home', a single HTTP get request, that
    gets counted in a data base. The initiator calculates a simple

Modified: trunk/drbd/drbd_fs.c
===================================================================
--- trunk/drbd/drbd_fs.c	2006-01-14 17:28:02 UTC (rev 2048)
+++ trunk/drbd/drbd_fs.c	2006-01-18 14:13:28 UTC (rev 2049)
@@ -898,6 +898,8 @@
 		drbd_send_state(mdev);
 	}
 
+	drbd_md_sync(mdev);
+
 	return 0;
 
  fail:

Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c	2006-01-14 17:28:02 UTC (rev 2048)
+++ trunk/drbd/drbd_main.c	2006-01-18 14:13:28 UTC (rev 2049)
@@ -754,16 +754,18 @@
 {
 	u32 mdf;
 
-	mdf = mdev->bc->md.flags & ~(MDF_Consistent|MDF_PrimaryInd|
-				     MDF_ConnectedInd|MDF_WasUpToDate);
-	if (mdev->state.role == Primary)        mdf |= MDF_PrimaryInd;
-	if (mdev->state.conn >= WFReportParams) mdf |= MDF_ConnectedInd;
-	if (mdev->state.disk >  Inconsistent)   mdf |= MDF_Consistent;
-	if (mdev->state.disk >  Outdated)       mdf |= MDF_WasUpToDate;
+	if(mdev->bc) {
+		mdf = mdev->bc->md.flags & ~(MDF_Consistent|MDF_PrimaryInd|
+					     MDF_ConnectedInd|MDF_WasUpToDate);
+		if (mdev->state.role == Primary)       mdf |= MDF_PrimaryInd;
+		if (mdev->state.conn > WFReportParams) mdf |= MDF_ConnectedInd;
+		if (mdev->state.disk > Inconsistent)   mdf |= MDF_Consistent;
+		if (mdev->state.disk > Outdated)       mdf |= MDF_WasUpToDate;
 
-	if( mdf != mdev->bc->md.flags) {
-		mdev->bc->md.flags = mdf;
-		drbd_md_mark_dirty(mdev);
+		if( mdf != mdev->bc->md.flags) {
+			mdev->bc->md.flags = mdf;
+			drbd_md_mark_dirty(mdev);
+		}
 	}
 
 	/* Here we have the actions that are performed after a
@@ -818,7 +820,6 @@
 	        ns.aftr_isp == 0 && ns.user_isp == 0   ) {
 		drbd_send_short_cmd(mdev,ResumeResync);
 	}
-	drbd_md_sync(mdev);
 }
 
 
@@ -2420,8 +2421,8 @@
 	int i;
 
 	if (!test_and_clear_bit(MD_DIRTY,&mdev->flags)) return;
-	del_timer(&mdev->resync_timer);
-
+	del_timer(&mdev->md_sync_timer);
+	INFO("Writing meta data super block now.\n");
 	ERR_IF(!inc_md_only(mdev,Attaching)) return;
 
 	down(&mdev->md_io_mutex);
@@ -2549,7 +2550,7 @@
 void drbd_md_mark_dirty(drbd_dev *mdev)
 {
 	set_bit(MD_DIRTY,&mdev->flags);
-	mod_timer(&mdev->resync_timer,jiffies + HZ );
+	mod_timer(&mdev->md_sync_timer,jiffies + HZ );
 }
 
 static void drbd_uuid_move_history(drbd_dev *mdev)
@@ -2638,13 +2639,12 @@
 {
 	drbd_dev* mdev = (drbd_dev*) data;
 
-	WARN("md_sync_timer expired!\n");
 	drbd_queue_work_front(mdev,&mdev->data.work,&mdev->md_sync_work);
 }
 
 STATIC int w_md_sync(drbd_dev *mdev, struct drbd_work *w, int unused)
 {
-	WARN("Worker calls drbd_md_sync() now.\n");
+	WARN("BUG! md_sync_timer expired! Worker calls drbd_md_sync().\n");
 	drbd_md_sync(mdev);
 
 	return 1;

Modified: trunk/drbd/drbd_receiver.c
===================================================================
--- trunk/drbd/drbd_receiver.c	2006-01-14 17:28:02 UTC (rev 2048)
+++ trunk/drbd/drbd_receiver.c	2006-01-18 14:13:28 UTC (rev 2049)
@@ -2418,9 +2418,9 @@
 			drbd_disks_t nps = drbd_try_outdate_peer(mdev);
 			drbd_request_state(mdev,NS(pdsk,nps));
 		}
-		drbd_md_sync(mdev);
 	}
 
+	drbd_md_sync(mdev);
 	INFO("Connection lost.\n");
 }
 

Modified: trunk/drbd/drbd_req.c
===================================================================
--- trunk/drbd/drbd_req.c	2006-01-14 17:28:02 UTC (rev 2048)
+++ trunk/drbd/drbd_req.c	2006-01-18 14:13:28 UTC (rev 2049)
@@ -208,7 +208,6 @@
 		req->master_bio  = bio_src;
 		req->private_bio = bio;
 
-		bio->bi_bdev     = mdev->bc->backing_bdev;
 		bio->bi_private  = req;
 		bio->bi_end_io   =
 			bio_data_dir(bio) == WRITE
@@ -377,6 +376,7 @@
 
 		// in 2.4.X, READA are submitted as READ.
 		req->private_bio->bi_rw = rw;
+		req->private_bio->bi_bdev = mdev->bc->backing_bdev;
 		generic_make_request(req->private_bio);
 	}
 

Modified: trunk/drbd/drbd_worker.c
===================================================================
--- trunk/drbd/drbd_worker.c	2006-01-14 17:28:02 UTC (rev 2048)
+++ trunk/drbd/drbd_worker.c	2006-01-18 14:13:28 UTC (rev 2049)
@@ -433,6 +433,9 @@
 	drbd_request_state(mdev,NS3(conn,Connected,
 				    disk,UpToDate,
 				    pdsk,UpToDate));
+
+	drbd_md_sync(mdev);
+
 	return 1;
 }
 
@@ -818,6 +821,8 @@
 			D_ASSERT(!test_bit(STOP_SYNC_TIMER,&mdev->flags));
 			mod_timer(&mdev->resync_timer,jiffies);
 		}
+
+		drbd_md_sync(mdev);
 	}
 }
 

From drbd-cvs at lists.linbit.com  Thu Jan 19 16:28:45 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Thu Jan 19 16:28:48 2006
Subject: [DRBD-cvs] svn commit by phil - r2050 - in trunk: drbd scripts user
	- Fixed the user space handlers. 
Message-ID: <20060119152846.0A13F160AF@mail.linbit.com>

Author: phil
Date: 2006-01-19 16:28:44 +0100 (Thu, 19 Jan 2006)
New Revision: 2050

Modified:
   trunk/drbd/drbd_int.h
   trunk/drbd/drbd_receiver.c
   trunk/drbd/drbd_worker.c
   trunk/scripts/drbd.conf
   trunk/user/drbdadm_main.c
   trunk/user/drbdadm_parser.y
   trunk/user/drbdadm_scanner.fl
Log:
Fixed the user space handlers.


Modified: trunk/drbd/drbd_int.h
===================================================================
--- trunk/drbd/drbd_int.h	2006-01-18 14:13:28 UTC (rev 2049)
+++ trunk/drbd/drbd_int.h	2006-01-19 15:28:44 UTC (rev 2050)
@@ -1074,6 +1074,7 @@
 		      unsigned int cmd, unsigned long arg);
 drbd_disks_t drbd_try_outdate_peer(drbd_dev *mdev);
 extern long drbd_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg);
+extern int drbd_khelper(drbd_dev *mdev, char* cmd);
 
 // drbd_worker.c
 enum RSPauseReason {

Modified: trunk/drbd/drbd_receiver.c
===================================================================
--- trunk/drbd/drbd_receiver.c	2006-01-18 14:13:28 UTC (rev 2049)
+++ trunk/drbd/drbd_receiver.c	2006-01-19 15:28:44 UTC (rev 2050)
@@ -1526,6 +1526,7 @@
 			int got_mutex=!down_interruptible(&mdev->device_mutex);
 			if (got_mutex) self = drbd_set_role(mdev,&sec);
 			if (self || !got_mutex) {
+				drbd_khelper(mdev,"pri-lost-after-sb");
 				drbd_panic("Panic by after-sb-1pri handler\n");
 			} else {
 				WARN("Sucessfully gave up primary role.\n");
@@ -1563,6 +1564,7 @@
 			int got_mutex=!down_interruptible(&mdev->device_mutex);
 			if (got_mutex) self = drbd_set_role(mdev,&sec);
 			if (self || !got_mutex) {
+				drbd_khelper(mdev,"pri-lost-after-sb");
 				drbd_panic("Panic by after-sb-2pri handler\n");
 			} else {
 				WARN("Sucessfully gave up primary role.\n");
@@ -2802,6 +2804,7 @@
 
 	drbd_req_free(req);
 
+	drbd_khelper(mdev,"pri-on-incon-degr");
 	drbd_panic("Got NegDReply. WE ARE LOST. We lost our up-to-date disk.\n");
 
 	// THINK do we have other options, but panic?
@@ -2820,6 +2823,9 @@
 
 	drbd_rs_complete_io(mdev,sector);
 
+
+	// In case we are not primary, we could simply live on...
+
 	drbd_panic("Got NegRSDReply. WE ARE LOST. We lost our up-to-date disk.\n");
 
 	// THINK do we have other options, but panic?

Modified: trunk/drbd/drbd_worker.c
===================================================================
--- trunk/drbd/drbd_worker.c	2006-01-18 14:13:28 UTC (rev 2049)
+++ trunk/drbd/drbd_worker.c	2006-01-19 15:28:44 UTC (rev 2050)
@@ -223,6 +223,7 @@
 	if ( cancel ||
 	     mdev->state.conn < Connected ||
 	     mdev->state.pdsk <= Inconsistent ) {
+		drbd_khelper(mdev,"pri-on-incon-degr");
 		drbd_panic("WE ARE LOST. Local IO failure, no peer.\n");
 
 		// does not make much sense, but anyways...

Modified: trunk/scripts/drbd.conf
===================================================================
--- trunk/scripts/drbd.conf	2006-01-18 14:13:28 UTC (rev 2049)
+++ trunk/scripts/drbd.conf	2006-01-19 15:28:44 UTC (rev 2050)
@@ -133,9 +133,9 @@
     # (=no connection) and has inconsistent data.
     pri-on-incon-degr "halt -f";
 
-    # If suddenly the peer presents a higher generation count
-    # than we have, and we are primary.
-    pri-sees-sec-with-higher-gc "halt -f";
+    # The node is currently primary, but lost the after split brain
+    # auto recovery procedure. As as consequence it should go away.
+    pri-lost-after-sb "halt -f";
 
     # Commands to run in case we need to downgrade the peer's disk 
     # state to "Outdated". Should be implemented by the superior

Modified: trunk/user/drbdadm_main.c
===================================================================
--- trunk/user/drbdadm_main.c	2006-01-18 14:13:28 UTC (rev 2049)
+++ trunk/user/drbdadm_main.c	2006-01-19 15:28:44 UTC (rev 2050)
@@ -203,7 +203,7 @@
   { "dump-md",           admm_generic,  1,1,0 },
   { "set-gi",            admm_generic,  0,1,0 },
   { "pri-on-incon-degr", adm_khelper,   0,1,0 },
-  { "pri-sees-sec-with-higher-gc", adm_khelper, 0,1,0 },
+  { "pri-lost-after-sb", adm_khelper,   0,1,0 },
   { "outdate-peer",      adm_khelper,   0,1,0 },
   { "wait_con_int",      adm_wait_ci,   1,0,1 },
   { "sh-resources",      sh_resources,  0,0,0 },

Modified: trunk/user/drbdadm_parser.y
===================================================================
--- trunk/user/drbdadm_parser.y	2006-01-18 14:13:28 UTC (rev 2049)
+++ trunk/user/drbdadm_parser.y	2006-01-19 15:28:44 UTC (rev 2050)
@@ -258,7 +258,7 @@
 %token <txt> TK_WFC_TIMEOUT TK_DEGR_WFC_TIMEOUT
 %token <txt> TK_KO_COUNT TK_ON_DISCONNECT TK_DIALOG_REFRESH
 %token <txt> TK_ALLOW_TWO_PRIMARIES
-%token <txt> TK_PRI_ON_INCON_DEGR TK_PRI_SEES_SEC_WITH_HIGHER_GC
+%token <txt> TK_PRI_ON_INCON_DEGR TK_PRI_LOST_AFTER_SB
 %token <txt> TK_OUTDATE_PEER TK_CRAM_HMAC_ALG TK_SHARED_SECRET
 %token <txt> TK_AFTER_SB_PRI
 
@@ -464,7 +464,6 @@
 		;
 
 handler_stmt:	  TK_PRI_ON_INCON_DEGR TK_STRING	{ $$=new_opt($1,$2); }
-		| TK_PRI_SEES_SEC_WITH_HIGHER_GC TK_STRING
-		{ $$=new_opt($1,$2); }
+		| TK_PRI_LOST_AFTER_SB TK_STRING	{ $$=new_opt($1,$2); }
 		| TK_OUTDATE_PEER TK_STRING		{ $$=new_opt($1,$2); }
 		;

Modified: trunk/user/drbdadm_scanner.fl
===================================================================
--- trunk/user/drbdadm_scanner.fl	2006-01-18 14:13:28 UTC (rev 2049)
+++ trunk/user/drbdadm_scanner.fl	2006-01-19 15:28:44 UTC (rev 2050)
@@ -305,12 +305,12 @@
 
 <HANDLERS>{
   pri-on-incon-degr	do_assign(STRING); CP; return TK_PRI_ON_INCON_DEGR;
-  pri-sees-sec-with-higher-gc	do_assign(STRING); CP; return TK_PRI_SEES_SEC_WITH_HIGHER_GC;
+  pri-lost-after-sb     do_assign(STRING); CP; return TK_PRI_LOST_AFTER_SB;
   outdate-peer		do_assign(STRING); CP; return TK_OUTDATE_PEER;
   {NDELIM}		{
 	  		  expect_error(
 				"one of 'pri-on-incon-degr|"
-				"pri-sees-sec-with-higher-gc|"
+				"pri-lost-after-sb|"
 				"outdate-peer");
 			}
 }

From drbd-cvs at lists.linbit.com  Thu Jan 19 18:39:53 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Thu Jan 19 18:39:55 2006
Subject: [DRBD-cvs] svn commit by phil - r2051 - in trunk: . user - drbdadm
	can now also show its secret commands. 
Message-ID: <20060119173954.1A8DA165CB@mail.linbit.com>

Author: phil
Date: 2006-01-19 18:39:52 +0100 (Thu, 19 Jan 2006)
New Revision: 2051

Modified:
   trunk/ROADMAP
   trunk/user/drbdadm_main.c
   trunk/user/drbdmeta.c
Log:
drbdadm can now also show its secret commands.


Modified: trunk/ROADMAP
===================================================================
--- trunk/ROADMAP	2006-01-19 15:28:44 UTC (rev 2050)
+++ trunk/ROADMAP	2006-01-19 17:39:52 UTC (rev 2051)
@@ -667,9 +667,11 @@
    set gets generated, the 'call home' is initiated. The user might
    of course opt out of this.
 
-29 Make all the commands to have 'expert' switches to also show
+29 Make drbdadm to have 'hidden-commands' command to also show
    the hidden sub-commands in the ussage.
 
+   99% DONE
+
 30 The current drbdadm_scanner is 1MB in source and as binary.
    Use a _basic_ flex scanner, and a hand written parser for superb
    errror reporting.

Modified: trunk/user/drbdadm_main.c
===================================================================
--- trunk/user/drbdadm_main.c	2006-01-19 15:28:44 UTC (rev 2050)
+++ trunk/user/drbdadm_main.c	2006-01-19 17:39:52 UTC (rev 2051)
@@ -64,9 +64,9 @@
 struct adm_cmd {
   const char* name;
   int (* function)(struct d_resource*,const char* );
-  int show_in_usage     :1;
-  int res_name_required :1;
-  int verify_ips        :1;
+  unsigned int show_in_usage     :3;
+  unsigned int res_name_required :1;
+  unsigned int verify_ips        :1;
 };
 
 struct deferred_cmd
@@ -100,6 +100,7 @@
 static int admm_generic(struct d_resource* ,const char* );
 static int adm_khelper(struct d_resource* ,const char* );
 static int adm_generic_b(struct d_resource* ,const char* );
+static int hidden_cmds(struct d_resource* ,const char* );
 
 char ss_buffer[255];
 struct utsname nodeinfo;
@@ -201,17 +202,18 @@
   { "show-gi",           adm_generic_b, 1,1,0 },
   { "get-gi",            adm_generic_b, 1,1,0 },
   { "dump-md",           admm_generic,  1,1,0 },
-  { "set-gi",            admm_generic,  0,1,0 },
-  { "pri-on-incon-degr", adm_khelper,   0,1,0 },
-  { "pri-lost-after-sb", adm_khelper,   0,1,0 },
-  { "outdate-peer",      adm_khelper,   0,1,0 },
   { "wait_con_int",      adm_wait_ci,   1,0,1 },
-  { "sh-resources",      sh_resources,  0,0,0 },
-  { "sh-mod-parms",      sh_mod_parms,  0,0,0 },
-  { "sh-dev",            sh_dev,        0,1,0 },
-  { "sh-ll-dev",         sh_ll_dev,     0,1,0 },
-  { "sh-md-dev",         sh_md_dev,     0,1,0 },
-  { "sh-md-idx",         sh_md_idx,     0,1,0 },
+  { "hidden-commands",   hidden_cmds,   1,0,0 },
+  { "sh-resources",      sh_resources,  2,0,0 },
+  { "sh-mod-parms",      sh_mod_parms,  2,0,0 },
+  { "sh-dev",            sh_dev,        2,1,0 },
+  { "sh-ll-dev",         sh_ll_dev,     2,1,0 },
+  { "sh-md-dev",         sh_md_dev,     2,1,0 },
+  { "sh-md-idx",         sh_md_idx,     2,1,0 },
+  { "pri-on-incon-degr", adm_khelper,   3,1,0 },
+  { "pri-lost-after-sb", adm_khelper,   3,1,0 },
+  { "outdate-peer",      adm_khelper,   3,1,0 },
+  { "set-gi",            admm_generic,  4,1,0 },
 };
 
 /*** These functions are used to the print the config ***/
@@ -1048,9 +1050,46 @@
   return 0;
 }
 
+static void print_cmds(int level)
+{
+  size_t i;
+  int j=0;
+
+  for(i=0;i<ARRY_SIZE(cmds);i++) {
+    if(cmds[i].show_in_usage!=level) continue;
+    if(j++ % 2) {
+      printf("%-35s\n",cmds[i].name);
+    } else {
+      printf(" %-35s",cmds[i].name);
+    }
+  }
+  if(j % 2) printf("\n");
+}
+
+static int hidden_cmds(struct d_resource* ignored __attribute((unused)),
+		       const char* ignored2 __attribute((unused)) )
+{
+  printf("\nThese additional commands might be usefull for writing\n"
+	 "nifty shell scripts around drbdadm\n\n");
+
+  print_cmds(2);
+
+  printf("\nThese command are used by the kernel part of DRBD to\n"
+	 "invoke user mode helper programs\n\n");
+
+  print_cmds(3);
+
+  printf("\nThese commands ought to be used by experts and developers\n\n");
+  
+  print_cmds(4);
+
+  printf("\n");
+
+  exit(0);
+}
+
 void print_usage_and_exit(const char* addinfo)
 {
-  size_t i;
   struct option *opt;
 
   printf("\nUSAGE: %s [OPTION...] [-- DRBDSETUP-OPTION...] COMMAND "
@@ -1068,14 +1107,7 @@
 
   printf("\nCOMMANDS:\n");
 
-  for(i=0;i<ARRY_SIZE(cmds);i++) {
-    if(cmds[i].show_in_usage==0) break;
-    if(i%2) {
-      printf("%-35s\n",cmds[i].name);
-    } else {
-      printf(" %-35s",cmds[i].name);
-    }
-  }
+  print_cmds(1);
 
   printf("\nVersion: "REL_VERSION" (api:%d)\n%s\n",
 		  API_VERSION, drbd_buildtag());
@@ -1400,6 +1432,12 @@
   }
   if (optind == argc) print_usage_and_exit(0);
 
+  if(!strcmp("hidden-commands",argv[optind])) {
+    // before parsing the configuration file...
+    hidden_cmds(NULL,NULL);
+    exit(0);
+  }
+
   cmd=NULL;
   for(i=0;i<ARRY_SIZE(cmds);i++) {
       if(!strcmp(cmds[i].name,argv[optind])) {

Modified: trunk/user/drbdmeta.c
===================================================================
--- trunk/user/drbdmeta.c	2006-01-19 15:28:44 UTC (rev 2050)
+++ trunk/user/drbdmeta.c	2006-01-19 17:39:52 UTC (rev 2051)
@@ -801,9 +801,8 @@
 int meta_dump_md(struct format *cfg, char **argv, int argc);
 int meta_restore_md(struct format *cfg, char **argv, int argc);
 int meta_create_md(struct format *cfg, char **argv, int argc);
-int meta_set_gi(struct format *cfg, char **argv, int argc);
 int meta_outdate(struct format *cfg, char **argv, int argc);
-int meta_set_uuid(struct format *cfg, char **argv, int argc);
+int meta_set_gi(struct format *cfg, char **argv, int argc);
 
 struct meta_cmd cmds[] = {
 	{"get-gi", 0, meta_get_gi, 1},

From drbd-cvs at lists.linbit.com  Sun Jan 22 00:07:33 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Sun Jan 22 00:07:35 2006
Subject: [DRBD-cvs] svn commit by phil - r2052 - in trunk: . user - Rewrote
	drbdadm's scanner/lexer and parser. The previou
Message-ID: <20060121230733.F2E4316604@mail.linbit.com>

Author: phil
Date: 2006-01-22 00:07:32 +0100 (Sun, 22 Jan 2006)
New Revision: 2052

Added:
   trunk/user/drbdadm_parser.c
   trunk/user/drbdadm_parser.h
Removed:
   trunk/user/drbdadm_parser.y
Modified:
   trunk/ROADMAP
   trunk/user/Makefile
   trunk/user/drbdadm_scanner.fl
Log:
Rewrote drbdadm's scanner/lexer and parser. The previous scanner/lexer
was more a parser by itself, and the parser was in its own way obscure
as well.

The new scanner (flex based) only has a single context, the new parser is hand
written instead of bison based.

The old bindary was 966 960 Bytes, the new one is about 6% of this 59 728 .
The new scanner code is a lot easier to read, the new parser code is
less lines of C than it had lines of bison grammer, it is earsier to read
as well.

The new code executes about 10 times faster, than the old one.

The new code also has the extensive error reporting capability, that
drove the old implementation into its bloatness.


Modified: trunk/ROADMAP
===================================================================
--- trunk/ROADMAP	2006-01-19 17:39:52 UTC (rev 2051)
+++ trunk/ROADMAP	2006-01-21 23:07:32 UTC (rev 2052)
@@ -676,6 +676,8 @@
    Use a _basic_ flex scanner, and a hand written parser for superb
    errror reporting.
 
+   99% DONE
+
 31 Resizing several GB results in ko-count timeouts, maybe since the
    secondary node does the enlargement of the bitmap in the receiver (?)
 

Modified: trunk/user/Makefile
===================================================================
--- trunk/user/Makefile	2006-01-19 17:39:52 UTC (rev 2051)
+++ trunk/user/Makefile	2006-01-21 23:07:32 UTC (rev 2052)
@@ -41,12 +41,6 @@
 
 # for debug:	flex -d -s -odrbdadm_scanner.c drbdadm_scanner.fl
 
-drbdadm_parser.h: drbdadm_parser.y
-	bison -d -o drbdadm_parser.c drbdadm_parser.y
-
-drbdadm_parser.c: drbdadm_parser.y drbdadm.h drbd_limits.h drbdtool_common.h
-	bison -d -o drbdadm_parser.c drbdadm_parser.y
-
 drbdsetup: $(drbdsetup-obj)
 	$(CC) -o $@ $^ 
 
@@ -55,8 +49,6 @@
 
 clean:
 	rm -f drbdadm_scanner.c
-	rm -f drbdadm_parser.c
-	rm -f drbdadm_parser.h
 	rm -f drbdsetup drbdadm drbdmeta *.o
 	rm -f *~
 

Added: trunk/user/drbdadm_parser.c
===================================================================
--- trunk/user/drbdadm_parser.c	2006-01-19 17:39:52 UTC (rev 2051)
+++ trunk/user/drbdadm_parser.c	2006-01-21 23:07:32 UTC (rev 2052)
@@ -0,0 +1,461 @@
+/*
+   drbdadm_parser.c a hand crafted parser
+
+   This file is part of drbd by Philipp Reisner.
+
+   Copyright (C) 2006, Philipp Reisner <philipp.reisner@linbit.com>.
+        Initial author.
+
+   drbd is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   drbd is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with drbd; see the file COPYING.  If not, write to
+   the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ */
+#define _GNU_SOURCE
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "drbdadm.h"
+#include "drbd_limits.h"
+#include "drbdtool_common.h"
+#include "drbdadm_parser.h"
+
+YYSTYPE yylval;
+
+/////////////////////
+
+#define APPEND(LIST,ITEM) ({		      \
+  typeof((LIST)) _l = (LIST);		      \
+  typeof((ITEM)) _i = (ITEM);		      \
+  typeof((ITEM)) _t;			      \
+  _i->next = NULL;			      \
+  if (_l == NULL) { _l = _i; }		      \
+  else {				      \
+    for (_t = _l; _t->next; _t = _t->next);   \
+    _t->next = _i;			      \
+  };					      \
+  _l;					      \
+})
+
+static int   c_section_start;
+
+void
+m_strtoll_range(const char *s, char def_unit,
+		const char *name,
+		unsigned long long min, unsigned long long max)
+{
+  unsigned long long r = m_strtoll(s, def_unit);
+  char unit[] = { def_unit > '1' ? def_unit : 0, 0 };
+  if (min > r || r > max)
+    {
+      fprintf(stderr,
+	      "%s:%d: %s %s => %llu%s out of range [%llu..%llu]%s.\n",
+	      config_file, fline, name, s, r, unit, min, max, unit);
+      exit(E_config_invalid);
+    }
+  if (DEBUG_RANGE_CHECK)
+    {
+      fprintf(stderr,
+	      "%s:%d: %s %s => %llu%s in range [%llu..%llu]%s.\n",
+	      config_file, fline, name, s, r, unit, min, max, unit);
+    }
+}
+
+enum range_checks
+{
+  R_MINOR_COUNT,
+  R_DIALOG_REFRESH,
+  R_DISK_SIZE,
+  R_TIMEOUT,
+  R_CONNECT_INT,
+  R_PING_INT,
+  R_MAX_BUFFERS,
+  R_MAX_EPOCH_SIZE,
+  R_SNDBUF_SIZE,
+  R_KO_COUNT,
+  R_RATE,
+  R_GROUP,
+  R_AL_EXTENTS,
+  R_PORT,
+  R_META_IDX,
+  R_WFC_TIMEOUT,
+  R_DEGR_WFC_TIMEOUT,
+};
+
+void
+range_check(const enum range_checks what, const char *name, const char *value)
+{
+  switch (what)
+    {
+    default:
+      fprintf(stderr, "%s:%d: unknown range for %s => %s\n",
+	      config_file, fline, name, value);
+      break;
+    case R_MINOR_COUNT:
+      m_strtoll_range(value, 1, name,
+		      DRBD_MINOR_COUNT_MIN, DRBD_MINOR_COUNT_MAX);
+      break;
+    case R_DIALOG_REFRESH:
+      m_strtoll_range(value, 1, name,
+		      DRBD_DIALOG_REFRESH_MIN, DRBD_DIALOG_REFRESH_MAX);
+      break;
+    case R_DISK_SIZE:
+      m_strtoll_range(value, 'K', name,
+		      DRBD_DISK_SIZE_SECT_MIN >> 1,
+		      DRBD_DISK_SIZE_SECT_MAX >> 1);
+      break;
+    case R_TIMEOUT:
+      m_strtoll_range(value, 1, name, DRBD_TIMEOUT_MIN, DRBD_TIMEOUT_MAX);
+      break;
+    case R_CONNECT_INT:
+      m_strtoll_range(value, 1, name, DRBD_CONNECT_INT_MIN,
+		      DRBD_CONNECT_INT_MAX);
+      break;
+    case R_PING_INT:
+      m_strtoll_range(value, 1, name, DRBD_PING_INT_MIN, DRBD_PING_INT_MAX);
+      break;
+    case R_MAX_BUFFERS:
+      m_strtoll_range(value, 1, name, DRBD_MAX_BUFFERS_MIN,
+		      DRBD_MAX_BUFFERS_MAX);
+      break;
+    case R_MAX_EPOCH_SIZE:
+      m_strtoll_range(value, 1, name, DRBD_MAX_EPOCH_SIZE_MIN,
+		      DRBD_MAX_EPOCH_SIZE_MAX);
+      break;
+    case R_SNDBUF_SIZE:
+      m_strtoll_range(value, 1, name, DRBD_SNDBUF_SIZE_MIN,
+		      DRBD_SNDBUF_SIZE_MAX);
+      break;
+    case R_KO_COUNT:
+      m_strtoll_range(value, 1, name, DRBD_KO_COUNT_MIN, DRBD_KO_COUNT_MAX);
+      break;
+    case R_RATE:
+      m_strtoll_range(value, 'K', name, DRBD_RATE_MIN, DRBD_RATE_MAX);
+      break;
+    case R_AL_EXTENTS:
+      m_strtoll_range(value, 1, name, DRBD_AL_EXTENTS_MIN,
+		      DRBD_AL_EXTENTS_MAX);
+      break;
+    case R_PORT:
+      m_strtoll_range(value, 1, name, DRBD_PORT_MIN, DRBD_PORT_MAX);
+      break;
+      /* FIXME not yet implemented!
+         case R_META_IDX:
+         m_strtoll_range(value, 1, name, DRBD_META_IDX_MIN, DRBD_META_IDX_MAX);
+         break;
+       */
+    case R_WFC_TIMEOUT:
+      m_strtoll_range(value, 1, name, DRBD_WFC_TIMEOUT_MIN,
+		      DRBD_WFC_TIMEOUT_MAX);
+      break;
+    case R_DEGR_WFC_TIMEOUT:
+      m_strtoll_range(value, 1, name, DRBD_DEGR_WFC_TIMEOUT_MIN,
+		      DRBD_DEGR_WFC_TIMEOUT_MAX);
+      break;
+    }
+}
+
+static struct d_option* new_opt(char* name,char* value)
+{
+	struct d_option* cn = malloc(sizeof(struct d_option));
+
+	/* fprintf(stderr,"%s:%d: %s = %s\n",config_file,line,name,value); */
+	cn->name=name;
+	cn->value=value;
+	cn->mentioned=0;
+
+	return cn;
+}
+
+static void derror(struct d_host_info *host,
+		   struct d_resource* res,
+		   char* text)
+{
+	config_valid=0;
+	fprintf(stderr, "%s:%d: in resource %s, on %s { ... }:"
+		" '%s' keyword missing.\n",
+		config_file,c_section_start,res->name,host->name,text);
+}
+
+void check_meta_disk(struct d_host_info *host)
+{
+  if (strcmp(host->meta_disk, "internal") != 0) {
+    /* external */
+    if (host->meta_index == NULL) {
+      fprintf(stderr, "%s:%d: expected 'meta-disk = %s [index]'.\n",
+	      config_file, fline, host->meta_disk);
+    }
+    /* index either some number, or "flexible" */
+    check_uniq("meta-disk", "%s:%s[%s]", host->name,
+	       host->meta_disk, host->meta_index);
+  } else if (host->meta_index) {
+    /* internal */
+    if (strcmp(host->meta_index,"flexible") != 0) {
+      /* internal, not flexible, but index given: no sir! */
+      fprintf(stderr,
+	      "%s:%d: no index allowed with 'meta-disk = internal'.\n",
+	      config_file, fline);
+    } /* else internal, flexible: fine */
+  } else {
+    /* internal, not flexible */
+    host->meta_index = strdup("internal");
+  }
+}
+
+///////////////////////////
+
+
+#define EXP(TOKEN1)					\
+({ 							\
+	int token; 					\
+	token = yylex(); 				\
+	if(token != TOKEN1)				\
+		pe_expected_got( #TOKEN1, token ); 	\
+})
+
+#define EXP2(TOKEN1,TOKEN2)					\
+({ 								\
+	int token; 						\
+	token = yylex(); 					\
+	if(token != TOKEN1 && token != TOKEN2) 			\
+		pe_expected_got( #TOKEN1 "|" # TOKEN2, token );	\
+})
+
+static void pe_expected(const char *exp)
+{
+	fprintf(stderr,"Parse error '%s' expected, at line %d\n",exp,line);
+	exit(10);
+}
+
+static void pe_expected_got(const char *exp, int got)
+{
+	fprintf(stderr,"Parse error '%s' expected but got %d, at line %d\n",
+		exp,got,line);
+	exit(10);
+}
+
+static void parse_global(void) {
+	EXP('{');
+	while(1) {
+		switch(yylex()) {
+		case TK_DISABLE_IP_VERIFICATION:
+			global_options.disable_ip_verification=1;
+			break;
+		case TK_MINOR_COUNT:
+			EXP(TK_INTEGER);
+			range_check(R_MINOR_COUNT,"minor-count",yylval.txt);
+			global_options.minor_count=atoi(yylval.txt);
+			break;
+		case TK_DIALOG_REFRESH:
+			EXP(TK_INTEGER);
+			range_check(R_DIALOG_REFRESH,"dialog-refresh",yylval.txt);
+			global_options.dialog_refresh=atoi(yylval.txt);
+			break;
+		case '}':
+			return;
+		default:
+			pe_expected("dialog-refresh | minor-count | "
+				    "disable-ip-verification");
+		}
+		EXP(';');
+	}
+}
+
+static struct d_option* parse_options(int token_switch,int token_option)
+{
+	char *opt_name;
+	int token;
+
+	struct d_option* options = NULL;
+
+	EXP('{');
+	while(1) {
+		token = yylex();
+		if( token == token_switch) {
+			options = APPEND(options,new_opt(yylval.txt,NULL));
+		} else if ( token == token_option) {
+			opt_name=yylval.txt;
+			EXP2(TK_STRING,TK_INTEGER);
+			options = APPEND(options,new_opt(opt_name,yylval.txt));
+		} else if ( token == '}' ) {
+			return options;
+		} else {
+			pe_expected("An option keyword");
+		}
+		EXP(';');
+	}
+}
+
+static void parse_host_section(struct d_resource* res)
+{
+	struct d_host_info *host;
+
+	c_section_start = line;
+
+	host=calloc(1,sizeof(struct d_host_info));
+	EXP(TK_STRING);
+	host->name = yylval.txt;
+	if(strcmp(host->name, nodeinfo.nodename) == 0) {
+		res->me = host;
+	} else {
+		if (res->peer) {
+			config_valid = 0;
+			fprintf(stderr,
+		"%s:%d: in resource %s, on %s { ... } ... on %s { ... }:\n"
+		"\tThere are multiple host sections for the peer.\n"
+		"\tMaybe misspelled local host name '%s'?\n",
+				config_file, c_section_start, res->name,
+				res->peer->name, host->name, nodeinfo.nodename);
+		}
+		res->peer = host;
+	}
+
+	EXP('{');
+	while(1) {
+		switch(yylex()) {
+		case TK_DISK:
+			EXP(TK_STRING);
+			host->disk = yylval.txt;
+			check_uniq("disk", "%s:%s:%s","disk",
+				   host->name,yylval.txt);
+			break;
+		case TK_DEVICE:
+			EXP(TK_STRING);
+			host->device = yylval.txt;
+			check_uniq("device", "%s:%s:%s","device",
+				   host->name,yylval.txt);
+			break;
+		case TK_ADDRESS:
+			EXP(TK_IPADDR);
+			host->address = yylval.txt;
+			EXP(':');
+			EXP(TK_INTEGER);
+			host->port = yylval.txt;
+			range_check(R_PORT, "port", yylval.txt);
+			break;
+		case TK_META_DISK:
+			EXP(TK_STRING);
+			host->meta_disk = yylval.txt;
+			if(strcmp("internal",yylval.txt)) {
+				EXP('[');
+				EXP(TK_INTEGER);
+				host->meta_index = yylval.txt;
+				EXP(']');
+			}
+			check_meta_disk(host);
+			break;
+		case TK_FLEX_META_DISK:
+			EXP(TK_STRING);
+			host->meta_disk = yylval.txt;
+			host->meta_index = strdup("flexible");
+			check_meta_disk(host);
+			break;
+		case '}':
+			goto break_loop;
+		default:
+			pe_expected("disk | device | address | meta-disk "
+				    "| flex-meta-disk");
+		}
+		EXP(';');
+	}
+ break_loop:
+	if (!host->device)	derror(host,res,"device");
+	if (!host->disk)	derror(host,res,"disk");
+	if (!host->address)	derror(host,res,"address");
+	if (!host->meta_disk)	derror(host,res,"meta-disk");
+}
+
+struct d_resource* parse_resource(char* res_name)
+{
+	struct d_resource* res;
+
+	res=calloc(1,sizeof(struct d_resource));
+	res->name = res_name;
+	res->next = NULL;
+
+	EXP('{');
+	while(1) {
+		switch(yylex()) {
+		case TK_PROTOCOL:
+			EXP(TK_STRING);
+			res->protocol=yylval.txt;
+			EXP(';');
+			break;
+		case TK_ON:
+			parse_host_section(res);
+			break;
+		case TK_DISK:
+			res->disk_options = parse_options(TK_DISK_SWITCH,
+							  TK_DISK_OPTION);
+			break;
+		case TK_NET: 
+			res->net_options = parse_options(TK_NET_SWITCH,
+							 TK_NET_OPTION);
+			break;
+		case TK_SYNCER:
+			res->sync_options = parse_options(TK_SYNCER_SWITCH,
+							  TK_SYNCER_OPTION);
+			break;
+		case TK_STARTUP:
+			res->startup_options=parse_options(TK_STARTUP_SWITCH,
+							   TK_STARTUP_OPTION);
+			break;
+		case TK_HANDLER:
+			res->handlers =  parse_options(0,
+						       TK_HANDLER_OPTION);
+			break;
+		case '}': return res;
+		default:
+			pe_expected("protocol | on | disk | net | syncer |"
+				    " startup | handler");
+		}
+	}
+}
+
+void parse_skip()
+{
+	int level=0;
+	do {
+		switch(yylex()) {
+		case '{': 
+			level++;
+			break;
+		case '}': 
+			level--;
+			break;
+		}
+	} while(level);
+}
+
+void yyparse(void)
+{
+	common = NULL;
+	config = NULL;
+
+	while(1) {
+		switch(yylex()) {
+		case TK_GLOBAL: parse_global(); break;
+		case TK_COMMON: common = parse_resource("common"); break;
+		case TK_RESOURCE: 
+			EXP(TK_STRING);
+			config = APPEND( config , parse_resource(yylval.txt) );
+			break;
+		case TK_SKIP: parse_skip(); break;
+		case 0: return;
+		default:
+			pe_expected("global | common | resource | skip");
+		}
+	}
+}

Added: trunk/user/drbdadm_parser.h
===================================================================
--- trunk/user/drbdadm_parser.h	2006-01-19 17:39:52 UTC (rev 2051)
+++ trunk/user/drbdadm_parser.h	2006-01-21 23:07:32 UTC (rev 2052)
@@ -0,0 +1,76 @@
+/*
+   drbdadm_parser.h a hand crafted parser
+
+   This file is part of drbd by Philipp Reisner.
+
+   Copyright (C) 2006, Philipp Reisner <philipp.reisner@linbit.com>.
+        Initial author.
+
+   drbd is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   drbd is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with drbd; see the file COPYING.  If not, write to
+   the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ */
+
+typedef union YYSTYPE {
+  char* txt;
+  struct d_option* d_option;
+  struct d_resource* d_resource;
+} YYSTYPE;
+
+#define yystype YYSTYPE /* obsolescent; will be withdrawn */
+#define YYSTYPE_IS_DECLARED 1
+#define YYSTYPE_IS_TRIVIAL 1
+
+extern YYSTYPE yylval;
+
+
+enum yytokentype {
+	 TK_GLOBAL = 258,
+	 TK_RESOURCE,
+	 TK_ON,
+	 TK_NET,
+	 TK_DISK,
+	 TK_SKIP,
+	 TK_SYNCER,
+	 TK_STARTUP,
+	 TK_DISABLE_IO_HINTS,
+	 TK_DISABLE_IP_VERIFICATION,
+	 TK_DIALOG_REFRESH,
+	 TK_PROTOCOL,
+	 TK_HANDLER, // 270
+	 TK_COMMON,
+	 TK_ADDRESS,
+	 TK_DEVICE,
+	 TK_META_DISK,
+	 TK_FLEX_META_DISK,
+	 TK_MINOR_COUNT,
+
+	 TK_IPADDR,
+	 TK_INTEGER,
+	 TK_STRING,
+	 TK_ELSE, // 280
+
+	 TK_DISK_SWITCH,
+	 TK_DISK_OPTION,
+	 TK_NET_SWITCH,
+	 TK_NET_OPTION,
+	 TK_SYNCER_SWITCH,
+	 TK_SYNCER_OPTION,
+	 TK_STARTUP_SWITCH,
+	 TK_STARTUP_OPTION,
+	 TK_HANDLER_OPTION
+};
+
+/* avoid compiler warnings about implicit declaration */
+int yylex(void);

Deleted: trunk/user/drbdadm_parser.y
===================================================================
--- trunk/user/drbdadm_parser.y	2006-01-19 17:39:52 UTC (rev 2051)
+++ trunk/user/drbdadm_parser.y	2006-01-21 23:07:32 UTC (rev 2052)
@@ -1,469 +0,0 @@
-%{
-
-#define _GNU_SOURCE
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "drbdadm.h"
-#include "drbd_limits.h"
-#include "drbdtool_common.h"
-
-extern void yyerror(char* text);
-extern int  yylex(void);
-
-#define YYDEBUG 1
-
-#define APPEND(LIST,ITEM) ({		      \
-  typeof((LIST)) _l = (LIST);		      \
-  typeof((ITEM)) _i = (ITEM);		      \
-  typeof((ITEM)) _t;			      \
-  _i->next = NULL;			      \
-  if (_l == NULL) { _l = _i; }		      \
-  else {				      \
-    for (_t = _l; _t->next; _t = _t->next);   \
-    _t->next = _i;			      \
-  };					      \
-  _l;					      \
-})
-
-static struct d_resource* c_res;
-static struct d_resource* c_config;
-static struct d_host_info* c_host;
-static char* c_hostname;
-static int   c_section_start, n_hosts;
-
-void
-m_strtoll_range(const char *s, char def_unit,
-		const char *name,
-		unsigned long long min, unsigned long long max)
-{
-  unsigned long long r = m_strtoll(s, def_unit);
-  char unit[] = { def_unit > '1' ? def_unit : 0, 0 };
-  if (min > r || r > max)
-    {
-      fprintf(stderr,
-	      "%s:%d: %s %s => %llu%s out of range [%llu..%llu]%s.\n",
-	      config_file, fline, name, s, r, unit, min, max, unit);
-      exit(E_config_invalid);
-    }
-  if (DEBUG_RANGE_CHECK)
-    {
-      fprintf(stderr,
-	      "%s:%d: %s %s => %llu%s in range [%llu..%llu]%s.\n",
-	      config_file, fline, name, s, r, unit, min, max, unit);
-    }
-}
-
-enum range_checks
-{
-  R_MINOR_COUNT,
-  R_DIALOG_REFRESH,
-  R_DISK_SIZE,
-  R_TIMEOUT,
-  R_CONNECT_INT,
-  R_PING_INT,
-  R_MAX_BUFFERS,
-  R_MAX_EPOCH_SIZE,
-  R_SNDBUF_SIZE,
-  R_KO_COUNT,
-  R_RATE,
-  R_GROUP,
-  R_AL_EXTENTS,
-  R_PORT,
-  R_META_IDX,
-  R_WFC_TIMEOUT,
-  R_DEGR_WFC_TIMEOUT,
-};
-
-void
-range_check(const enum range_checks what, const char *name, const char *value)
-{
-  switch (what)
-    {
-    default:
-      fprintf(stderr, "%s:%d: unknown range for %s => %s\n",
-	      config_file, fline, name, value);
-      break;
-    case R_MINOR_COUNT:
-      m_strtoll_range(value, 1, name,
-		      DRBD_MINOR_COUNT_MIN, DRBD_MINOR_COUNT_MAX);
-      break;
-    case R_DIALOG_REFRESH:
-      m_strtoll_range(value, 1, name,
-		      DRBD_DIALOG_REFRESH_MIN, DRBD_DIALOG_REFRESH_MAX);
-      break;
-    case R_DISK_SIZE:
-      m_strtoll_range(value, 'K', name,
-		      DRBD_DISK_SIZE_SECT_MIN >> 1,
-		      DRBD_DISK_SIZE_SECT_MAX >> 1);
-      break;
-    case R_TIMEOUT:
-      m_strtoll_range(value, 1, name, DRBD_TIMEOUT_MIN, DRBD_TIMEOUT_MAX);
-      break;
-    case R_CONNECT_INT:
-      m_strtoll_range(value, 1, name, DRBD_CONNECT_INT_MIN,
-		      DRBD_CONNECT_INT_MAX);
-      break;
-    case R_PING_INT:
-      m_strtoll_range(value, 1, name, DRBD_PING_INT_MIN, DRBD_PING_INT_MAX);
-      break;
-    case R_MAX_BUFFERS:
-      m_strtoll_range(value, 1, name, DRBD_MAX_BUFFERS_MIN,
-		      DRBD_MAX_BUFFERS_MAX);
-      break;
-    case R_MAX_EPOCH_SIZE:
-      m_strtoll_range(value, 1, name, DRBD_MAX_EPOCH_SIZE_MIN,
-		      DRBD_MAX_EPOCH_SIZE_MAX);
-      break;
-    case R_SNDBUF_SIZE:
-      m_strtoll_range(value, 1, name, DRBD_SNDBUF_SIZE_MIN,
-		      DRBD_SNDBUF_SIZE_MAX);
-      break;
-    case R_KO_COUNT:
-      m_strtoll_range(value, 1, name, DRBD_KO_COUNT_MIN, DRBD_KO_COUNT_MAX);
-      break;
-    case R_RATE:
-      m_strtoll_range(value, 'K', name, DRBD_RATE_MIN, DRBD_RATE_MAX);
-      break;
-    case R_AL_EXTENTS:
-      m_strtoll_range(value, 1, name, DRBD_AL_EXTENTS_MIN,
-		      DRBD_AL_EXTENTS_MAX);
-      break;
-    case R_PORT:
-      m_strtoll_range(value, 1, name, DRBD_PORT_MIN, DRBD_PORT_MAX);
-      break;
-      /* FIXME not yet implemented!
-         case R_META_IDX:
-         m_strtoll_range(value, 1, name, DRBD_META_IDX_MIN, DRBD_META_IDX_MAX);
-         break;
-       */
-    case R_WFC_TIMEOUT:
-      m_strtoll_range(value, 1, name, DRBD_WFC_TIMEOUT_MIN,
-		      DRBD_WFC_TIMEOUT_MAX);
-      break;
-    case R_DEGR_WFC_TIMEOUT:
-      m_strtoll_range(value, 1, name, DRBD_DEGR_WFC_TIMEOUT_MIN,
-		      DRBD_DEGR_WFC_TIMEOUT_MAX);
-      break;
-    }
-}
-
-static struct d_option* new_opt(char* name,char* value)
-{
-  struct d_option* cn = malloc(sizeof(struct d_option));
-
-  /* fprintf(stderr,"%s:%d: %s = %s\n",config_file,line,name,value); */
-  cn->name=name;
-  cn->value=value;
-  cn->mentioned=0;
-
-  return cn;
-}
-
-static void derror(char* text)
-{
-  config_valid=0;
-  fprintf(stderr, "%s:%d: in resource %s, on %s { ... }:"
-	          " '%s' keyword missing.\n",
-	  config_file,c_section_start,c_res->name,c_hostname,text);
-}
-
-static void host_sec(char *name)
-{
-  c_host->name = name;
-  if (!c_host->device)	  derror("device");
-  if (!c_host->disk)	  derror("disk");
-  if (!c_host->address)   derror("address");
-  if (!c_host->meta_disk) derror("meta-disk");
-
-  if (strcmp(name, nodeinfo.nodename) == 0) {
-    // if (c_res->me) error(...); -- already done by check_uniq in the rules.
-    c_res->me = c_host;
-  } else {
-    if (c_res->peer) {
-      config_valid = 0;
-      fprintf(stderr,
-	      "%s:%d: in resource %s, on %s { ... } ... on %s { ... }:\n"
-	      "\tThere are multiple host sections for the peer.\n"
-	      "\tMaybe misspelled local host name '%s'?\n",
-	      config_file, c_section_start, c_res->name,
-	      c_res->peer->name, c_hostname, nodeinfo.nodename);
-    }
-    c_res->peer = c_host;
-  }
-}
-
-static struct d_resource* new_resource(char* name)
-{
-  struct d_resource* res;
-  res=calloc(1,sizeof(struct d_resource));
-  res->name=name;
-  res->next = NULL;
-
-  return res;
-}
-
-void check_meta_disk()
-{
-  if (strcmp(c_host->meta_disk, "internal") != 0) {
-    /* external */
-    if (c_host->meta_index == NULL) {
-      fprintf(stderr, "%s:%d: expected 'meta-disk = %s [index]'.\n",
-	      config_file, fline, c_host->meta_disk);
-    }
-    /* index either some number, or "flexible" */
-    check_uniq("meta-disk", "%s:%s[%s]", c_hostname,
-	       c_host->meta_disk, c_host->meta_index);
-  } else if (c_host->meta_index) {
-    /* internal */
-    if (strcmp(c_host->meta_index,"flexible") != 0) {
-      /* internal, not flexible, but index given: no sir! */
-      fprintf(stderr,
-	      "%s:%d: no index allowed with 'meta-disk = internal'.\n",
-	      config_file, fline);
-    } /* else internal, flexible: fine */
-  } else {
-    /* internal, not flexible */
-    c_host->meta_index = strdup("internal");
-  }
-}
-
-#define CHKU(what,val) \
-	c_host->what = val; \
-	check_uniq( #what, "%s:%s:%s", #what, c_hostname,val)
-
-#define CHKS(sname) \
-	check_uniq(sname " section","%s:" sname, c_res->name)
-%}
-
-%union {
-  char* txt;
-  struct d_option* d_option;
-  struct d_resource* d_resource;
-}
-
-%token TK_GLOBAL TK_RESOURCE
-%token TK_ON TK_NET TK_DISK_S TK_SYNCER TK_STARTUP
-%token TK_DISABLE_IO_HINTS
-%token TK_DISABLE_IP_VERIFICATION
-%token TK_PROTOCOL TK_HANDLERS TK_COMMON
-%token TK_ADDRESS TK_DISK TK_DEVICE TK_META_DISK TK_FLEX_META_DISK
-%token <txt> TK_MINOR_COUNT TK_INTEGER TK_STRING
-%token <txt> TK_ON_IO_ERROR TK_SIZE TK_SPLIT_BRAIN_FIX
-%token <txt> TK_TIMEOUT TK_CONNECT_INT TK_PING_INT TK_MAX_BUFFERS TK_IPADDR
-%token <txt> TK_MAX_EPOCH_SIZE TK_SNDBUF_SIZE
-%token <txt> TK_SKIP_SYNC TK_USE_CSUMS TK_RATE TK_SYNC_AFTER TK_AL_EXTENTS
-%token <txt> TK_WFC_TIMEOUT TK_DEGR_WFC_TIMEOUT
-%token <txt> TK_KO_COUNT TK_ON_DISCONNECT TK_DIALOG_REFRESH
-%token <txt> TK_ALLOW_TWO_PRIMARIES
-%token <txt> TK_PRI_ON_INCON_DEGR TK_PRI_LOST_AFTER_SB
-%token <txt> TK_OUTDATE_PEER TK_CRAM_HMAC_ALG TK_SHARED_SECRET
-%token <txt> TK_AFTER_SB_PRI
-
-%type <txt> hostname resource_name
-%type <d_option> disk_stmts disk_stmt
-%type <d_option> net_stmts net_stmt
-%type <d_option> sync_stmts sync_stmt
-%type <d_option> startup_stmts startup_stmt
-%type <d_option> handler_stmts handler_stmt
-%type <d_resource> resources resource
-
-%%
-config:		  global_sec common resources	 { config=$3; }
-		;
-
-global_sec:	  /* empty */
-		| TK_GLOBAL glob_stmts
-		;
-
-glob_stmts:	  /* empty */
-		| glob_stmts glob_stmt
-		;
-
-glob_stmt:	  TK_DISABLE_IO_HINTS
-		{
-		    fprintf(stderr,
-			    "%s:%d: in global section, "
-			    "useless use of no longer available option \"disable_io_hints\".\n",
-			    config_file, line);
-		}
-		|  TK_DISABLE_IP_VERIFICATION
-		{ global_options.disable_ip_verification=1; }
-		| TK_MINOR_COUNT TK_INTEGER
-		{
-			range_check(R_MINOR_COUNT,$1,$2);
-			global_options.minor_count=atoi($2);
-		}
-		| TK_DIALOG_REFRESH TK_INTEGER
-                {
-			range_check(R_DIALOG_REFRESH,$1,$2);
-			global_options.dialog_refresh=atoi($2);
-		}
-		;
-
-common:		  /* empty */	      { common = NULL;  }
-		| TK_COMMON { c_res = new_resource("common"); } 
-			res_stmts { common = c_res; }
-		;
-
-resources:	  /* empty */	     { $$ = 0; c_config = 0; }
-		| resources resource { $$=APPEND($1,$2); c_config=$$; }
-		;
-
-resource:	TK_RESOURCE { n_hosts = 0; } resource_name res_stmts
-			{ $$ = c_res; validate_resource(c_res); }
-		;
-
-resource_name:	TK_STRING
-		{
-			int uniq;
-			c_resource_start = line;
-			c_res		 = new_resource($1);
-			uniq = check_uniq("resource","%s",$1);
-			if (!uniq) exit(E_config_invalid);
-		}
-		;
-
-res_stmts:	  /* empty */
-		| res_stmts res_stmt
-		| res_stmts section
-		;
-
-res_stmt:	  TK_PROTOCOL	    TK_STRING { c_res->protocol=$2; }
-		;
-
-section:	  TK_DISK_S   disk_stmts
-		{ CHKS("disk");    c_res->disk_options=$2;    }
-		| TK_NET      net_stmts
-		{ CHKS("net");     c_res->net_options=$2;     }
-		| TK_SYNCER   sync_stmts
-		{ CHKS("syncer");  c_res->sync_options=$2;    }
-		| TK_STARTUP  startup_stmts
-		{ CHKS("startup"); c_res->startup_options=$2; }
-		| TK_ON hostname host_stmts { host_sec($2); }
-		| TK_HANDLERS  handler_stmts
-		{ CHKS("handlers"); c_res->handlers=$2; }
-		;
-
-hostname:	TK_STRING
-		{
-		  int uniq;
-		  c_section_start = line;
-		  c_hostname = $1;
-		  uniq = check_uniq("host section", "%s: on %s",
-				    c_res->name, c_hostname);
-		  if (!uniq)
-		    exit(E_config_invalid);
-		  if (++n_hosts > 2) {
-		    fprintf(stderr,
-			    "%s:%d: in resource %s, "
-			    "unsupported third host section on %s { ... }.\n",
-			    config_file, c_section_start, c_res->name,
-			    c_hostname);
-		    exit(E_config_invalid);
-		  }
-		}
-		;
-
-disk_stmts:	  /* empty */	           { $$ = NULL; }
-		| disk_stmts disk_stmt	   { $$=APPEND($1,$2); }
-		;
-
-disk_stmt:	  TK_ON_IO_ERROR TK_STRING { $$=new_opt($1,$2); }
-		| TK_SIZE TK_INTEGER
-		{ $$=new_opt($1,$2); range_check(R_DISK_SIZE,$1,$2); }
-		| TK_SPLIT_BRAIN_FIX       { $$=new_opt($1,NULL);  }
-		;
-
-net_stmts:	  /* empty */	           { $$ = NULL; }
-		| net_stmts net_stmt       { $$=APPEND($1,$2); }
-		;
-
-net_stmt:	  TK_TIMEOUT	    TK_INTEGER
-		{ range_check(R_TIMEOUT,$1,$2);		$$=new_opt($1,$2); }
-		| TK_CONNECT_INT    TK_INTEGER
-		{ range_check(R_CONNECT_INT,$1,$2);	$$=new_opt($1,$2); }
-		| TK_PING_INT	    TK_INTEGER
-		{ range_check(R_PING_INT,$1,$2);	$$=new_opt($1,$2); }
-		| TK_MAX_BUFFERS    TK_INTEGER
-		{ range_check(R_MAX_BUFFERS,$1,$2);	$$=new_opt($1,$2); }
-		| TK_MAX_EPOCH_SIZE TK_INTEGER
-		{ range_check(R_MAX_EPOCH_SIZE,$1,$2);	$$=new_opt($1,$2); }
-		| TK_SNDBUF_SIZE    TK_INTEGER
-		{ range_check(R_SNDBUF_SIZE,$1,$2);	$$=new_opt($1,$2); }
-		| TK_KO_COUNT       TK_INTEGER
-		{ range_check(R_KO_COUNT,$1,$2);	$$=new_opt($1,$2); }
-		| TK_ON_DISCONNECT  TK_STRING	{	$$=new_opt($1,$2); }
-		| TK_ALLOW_TWO_PRIMARIES	{	$$=new_opt($1,NULL); }
-		| TK_CRAM_HMAC_ALG  TK_STRING	{	$$=new_opt($1,$2); }
-		| TK_SHARED_SECRET  TK_STRING	{	$$=new_opt($1,$2); }
-                | TK_AFTER_SB_PRI   TK_STRING	{	$$=new_opt($1,$2); }
-		;
-
-sync_stmts:	  /* empty */	           { $$ = NULL; }
-		| sync_stmts sync_stmt	   { $$=APPEND($1,$2); }
-		;
-
-sync_stmt:	  TK_SKIP_SYNC		   { $$=new_opt($1,NULL);  }
-		| TK_USE_CSUMS		   { $$=new_opt($1,NULL);  }
-		| TK_RATE	TK_INTEGER
-		{ range_check(R_RATE,$1,$2); $$=new_opt($1,$2); }
-		| TK_SYNC_AFTER TK_STRING  { $$=new_opt($1,$2); }
-		| TK_AL_EXTENTS TK_INTEGER { $$=new_opt($1,$2); }
-		{ range_check(R_AL_EXTENTS,$1,$2); $$=new_opt($1,$2); }
-		;
-
-host_stmts:	  /* empty */ { c_host=calloc(1,sizeof(struct d_host_info)); }
-		| host_stmts host_stmt
-		;
-
-host_stmt:	  TK_DISK    TK_STRING	  { CHKU(disk,$2); }
-		| TK_DEVICE  TK_STRING	  { CHKU(device,$2); }
-		| TK_ADDRESS ip_and_port
-		{ check_uniq("IP","%s:%s", c_host->address,c_host->port); }
-		| TK_META_DISK meta_disk_and_index { check_meta_disk(); }
-		| TK_FLEX_META_DISK flex_meta_disk { check_meta_disk(); }
-		;
-
-
-ip_and_port:	  TK_IPADDR TK_INTEGER
-		{
-			range_check(R_PORT, "port", $2);
-			c_host->address=$1; c_host->port = $2;
-		}
-		;
-
-flex_meta_disk:
-		  TK_STRING
-		{
-			c_host->meta_disk = $1;
-			/* overload index once more */
-			c_host->meta_index = strdup("flexible");
-		}
-		;
-meta_disk_and_index:
-		  TK_STRING TK_INTEGER
-		{ c_host->meta_disk = $1; c_host->meta_index = $2; }
-		| TK_STRING { c_host->meta_disk = $1; }
-		;
-
-startup_stmts:	  /* empty */  { $$ = NULL; }
-		| startup_stmts startup_stmt   { $$=APPEND($1,$2); }
-		;
-
-startup_stmt:	  TK_WFC_TIMEOUT      TK_INTEGER
-		{ range_check(R_WFC_TIMEOUT,$1,$2);	$$=new_opt($1,$2); }
-		| TK_DEGR_WFC_TIMEOUT TK_INTEGER
-		{ range_check(R_DEGR_WFC_TIMEOUT,$1,$2);$$=new_opt($1,$2); }
-		;
-
-handler_stmts:	  /* empty */	           { $$ = NULL; }
-		| handler_stmts handler_stmt	   { $$=APPEND($1,$2); }
-		;
-
-handler_stmt:	  TK_PRI_ON_INCON_DEGR TK_STRING	{ $$=new_opt($1,$2); }
-		| TK_PRI_LOST_AFTER_SB TK_STRING	{ $$=new_opt($1,$2); }
-		| TK_OUTDATE_PEER TK_STRING		{ $$=new_opt($1,$2); }
-		;

Modified: trunk/user/drbdadm_scanner.fl
===================================================================
--- trunk/user/drbdadm_scanner.fl	2006-01-19 17:39:52 UTC (rev 2051)
+++ trunk/user/drbdadm_scanner.fl	2006-01-21 23:07:32 UTC (rev 2052)
@@ -1,427 +1,104 @@
 %{
-/*
-*/
-
+#include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
-#include <ctype.h>
-#include "drbdadm.h"
 #include "drbdadm_parser.h"
+#include "drbdadm.h"
 
-static void update_lcnt(void);
-static void section(int);
-static void named_section(int);
-static void do_assign(int);
+void long_string(char* text);
 static void unescape(void);
-static void unescape_midx(void);
-/* static char* const escape(char* const str); */
-static void syntax_error(char*);
-static void expect_error(char*);
 
-#define CP		yylval.txt = strdup(yytext);
+#if 0
+#define DP printf("'%s' ",yytext)
+#else
+#define DP
+#endif
 
+#define CP yylval.txt = strdup(yytext)
+
 #define YY_NO_UNPUT 1
-static int yy_top_state(void) __attribute((unused)); /* no unused warning */
 static void yyunput (int c, register char * yy_bp ) __attribute((unused));
 
-#define PRINTF(fmt, args...) \
-  fprintf(stderr, "%s:%d: " fmt, config_file, line , ## args )
+int skip_level=0;
 
-/* This is an "unusual" scanner. If someone tells me how to do this in
- * the parser instead, tell me. I just was not able to make the error
- * handling of yacc do what I want.
- *		-- lge
- */ 
-
 %}
 
 %option noyywrap
-%option stack
 
-%x RESOURCE GLOBAL
-%x STARTUP DISK NET SYNCER HOST HANDLERS COMMON
-%x SEMICOLON ASSIGN NUM NUM_U NAME STRING PROTO IO_ERROR ON_DISCONNECT
-%x IP_AND_PORT PORT FLEX_META_DISK META_DISK META_IDX
-%x LS LBRACE IGNORE_SECTION
+NUM		[0-9]{1,8}[MKG]?
+SNUMB		[0-9]{1,3}
+IPV4ADDR	({SNUMB}"."){3}{SNUMB}
+WS		[ \t]
+OPCHAR		[{};\[\]:]
+DQSTRING	\"[^\"\\\n]{1,255}\"
+STRING		[a-zA-Z0-9/._-]{1,80}
+LONG_STRING	[a-zA-Z0-9/._-]{81}
 
-LS			  [ \t]{1,80}
-WS			  ({LS}|\n)
-COMMENT_START		  \#
-ASSIGN			  {LS}
-OUT_OF_RANGE_NUM	  [0-9]{10,}[kmgKMG]? 
-NUM			  [0-9]{1,9}
-NUM_U			  [0-9]{1,9}[kmgKMG]? 
-NAME			  [/_.A-Za-z0-9-]{1,80}
-ENAME			  [/_.A-Za-z0-9-]{81}
-L_NO_DQUOTES		  [^\"\\\n]
-STRING			  ({NAME}|\"{L_NO_DQUOTES}{1,220}\")
-ESTRING			  (\"{L_NO_DQUOTES}{221}|\"\")
-DISK			  disk
-INTERN			  internal|\"internal\"
-META_IDX		  {LS}?\[{LS}?{NUM}{LS}?\]
-O_IDX			  {WS}meta-index{ASSIGN}
-IGNORE			  {WS}
-SKIP			  skip({LS}[^{\n]{0,80})?
-NDELIM			  [^ \t\n#;{}]{1,50}
-_1_254			  [1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-4]
-_0_255			  0|[1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]
-IPV4ADDR		  {_1_254}\.{_0_255}\.{_0_255}\.{_1_254}
-PORT			  {WS}port{ASSIGN}{NUM}
-COMMON			  common
-AFTER_SB_PRI		  after-sb-[012]pri
+%x in_string id skip
 
 %%
 
-<INITIAL,RESOURCE>{
-  {SKIP}		section(IGNORE_SECTION);
-}
+\n			{ line++; 				}
+#[^\n]*			/* ignore comments */
+{WS}			/* ignore whitespaces */
+{OPCHAR}		{ DP; return yytext[0];			}
+on			{ DP; return TK_ON;			}
+net			{ DP; return TK_NET;			}
+skip			{ DP; return TK_SKIP;			}
+disk			{ DP; return TK_DISK;			}
+syncer			{ DP; return TK_SYNCER;			}
+device			{ DP; return TK_DEVICE;			}
+global			{ DP; return TK_GLOBAL;			}
+common			{ DP; return TK_COMMON;			}
+address			{ DP; return TK_ADDRESS;		}
+startup			{ DP; return TK_STARTUP;		}
+handlers		{ DP; return TK_HANDLER;		}
+protocol		{ DP; return TK_PROTOCOL;		}
+minor-count		{ DP; return TK_MINOR_COUNT;		}
+disable-io-hints	{ DP; return TK_DISABLE_IO_HINTS;	}
+disable-ip-verfification {DP; return TK_DISABLE_IP_VERIFICATION;}
+dialog-refresh		{ DP; return TK_DIALOG_REFRESH;		}
+resource		{ DP; return TK_RESOURCE;		}
+meta-disk		{ DP; return TK_META_DISK;		}
+flexible-meta-disk	{ DP; return TK_FLEX_META_DISK;		}
+size			{ DP; CP; return TK_DISK_OPTION;	}
+on-io-error		{ DP; CP; return TK_DISK_OPTION;	}
+split-brain-fix		{ DP; CP; return TK_DISK_SWITCH;	}
+timeout			{ DP; CP; return TK_NET_OPTION;		}
+ping-int		{ DP; CP; return TK_NET_OPTION;		}
+max-buffers		{ DP; CP; return TK_NET_OPTION;		}
+sndbuf-size		{ DP; CP; return TK_NET_OPTION;		}
+connect-int		{ DP; CP; return TK_NET_OPTION;		}
+max-epoch-size		{ DP; CP; return TK_NET_OPTION;		}
+after-sb-[012]pri	{ DP; CP; return TK_NET_OPTION;		}
+allow-two-primaries	{ DP; CP; return TK_NET_SWITCH;		}
+rate			{ DP; CP; return TK_SYNCER_OPTION;	}
+after			{ DP; CP; return TK_SYNCER_OPTION;	}
+use-csums		{ DP; CP; return TK_SYNCER_SWITCH;	}
+skip-sync		{ DP; CP; return TK_SYNCER_SWITCH;	}
+al-extents		{ DP; CP; return TK_SYNCER_OPTION; 	}
+wfc-timeout		{ DP; CP; return TK_STARTUP_OPTION;	}
+degr-wfc-timeout	{ DP; CP; return TK_STARTUP_OPTION;	}
+pri-on-incon-degr	{ DP; CP; return TK_HANDLER_OPTION;	}
+pri-lost-after-sb	{ DP; CP; return TK_HANDLER_OPTION;	}
+outdate-peer		{ DP; CP; return TK_HANDLER_OPTION;	}
+{IPV4ADDR}		{ DP; CP; return TK_IPADDR;		}
+{NUM}			{ DP; CP; return TK_INTEGER;		}
+{DQSTRING}		{ unescape(); DP; CP; return TK_STRING;	}
+{STRING}		{ DP; CP; return TK_STRING;		}
+{LONG_STRING}		{ long_string( yylval.txt ); 		}
+[^\n]			{ DP; return TK_ELSE;			}
 
-<INITIAL,ASSIGN,LBRACE,META_IDX,RESOURCE,GLOBAL,STARTUP,DISK,NET,SYNCER,HOST,HANDLERS,PORT>{
-  {COMMENT_START}	{
-  				char c;
-				while ((c = input()) != '\n' && c != EOF);
-				if (c == '\n') ++line;
-			}
-}
-
-<INITIAL>{
-  {WS}			update_lcnt();
-  global		section(GLOBAL); return TK_GLOBAL;
-  resource		named_section(RESOURCE); return TK_RESOURCE;
-  \}			syntax_error("unmached closing brace.");
-  common		section(COMMON); return TK_COMMON;
-  {NDELIM}		expect_error("one of 'global|resource'");
-}
-
-<RESOURCE,GLOBAL,IGNORE_SECTION,STARTUP,DISK,NET,SYNCER,HOST,HANDLERS,COMMON>{
-  {IGNORE}		update_lcnt();
-  \}			yy_pop_state();
-}
-
-<NAME>{
-  {ENAME}		syntax_error("name too long.\n");
-  {NAME}		yy_pop_state(); CP; return TK_STRING;
-  [^ \t\n#]{1,80}	expect_error("name"); /* not referenced currently */
-}
-
-<SEMICOLON>{
-  {LS}			/* ignore */
-  ;			yy_pop_state();
-  \n                    yy_pop_state(); PRINTF("missing ';'\n"); line++; 
-  {NDELIM}   		expect_error("';'");
-}
-
-<ASSIGN>{
-  {ASSIGN}		yy_pop_state(); fline = line;
-  =			syntax_error("don't use '=' signs anymore!");
-  {WS}			syntax_error("linebreak between option and value not allowed.\n");
-  {NDELIM}		expect_error("whitespace");
-}
-
-<NUM,NUM_U>{
-  {OUT_OF_RANGE_NUM}	{
-			  PRINTF("%s: number exeeds limit of 9 digits\n", yytext);
-			  exit(E_syntax);
-			}
-}
-
-<NUM>{
-  {NUM}			yy_pop_state(); CP; return TK_INTEGER;
-  {NDELIM}		expect_error("integer"); yy_pop_state();
-}
-
-<NUM_U>{
-  {NUM_U}		yy_pop_state(); CP; return TK_INTEGER;
-  {NDELIM}		expect_error("[0-9]+[KMG]?"); yy_pop_state();
-}
-
-<STRING>{
-  {ENAME}		syntax_error("name too long.\n");
-  {ESTRING}		syntax_error("string terminator missing or string too long.\n");
-  {STRING}		yy_pop_state(); unescape(); CP; return TK_STRING;
-  {NDELIM}		expect_error("string"); yy_pop_state();
-}
-
-<PROTO>{
-  \"[abcABC]\"		yy_pop_state(); unescape(); CP; return TK_STRING;
-  [abcABC]		yy_pop_state(); CP; return TK_STRING;
-  {NDELIM}		expect_error("one of 'A|B|C'"); yy_pop_state();
-}
-
-<PORT>{
-  :			BEGIN(NUM); /* this is only reached when I have a colon */
-  {WS}			update_lcnt();
-  port{ASSIGN}		{
-			  /* or a 'port = ' following the 'address = ' */
-			  update_lcnt(); BEGIN(NUM);
-			  PRINTF("'port=<port>' deprecated, "
-				 "please use 'IP:port' instead.\n");
-			}
-}
-
-<IP_AND_PORT>{
-  {LS}			/* ignore */
-  \"			syntax_error("please do not quote IP:PORT.\n");
-  {IPV4ADDR}/:{NUM}	BEGIN(PORT); CP; return TK_IPADDR;
-  {IPV4ADDR}/{PORT}	BEGIN(PORT); CP; return TK_IPADDR;
-  {IPV4ADDR}		syntax_error("':PORT' missing from IP:PORT.\n");
-  {NDELIM}		expect_error("IP and port 'XXX.XXX.XXX.XXX:PORT'");
-}
-
-<META_IDX>{
-  {META_IDX}		unescape_midx(); yy_pop_state(); CP; return TK_INTEGER;
-  {WS}			update_lcnt();
-  {O_IDX}		{
-			  update_lcnt(); BEGIN(NUM);
-			  PRINTF("'meta-index=<idx>' deprecated, "
-				 "please use 'meta-disk /di/sk [idx]' instead.\n");
-			}
-}
-
-<FLEX_META_DISK>{
-  {INTERN}		unescape(); yy_pop_state();  CP; return TK_STRING;
-  {INTERN}{META_IDX}	|
-  {INTERN}{O_IDX}	syntax_error("don't give an index for flexible meta-data.");
-  {ESTRING}		syntax_error("string terminator missing or string too long.\n");
-  {STRING}		unescape(); yy_pop_state(); CP; return TK_STRING;
-  {STRING}{META_IDX}	|
-  {STRING}{O_IDX}{NUM}  syntax_error("don't give an index for flexible meta-data.");
-  {STRING}{LS}?{NDELIM}	|
-  {NDELIM}		expect_error("either 'internal' or '/dev/ice/name [index]'");
-}
-
-<META_DISK>{
-  {INTERN}		unescape(); yy_pop_state();  CP; return TK_STRING;
-  {INTERN}{META_IDX}	|
-  {INTERN}{O_IDX}	syntax_error("don't give an index for internal meta-data.");
-  {ESTRING}		syntax_error("string terminator missing or string too long.\n");
-  {STRING}/{META_IDX}	|
-  {STRING}/{O_IDX}{NUM} unescape(); BEGIN(META_IDX); CP; return TK_STRING;
-  {STRING}{LS}?{NDELIM}	expect_error("meta-disk: index missing; either 'internal' or '/dev/ice/name [index]'");
-  {NDELIM}		expect_error("either 'internal' or '/dev/ice/name [index]'");
-}
-
-<LS>{
-  {LS}			update_lcnt(); yy_pop_state();
-  {NDELIM}		expect_error("whitespace"); yy_pop_state();
-}
-
-<LBRACE>{
-  {WS}			update_lcnt();
-  \{			update_lcnt(); yy_pop_state();
-  [^{ \t\n]{1,40}	expect_error("'{'");
-}
-
-<IGNORE_SECTION>{
-  [^{}\n]{1,80}		/* no ECHO */
-  {WS}			update_lcnt(); /* no ECHO */
-  \{			yy_push_state(IGNORE_SECTION);
-}
-
-<GLOBAL>{
-  minor-count	do_assign(NUM); CP; return TK_MINOR_COUNT;
-  disable-io-hints yy_push_state(SEMICOLON); return TK_DISABLE_IO_HINTS;
-  dialog-refresh        do_assign(NUM); CP; return TK_DIALOG_REFRESH;
-  disable-ip-verification  yy_push_state(SEMICOLON); return TK_DISABLE_IP_VERIFICATION;
-  {NDELIM}		expect_error("'minor-count|disable-io-hints|dialog-refresh'");
-}
-
-<RESOURCE>{
-  on			named_section(HOST); return TK_ON;
-  startup		section(STARTUP);    return TK_STARTUP;
-  syncer		section(SYNCER);     return TK_SYNCER;
-  disk			section(DISK);	     return TK_DISK_S;
-  net			section(NET);	     return TK_NET;
-  handlers		section(HANDLERS);   return TK_HANDLERS;
-
-  protocol		do_assign(PROTO);  CP; return TK_PROTOCOL;
-  {NDELIM}		{
-			  expect_error(
-				"one of 'protocol"
-				"startup|disk|net|syncer|on <HOSTNAME>'|"
-				"handlers");
-			}
-}
-
-<STARTUP>{
-  wfc-timeout		do_assign(NUM); CP; return TK_WFC_TIMEOUT;
-  degr-wfc-timeout	do_assign(NUM); CP; return TK_DEGR_WFC_TIMEOUT;
-  {NDELIM}		expect_error("one of 'wfc-timeout|degr-wfc-timeout'");
-}
-
-<DISK>{
-  on-io-error		do_assign(IO_ERROR); CP; return TK_ON_IO_ERROR;
-  split-brain-fix 	yy_push_state(SEMICOLON); CP; return TK_SPLIT_BRAIN_FIX;
-  size                  do_assign(NUM_U); CP; return TK_SIZE;
-  {NDELIM}		expect_error("'on-io-error|split-brain-fix|size'");
-}
-
-<IO_ERROR>{
-  pass_on		|
-  panic			|
-  detach		yy_pop_state(); CP; return TK_STRING;
-  {NDELIM}		expect_error("one of 'pass_on|panic|detach'");
-}
-
-<ON_DISCONNECT>{
-  reconnect		|
-  stand_alone		|
-  freeze_io		yy_pop_state(); CP; return TK_STRING;
-  {NDELIM}		expect_error("one of 'reconnect|stand_alone|freeze_io'");
-}
-
-<NET>{
-  sndbuf-size		do_assign(NUM_U); CP; return TK_SNDBUF_SIZE;
-  timeout		do_assign(NUM);   CP; return TK_TIMEOUT;
-  ping-int		do_assign(NUM);   CP; return TK_PING_INT;
-  connect-int		do_assign(NUM);   CP; return TK_CONNECT_INT;
-  max-buffers		do_assign(NUM);   CP; return TK_MAX_BUFFERS;
-  max-epoch-size	do_assign(NUM);   CP; return TK_MAX_EPOCH_SIZE;
-  ko-count		do_assign(NUM);   CP; return TK_KO_COUNT;
-  on-disconnect 	do_assign(ON_DISCONNECT); CP; return TK_ON_DISCONNECT;
-  allow-two-primaries   yy_push_state(SEMICOLON); CP; return TK_ALLOW_TWO_PRIMARIES;
-  cram-hmac-alg		do_assign(STRING); CP; return TK_CRAM_HMAC_ALG;
-  shared-secret		do_assign(STRING); CP; return TK_SHARED_SECRET;
-  {AFTER_SB_PRI}	do_assign(STRING); CP; return TK_AFTER_SB_PRI;
-
-  {NDELIM}		expect_error("one of 'sndbuf-size|timeout|ping-int|connect-int|max-buffers|max-epoch-size|ko-count|on-disconnect|cram-hmac-alg|shared-secret|after-sb-[012]pri'");
-}
-
-<SYNCER>{
-  rate			do_assign(NUM_U); CP; return TK_RATE;
-  after			do_assign(STRING);CP; return TK_SYNC_AFTER;
-  al-extents		do_assign(NUM);   CP; return TK_AL_EXTENTS;
-  {NDELIM}		expect_error("one of 'rate|after|al-extents'");
-}
-
-<HOST>{
-  address		do_assign(IP_AND_PORT); CP; return TK_ADDRESS;
-  device		do_assign(STRING);	CP; return TK_DEVICE;
-  {DISK}		do_assign(STRING);	CP; return TK_DISK;
-  flex-meta-disk	|
-  flexible-meta-disk	do_assign(FLEX_META_DISK);CP; return TK_FLEX_META_DISK;
-  meta-disk		do_assign(META_DISK);	CP; return TK_META_DISK;
-  {NDELIM}		expect_error("one of 'address|device|disk|meta-disk'");
-}
-
-<HANDLERS>{
-  pri-on-incon-degr	do_assign(STRING); CP; return TK_PRI_ON_INCON_DEGR;
-  pri-lost-after-sb     do_assign(STRING); CP; return TK_PRI_LOST_AFTER_SB;
-  outdate-peer		do_assign(STRING); CP; return TK_OUTDATE_PEER;
-  {NDELIM}		{
-	  		  expect_error(
-				"one of 'pri-on-incon-degr|"
-				"pri-lost-after-sb|"
-				"outdate-peer");
-			}
-}
-
-<COMMON>{
-  startup		section(STARTUP);    return TK_STARTUP;
-  syncer		section(SYNCER);     return TK_SYNCER;
-  disk			section(DISK);	     return TK_DISK_S;
-  net			section(NET);	     return TK_NET;
-  handlers		section(HANDLERS);   return TK_HANDLERS;
-
-  {NDELIM}		{
-			  expect_error(
-				"one of 'startup|disk|net|syncer|handlers");
-			}
-}
-
-<*>{
-  \{			syntax_error("unexpected opening brace.");
-  \n			syntax_error("unexpected end of line, maybe missing ';' ? ");
-  .			expect_error("something else");
-  <<EOF>>		{
-			  if (YY_START != INITIAL)
-			    syntax_error("unexpected end of file. Maybe missing closing brace?.");
-			  /* else
-			    fprintf(stderr,"\n--- End of File. OK\n");
-			  */
-			  yyterminate();
-			}
-}
-
 %%
 
-static void syntax_error(char *err)
-{
-  PRINTF("%s\n", err);
-  exit(E_syntax);
-}
 
-static void expect_error(char *err)
-{
-  PRINTF("%s expected, not '%s'.\n", err, yytext);
-  exit(E_syntax);
-}
 
-static void update_lcnt(void)
+void long_string(char* text)
 {
-  char *p = yytext;
-  while (*p) {
-    if (*p++ == '\n')
-      ++line;
-  }
+  fprintf(stderr,"Too long token '%s' in line %d.\n",text,line);
+  exit(2);
 }
 
-static void section(int sect)
-{
-  static int s = 0;
-  static int g = 0;
-  if (sect != IGNORE_SECTION) {
-    ++s;
-    if (sect == GLOBAL) {
-      if (s != 1) {
-	if (g)
-	  syntax_error("only one global { ... } section allowed.\n");
-	syntax_error("global { ... } section must be first.\n");
-      }
-      ++g;
-    }
-  }
-  yy_push_state(sect);
-  yy_push_state(LBRACE);
-  fline = line;
-}
-
-static void named_section(int sect)
-{
-  section(sect);
-  yy_push_state(STRING);
-  yy_push_state(LS);
-}
-
-static void do_assign(int what)
-{
-  yy_push_state(SEMICOLON);
-  yy_push_state(what);
-  yy_push_state(ASSIGN);
-}
-
-/*
-static char* const escape(char* const str)
-{
-  static char buffer[1024];
-  char *ue = str, *e = buffer;
-
-  if (!str || !str[0]) {
-	return "\"\"";
-  }
-  *e++ = '"';
-  while(*ue) {
-    if (*ue == '"' || *ue == '\\') {
-	*e++ = '\\';
-    }
-    if (e-buffer >= 1021) { PRINTF("string too long.\n"); exit(E_syntax); }
-    *e++ = *ue++;
-  }
-  *e++ = '"';
-  *e++ = '\0';
-  return buffer;
-}
-*/
-
 static void unescape(void)
 {
   /* backslash escapes from string */
@@ -438,19 +115,3 @@
   }
   *e = '\0';
 }
-
-static void unescape_midx(void)
-{
-  char *b;
-  int n;
-
-  b = strrchr(yytext, '[');
-  if (b) {
-    n = atoi(b + 1);
-    n = snprintf(yytext, yyleng, "%d", n);
-    if (0 < n && n < yyleng)
-      return;			/* ok */
-  }
-  fprintf(stderr, "Oops, thinko in %s:%d.\n", __FILE__, __LINE__);
-  exit(E_thinko);
-}

From drbd-cvs at lists.linbit.com  Sun Jan 22 00:09:35 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Sun Jan 22 00:09:38 2006
Subject: [DRBD-cvs] svn commit by phil - r2053 - trunk/user - The makefile
	should remove all autogenerated files 
Message-ID: <20060121230935.EFD6616604@mail.linbit.com>

Author: phil
Date: 2006-01-22 00:09:35 +0100 (Sun, 22 Jan 2006)
New Revision: 2053

Modified:
   trunk/user/Makefile
Log:
The makefile should remove all autogenerated files


Modified: trunk/user/Makefile
===================================================================
--- trunk/user/Makefile	2006-01-21 23:07:32 UTC (rev 2052)
+++ trunk/user/Makefile	2006-01-21 23:09:35 UTC (rev 2053)
@@ -48,7 +48,7 @@
 	$(CC) -o $@ $^ 
 
 clean:
-	rm -f drbdadm_scanner.c
+	rm -f drbdadm_scanner.c drbdmeta_scanner.c
 	rm -f drbdsetup drbdadm drbdmeta *.o
 	rm -f *~
 

From drbd-cvs at lists.linbit.com  Mon Jan 23 10:58:19 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Mon Jan 23 10:58:21 2006
Subject: [DRBD-cvs] svn commit by phil - r2054 - trunk/user - The range
	checks on most of the options was missing. Ad
Message-ID: <20060123095819.6FF3C16981@mail.linbit.com>

Author: phil
Date: 2006-01-23 10:58:17 +0100 (Mon, 23 Jan 2006)
New Revision: 2054

Modified:
   trunk/user/drbdadm_parser.c
   trunk/user/drbdadm_parser.h
   trunk/user/drbdadm_scanner.fl
Log:
The range checks on most of the options was missing. Added that.


Modified: trunk/user/drbdadm_parser.c
===================================================================
--- trunk/user/drbdadm_parser.c	2006-01-21 23:09:35 UTC (rev 2053)
+++ trunk/user/drbdadm_parser.c	2006-01-23 09:58:17 UTC (rev 2054)
@@ -73,32 +73,14 @@
     }
 }
 
-enum range_checks
-{
-  R_MINOR_COUNT,
-  R_DIALOG_REFRESH,
-  R_DISK_SIZE,
-  R_TIMEOUT,
-  R_CONNECT_INT,
-  R_PING_INT,
-  R_MAX_BUFFERS,
-  R_MAX_EPOCH_SIZE,
-  R_SNDBUF_SIZE,
-  R_KO_COUNT,
-  R_RATE,
-  R_GROUP,
-  R_AL_EXTENTS,
-  R_PORT,
-  R_META_IDX,
-  R_WFC_TIMEOUT,
-  R_DEGR_WFC_TIMEOUT,
-};
 
 void
 range_check(const enum range_checks what, const char *name, const char *value)
 {
   switch (what)
     {
+    case R_NO_CHECK: 
+      break;
     default:
       fprintf(stderr, "%s:%d: unknown range for %s => %s\n",
 	      config_file, fline, name, value);
@@ -277,6 +259,7 @@
 {
 	char *opt_name;
 	int token;
+	enum range_checks rc;
 
 	struct d_option* options = NULL;
 
@@ -286,8 +269,10 @@
 		if( token == token_switch) {
 			options = APPEND(options,new_opt(yylval.txt,NULL));
 		} else if ( token == token_option) {
-			opt_name=yylval.txt;
+			opt_name = yylval.txt;
+			rc = yylval.rc;
 			EXP2(TK_STRING,TK_INTEGER);
+			range_check(rc,opt_name,yylval.txt);
 			options = APPEND(options,new_opt(opt_name,yylval.txt));
 		} else if ( token == '}' ) {
 			return options;

Modified: trunk/user/drbdadm_parser.h
===================================================================
--- trunk/user/drbdadm_parser.h	2006-01-21 23:09:35 UTC (rev 2053)
+++ trunk/user/drbdadm_parser.h	2006-01-23 09:58:17 UTC (rev 2054)
@@ -22,55 +22,76 @@
 
  */
 
-typedef union YYSTYPE {
-  char* txt;
-  struct d_option* d_option;
-  struct d_resource* d_resource;
+
+enum range_checks
+{
+	R_NO_CHECK,
+	R_MINOR_COUNT,
+	R_DIALOG_REFRESH,
+	R_DISK_SIZE,
+	R_TIMEOUT,
+	R_CONNECT_INT,
+	R_PING_INT,
+	R_MAX_BUFFERS,
+	R_MAX_EPOCH_SIZE,
+	R_SNDBUF_SIZE,
+	R_KO_COUNT,
+	R_RATE,
+	R_GROUP,
+	R_AL_EXTENTS,
+	R_PORT,
+	R_META_IDX,
+	R_WFC_TIMEOUT,
+	R_DEGR_WFC_TIMEOUT,
+};
+
+enum yytokentype {
+	TK_GLOBAL = 258,
+	TK_RESOURCE,
+	TK_ON,
+	TK_NET,
+	TK_DISK,
+	TK_SKIP,
+	TK_SYNCER,
+	TK_STARTUP,
+	TK_DISABLE_IO_HINTS,
+	TK_DISABLE_IP_VERIFICATION,
+	TK_DIALOG_REFRESH,
+	TK_PROTOCOL,
+	TK_HANDLER, // 270
+	TK_COMMON,
+	TK_ADDRESS,
+	TK_DEVICE,
+	TK_META_DISK,
+	TK_FLEX_META_DISK,
+	TK_MINOR_COUNT,
+
+	TK_IPADDR,
+	TK_INTEGER,
+	TK_STRING,
+	TK_ELSE, // 280
+
+	TK_DISK_SWITCH,
+	TK_DISK_OPTION,
+	TK_NET_SWITCH,
+	TK_NET_OPTION,
+	TK_SYNCER_SWITCH,
+	TK_SYNCER_OPTION,
+	TK_STARTUP_SWITCH,
+	TK_STARTUP_OPTION,
+	TK_HANDLER_OPTION
+};
+
+typedef struct YYSTYPE {
+	char* txt;
+	enum range_checks rc;
 } YYSTYPE;
 
 #define yystype YYSTYPE /* obsolescent; will be withdrawn */
 #define YYSTYPE_IS_DECLARED 1
 #define YYSTYPE_IS_TRIVIAL 1
 
-extern YYSTYPE yylval;
+extern yystype yylval;
 
-
-enum yytokentype {
-	 TK_GLOBAL = 258,
-	 TK_RESOURCE,
-	 TK_ON,
-	 TK_NET,
-	 TK_DISK,
-	 TK_SKIP,
-	 TK_SYNCER,
-	 TK_STARTUP,
-	 TK_DISABLE_IO_HINTS,
-	 TK_DISABLE_IP_VERIFICATION,
-	 TK_DIALOG_REFRESH,
-	 TK_PROTOCOL,
-	 TK_HANDLER, // 270
-	 TK_COMMON,
-	 TK_ADDRESS,
-	 TK_DEVICE,
-	 TK_META_DISK,
-	 TK_FLEX_META_DISK,
-	 TK_MINOR_COUNT,
-
-	 TK_IPADDR,
-	 TK_INTEGER,
-	 TK_STRING,
-	 TK_ELSE, // 280
-
-	 TK_DISK_SWITCH,
-	 TK_DISK_OPTION,
-	 TK_NET_SWITCH,
-	 TK_NET_OPTION,
-	 TK_SYNCER_SWITCH,
-	 TK_SYNCER_OPTION,
-	 TK_STARTUP_SWITCH,
-	 TK_STARTUP_OPTION,
-	 TK_HANDLER_OPTION
-};
-
 /* avoid compiler warnings about implicit declaration */
 int yylex(void);

Modified: trunk/user/drbdadm_scanner.fl
===================================================================
--- trunk/user/drbdadm_scanner.fl	2006-01-21 23:09:35 UTC (rev 2053)
+++ trunk/user/drbdadm_scanner.fl	2006-01-23 09:58:17 UTC (rev 2054)
@@ -14,7 +14,8 @@
 #define DP
 #endif
 
-#define CP yylval.txt = strdup(yytext)
+#define CP yylval.txt = strdup(yytext); yylval.rc = R_NO_CHECK
+#define RC(N) yylval.rc = R_ ## N 
 
 #define YY_NO_UNPUT 1
 static void yyunput (int c, register char * yy_bp ) __attribute((unused));
@@ -61,24 +62,25 @@
 resource		{ DP; return TK_RESOURCE;		}
 meta-disk		{ DP; return TK_META_DISK;		}
 flexible-meta-disk	{ DP; return TK_FLEX_META_DISK;		}
-size			{ DP; CP; return TK_DISK_OPTION;	}
+size			{ DP; CP; RC(DISK_SIZE); return TK_DISK_OPTION;	}
 on-io-error		{ DP; CP; return TK_DISK_OPTION;	}
 split-brain-fix		{ DP; CP; return TK_DISK_SWITCH;	}
-timeout			{ DP; CP; return TK_NET_OPTION;		}
-ping-int		{ DP; CP; return TK_NET_OPTION;		}
-max-buffers		{ DP; CP; return TK_NET_OPTION;		}
-sndbuf-size		{ DP; CP; return TK_NET_OPTION;		}
-connect-int		{ DP; CP; return TK_NET_OPTION;		}
-max-epoch-size		{ DP; CP; return TK_NET_OPTION;		}
+timeout			{ DP; CP; RC(TIMEOUT); return TK_NET_OPTION;	}
+ko-count		{ DP; CP; RC(KO_COUNT); return TK_NET_OPTION;	}
+ping-int		{ DP; CP; RC(PING_INT); return TK_NET_OPTION;	}
+max-buffers		{ DP; CP; RC(MAX_BUFFERS); return TK_NET_OPTION;}
+sndbuf-size		{ DP; CP; RC(SNDBUF_SIZE); return TK_NET_OPTION;}
+connect-int		{ DP; CP; RC(CONNECT_INT); return TK_NET_OPTION;}
+max-epoch-size		{ DP; CP; RC(MAX_EPOCH_SIZE); return TK_NET_OPTION;}
 after-sb-[012]pri	{ DP; CP; return TK_NET_OPTION;		}
 allow-two-primaries	{ DP; CP; return TK_NET_SWITCH;		}
-rate			{ DP; CP; return TK_SYNCER_OPTION;	}
+rate			{ DP; CP; RC(RATE); return TK_SYNCER_OPTION;	}
 after			{ DP; CP; return TK_SYNCER_OPTION;	}
 use-csums		{ DP; CP; return TK_SYNCER_SWITCH;	}
 skip-sync		{ DP; CP; return TK_SYNCER_SWITCH;	}
-al-extents		{ DP; CP; return TK_SYNCER_OPTION; 	}
-wfc-timeout		{ DP; CP; return TK_STARTUP_OPTION;	}
-degr-wfc-timeout	{ DP; CP; return TK_STARTUP_OPTION;	}
+al-extents		{ DP; CP; RC(AL_EXTENTS); return TK_SYNCER_OPTION;}
+wfc-timeout		{ DP; CP; RC(WFC_TIMEOUT); return TK_STARTUP_OPTION;}
+degr-wfc-timeout	{ DP; CP; RC(DEGR_WFC_TIMEOUT); return TK_STARTUP_OPTION;}
 pri-on-incon-degr	{ DP; CP; return TK_HANDLER_OPTION;	}
 pri-lost-after-sb	{ DP; CP; return TK_HANDLER_OPTION;	}
 outdate-peer		{ DP; CP; return TK_HANDLER_OPTION;	}

From drbd-cvs at lists.linbit.com  Wed Jan 25 23:20:33 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Wed Jan 25 23:20:35 2006
Subject: [DRBD-cvs] svn commit by phil - r2055 - branches/drbd-0.7/drbd -
	Make it compile on 2.6.16-rc1 
Message-ID: <20060125222033.DC9EC16A09@mail.linbit.com>

Author: phil
Date: 2006-01-25 23:20:32 +0100 (Wed, 25 Jan 2006)
New Revision: 2055

Modified:
   branches/drbd-0.7/drbd/drbd_receiver.c
Log:
Make it compile on 2.6.16-rc1


Modified: branches/drbd-0.7/drbd/drbd_receiver.c
===================================================================
--- branches/drbd-0.7/drbd/drbd_receiver.c	2006-01-23 09:58:17 UTC (rev 2054)
+++ branches/drbd-0.7/drbd/drbd_receiver.c	2006-01-25 22:20:32 UTC (rev 2055)
@@ -38,6 +38,7 @@
 #include <linux/version.h>
 #include <linux/fs.h>
 #include <linux/file.h>
+#include <linux/in.h>
 #include <linux/mm.h>
 #include <linux/drbd_config.h>
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) || defined(HAVE_MM_INLINE_H)

From drbd-cvs at lists.linbit.com  Sun Jan 29 12:40:34 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Sun Jan 29 12:40:48 2006
Subject: [DRBD-cvs] svn commit by phil - r2056 - branches/drbd-0.7/drbd -
	Neil Brown created a patch that serializes recursive ca
Message-ID: <20060129114035.756E216A09@mail.linbit.com>

Author: phil
Date: 2006-01-29 12:40:33 +0100 (Sun, 29 Jan 2006)
New Revision: 2056

Modified:
   branches/drbd-0.7/drbd/drbd_actlog.c
Log:
Neil Brown created a patch that serializes recursive calls
to generic_make_request(). FC4 included that patch in one
of their kernel updates. Since DRBD made a call to 
generi_make_request() from it's make_request function,
it deadlocked on that latest FC4 kernel.

This patch solves the issue by offloding the writing of 
AL transaction to our worker thread.


Modified: branches/drbd-0.7/drbd/drbd_actlog.c
===================================================================
--- branches/drbd-0.7/drbd/drbd_actlog.c	2006-01-25 22:20:32 UTC (rev 2055)
+++ branches/drbd-0.7/drbd/drbd_actlog.c	2006-01-29 11:40:33 UTC (rev 2056)
@@ -191,8 +191,15 @@
 	unsigned int enr;
 };
 
-STATIC void drbd_al_write_transaction(struct Drbd_Conf *,struct lc_element *,
-				      unsigned int );
+struct update_al_work {
+	struct drbd_work w;
+	struct lc_element * al_ext;
+	struct completion event;
+	unsigned int enr;
+};
+
+STATIC int w_al_write_transaction(struct Drbd_Conf *, struct drbd_work *, int);
+
 static inline
 struct lc_element* _al_get(struct Drbd_Conf *mdev, unsigned int enr)
 {
@@ -229,6 +236,7 @@
 {
 	unsigned int enr = (sector >> (AL_EXTENT_SIZE_B-9));
 	struct lc_element *al_ext;
+	struct update_al_work al_work;
 
 	D_ASSERT(atomic_read(&mdev->local_cnt)>0);
 	wait_event(mdev->al_wait, (al_ext = _al_get(mdev,enr)) );
@@ -242,7 +250,19 @@
 		if(mdev->cstate < Connected && evicted != LC_FREE ) {
 			drbd_bm_write_sect(mdev, evicted/AL_EXT_PER_BM_SECT );
 		}
-		drbd_al_write_transaction(mdev,al_ext,enr);
+
+		/* drbd_al_write_transaction(mdev,al_ext,enr);
+		   generic_make_request() are serialized on the 
+		   current->bio_tail list now. Therefore we have
+		   to deligate writing something to AL to the
+		   worker thread. */
+		init_completion(&al_work.event);
+		al_work.al_ext = al_ext;
+		al_work.enr = enr;
+		al_work.w.cb = w_al_write_transaction;
+		drbd_queue_work_front(mdev,&mdev->data.work,&al_work.w);
+		wait_for_completion(&al_work.event);
+		
 		mdev->al_writ_cnt++;
 
 		/*
@@ -279,9 +299,8 @@
 	spin_unlock_irqrestore(&mdev->al_lock,flags);
 }
 
-STATIC void
-drbd_al_write_transaction(struct Drbd_Conf *mdev,struct lc_element *updated,
-			  unsigned int new_enr)
+STATIC int
+w_al_write_transaction(struct Drbd_Conf *mdev, struct drbd_work *w, int unused)
 {
 	int i,n,mx;
 	unsigned int extent_nr;
@@ -289,6 +308,9 @@
 	sector_t sector;
 	u32 xor_sum=0;
 
+	struct lc_element *updated = ((struct update_al_work*)w)->al_ext;
+	unsigned int new_enr = ((struct update_al_work*)w)->enr;
+
 	down(&mdev->md_io_mutex); // protects md_io_buffer, al_tr_cycle, ...
 	buffer = (struct al_transaction*)page_address(mdev->md_io_page);
 
@@ -340,6 +362,10 @@
 	mdev->al_tr_number++;
 
 	up(&mdev->md_io_mutex);
+
+	complete(&((struct update_al_work*)w)->event);
+
+	return 1;
 }
 
 STATIC int drbd_al_read_tr(struct Drbd_Conf *mdev,

From drbd-cvs at lists.linbit.com  Tue Jan 31 15:54:36 2006
From: drbd-cvs at lists.linbit.com (drbd-cvs@lists.linbit.com)
Date: Tue Jan 31 15:54:37 2006
Subject: [DRBD-cvs] svn commit by phil - r2057 - branches/drbd-0.7/user -
	The old code could (unter oscure conditions) lead to
Message-ID: <20060131145436.ACAFB15F83@mail.linbit.com>

th
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Author: phil
Date: 2006-01-31 15:54:35 +0100 (Tue, 31 Jan 2006)
New Revision: 2057

Modified:
   branches/drbd-0.7/user/drbdadm_main.c
Log:
The old code could (unter oscure conditions) lead to
the assure_module_loaded to fail in the init-script.



Modified: branches/drbd-0.7/user/drbdadm_main.c
===================================================================
--- branches/drbd-0.7/user/drbdadm_main.c	2006-01-29 11:40:33 UTC (rev 2056)
+++ branches/drbd-0.7/user/drbdadm_main.c	2006-01-31 14:54:35 UTC (rev 2057)
@@ -296,8 +296,11 @@
 static int sh_resources(struct d_resource* ignored,char* unused)
 {
   struct d_resource *res,*t;
+  int first=1;
+
   for_each_resource(res,t,config) {
-    printf(res==config?"%s":" %s",esc(res->name));
+    printf(first?"%s":" %s",esc(res->name));
+    first=0;
   }
   printf("\n");
 

