From www-data at garcon.linbit.com  Mon Apr  4 13:04:37 2005
From: www-data at garcon.linbit.com (www-data)
Date: Mon Apr  4 13:04:38 2005
Subject: [DRBD-cvs] r1775 - trunk
Message-ID: <20050404110437.4537D1454A@mail.linbit.com>

Author: phil
Date: 2005-04-04 13:04:36 +0200 (Mon, 04 Apr 2005)
New Revision: 1775

Modified:
   trunk/ROADMAP
Log:
Some thoughts on the new generation-UUID stuff...


Modified: trunk/ROADMAP
===================================================================
--- trunk/ROADMAP	2005-04-01 13:23:41 UTC (rev 1774)
+++ trunk/ROADMAP	2005-04-04 11:04:36 UTC (rev 1775)
@@ -381,15 +381,15 @@
   for more then 4k e.g. 64k
   50% DONE we handle big BIOs now, a bitmap bit is still 4k.
 
-[ Item 16 is still unfinished, as described here, the algorithm has
-  some loose ends... ]
-16 Displace the current generation-counters with a generation-UUID concept.
+16 Displace the current generation-counters with a data-generation-UUID 
+   concept.
   The current generation counters have various weaknesses:
    * In a split braine'd cluster the appliance of the same events
      to both cluster nodes could lead to equal generation-counters
      on both nodes, while the data is not in sync for sure.
    * They are completely unsuitable if a 3rd node is used for 
      e.g. weekly snapshots.
+   * Lots of other shortcommings.
 
   We associate each data generation with an unique UUID (=64 bit random
   number). A new data generation is created if a node becomes primary
@@ -399,32 +399,68 @@
   In the meta-data we store a few generations-UUIDs: 
    * current
    * bitmap
-   * history[4]
+   * history[2]
 
   In addition there is an enum describing the authorisation of the
-  current gen-uuid: Human, Timout, Connected, Degraded
+  current gen-UUID: Human, Timout, Connected, Degraded
   As well as the currently known flags: 
-     Consistent, WasUpToDate, LastState, ConnectedInd, WantFullSync
+   Consistent, WasUpToDate, LastState, ConnectedInd, WantFullSync
 
   The difference here is that the former flags are determined
-  when the gen-uuid is created, while the latter are modified
-  as the state changes.
+  when the current-UUID is created, while the latter are modified
+  as the state changes. When drbdmeta initializes the meta-data
+  block it sets the current-UUID to JustCreated (a constant 64 bit number).
 
   When the cluster is in Connected state, then the bitmpat gen-uuid
   is set to 0 (Since the Bitmap is empty). When we create a new current
-  gen-uuid while we are disconencted the (old) current gets backuped
-  to the bitmap gen-uuid. (This allowes us to identify the base of
+  gen-UUID while we are disconencted the (old) current gets backuped
+  to the bitmap gen-UUID. (This allowes us to identify the base of
   of the bitmap later)
 
-  Algorithm on connect:
-   If the current gen-uuids are equal -> No sync.
-   else -> Need sync.
+  ALGORITHMS
 
-   The node which has bitmap gen-uuid == peer's current gen-uuid is
-   sync source.
+  Upon Connect:
+      self   peer   action
+  1.  JustC   JustC No Sync
+  2.  JustC  !JustC I am SyncTarget setting BM
+  3. !JustC   JustC I am SyncSource setting BM
+  4.   C   =   C    No Sync
+  5.   C   =   B    I am SyncTarget using BM
+  6.   C   = H1|H2  I am SyncTarget setting BM
+  7.   B   =   C    I am SyncSource using BM
+  8. H1|H2 =   C    I am SyncSource setting BM
+  9.   B   =   B    [ B != 0 ] SplitBrain, try auto recover strategies 
+  10 H1|H2 = H1|H2  SplitBrain, disconnect.
+  11.               Warn about unrelated Data, disconnect.
 
-   The node with the higher value in the authorisation enum is sync source.
+  Upon Disconnect:
+   Primary:
+      Copy the current-UUID over to the bitmap-UUID, create a new 
+      current-UUID.
+   Secondary:
+      Nothing to do.
 
+  Upon becomming Primary:
+   If new auth-enum would be different from current auth-enum, create
+   a new one. 
+
+  Upon start of resync:
+   Clear Consistent on the SyncTarget. The SyncTarget sets its
+   bitmap-UUID to the peer's current-UUID.
+
+  Upon finish of resync:
+   Set the bitmap-UUID to 0. The SyncTarget addopts the current-UUID
+   of the SyncSource. Set Consistent.
+   
+  * Note for the auto recover strategies after split brain (see
+    item 5) it is probabely a good idea to embedd the node's role
+    (i.e. Primary or Secondary) into the UUIDs.
+
+  Open Issues:
+   - When gets something moved to the History
+   - When to create a new UUID
+   - When (not) to overwrite the bitmap-UUID
+
 17 Something like
 
    drbdx: WARNING disk sizes more than 10% different

From www-data at garcon.linbit.com  Mon Apr  4 14:05:09 2005
From: www-data at garcon.linbit.com (www-data)
Date: Mon Apr  4 14:05:10 2005
Subject: [DRBD-cvs] r1776 - trunk
Message-ID: <20050404120509.D35AC1454A@mail.linbit.com>

Author: phil
Date: 2005-04-04 14:05:08 +0200 (Mon, 04 Apr 2005)
New Revision: 1776

Modified:
   trunk/ROADMAP
Log:
More work on intellectual work on item 16 (= new UUID concept).


Modified: trunk/ROADMAP
===================================================================
--- trunk/ROADMAP	2005-04-04 11:04:36 UTC (rev 1775)
+++ trunk/ROADMAP	2005-04-04 12:05:08 UTC (rev 1776)
@@ -43,12 +43,12 @@
    discard-NODENAME 
                   Auto sync to the named node 
   
-  pri-sees-sec-with-higher-gc =
+  pri-sees-sec-with-newer-data =
    disconnect         (current behaviour)
    discard-secondary  Auto sync from is the current primary
    suspend_io          The current primary freezes IO.
 
-  pri-sees-sec-with-higher-gc-cmd "command";
+  pri-sees-sec-with-newer-data-cmd "command";
                       In the same event this command will be executed.
   
   
@@ -64,6 +64,7 @@
        use the GC to tag the bitmap it is better the current way ]
   4) The execution of the pri-sees-sec-with-higher-gc-cmd should
      be implemented like the kernel can execute modprobe...
+  5) To implement this we have the "primary" bit in the data-gen-UUIDs.
   0% DONE
 
 6 It is possible that a secondary node crashes a primary by 
@@ -392,75 +393,81 @@
    * Lots of other shortcommings.
 
   We associate each data generation with an unique UUID (=64 bit random
-  number). A new data generation is created if a node becomes primary
-  and the new auth-enum (see below) is different from the current
-  auth enum.
+  number). A new data generation is created if a primary node is 
+  disconnected from its secondary and when a degraded secondary 
+  becomes primary for the first time.
 
   In the meta-data we store a few generations-UUIDs: 
    * current
    * bitmap
    * history[2]
 
-  In addition there is an enum describing the authorisation of the
-  current gen-UUID: Human, Timout, Connected, Degraded
   As well as the currently known flags: 
    Consistent, WasUpToDate, LastState, ConnectedInd, WantFullSync
 
   The difference here is that the former flags are determined
   when the current-UUID is created, while the latter are modified
   as the state changes. When drbdmeta initializes the meta-data
-  block it sets the current-UUID to JustCreated (a constant 64 bit number).
+  block it sets the current-UUID to JustCreated (a 64 bit constant ).
 
-  When the cluster is in Connected state, then the bitmpat gen-uuid
+  When the cluster is in Connected state, then the bitmpat gen-UUID
   is set to 0 (Since the Bitmap is empty). When we create a new current
   gen-UUID while we are disconencted the (old) current gets backuped
   to the bitmap gen-UUID. (This allowes us to identify the base of
   of the bitmap later)
 
+  Special UUID values:
+  JustCreated [JC] ___  4
+
   ALGORITHMS
 
   Upon Connect:
       self   peer   action
-  1.  JustC   JustC No Sync
-  2.  JustC  !JustC I am SyncTarget setting BM
-  3. !JustC   JustC I am SyncSource setting BM
+  1.  C=JC   C=JC   No Sync
+  2.  C=JC   C!=JC  I am SyncTarget setting BM
+  3. C!=JC   C=JC   I am SyncSource setting BM
   4.   C   =   C    No Sync
   5.   C   =   B    I am SyncTarget using BM
   6.   C   = H1|H2  I am SyncTarget setting BM
   7.   B   =   C    I am SyncSource using BM
   8. H1|H2 =   C    I am SyncSource setting BM
-  9.   B   =   B    [ B != 0 ] SplitBrain, try auto recover strategies 
+  9.   B   =   B    [ and B != 0 ] SplitBrain, try auto recover strategies.
   10 H1|H2 = H1|H2  SplitBrain, disconnect.
   11.               Warn about unrelated Data, disconnect.
 
   Upon Disconnect:
    Primary:
-      Copy the current-UUID over to the bitmap-UUID, create a new 
+      Copy the current-UUID over to the bitmap-UUID, create a new
       current-UUID.
    Secondary:
       Nothing to do.
 
   Upon becomming Primary:
-   If new auth-enum would be different from current auth-enum, create
-   a new one. 
+   In case we are disconnected and the bitmap-UUID is emptry, copy the
+   current-UUID over to the bitmap-UUID and create a new current-UUID.
+   Special-case: primary with --do-what-I-say, clearing the inconsistent
+                 flag causes a new UUID to be generated.
 
   Upon start of resync:
-   Clear Consistent on the SyncTarget. The SyncTarget sets its
+   Clear the consistent-flag on the SyncTarget. The SyncTarget sets its
    bitmap-UUID to the peer's current-UUID.
 
   Upon finish of resync:
    Set the bitmap-UUID to 0. The SyncTarget addopts the current-UUID
-   of the SyncSource. Set Consistent.
-   
-  * Note for the auto recover strategies after split brain (see
-    item 5) it is probabely a good idea to embedd the node's role
-    (i.e. Primary or Secondary) into the UUIDs.
+   of the SyncSource, and sets its consistent-flag.
 
-  Open Issues:
-   - When gets something moved to the History
-   - When to create a new UUID
-   - When (not) to overwrite the bitmap-UUID
+  When the bitmap-UUID gets cleared, move the previous value to H1.
+  In case H1 was already set copy its previous value to H2. Etc..
 
+  For the auto recover strategies after split brain (see item 5) 
+  it is neccessary to embedd the node's role into the UUIDs.
+  This is masked out of course when the UUIDs are compared.
+
+  * Note1: Discontinue the --human and --timout options when 
+           becoming primary.
+           NB: If they are needed, I think they can be implemented
+               as special UUID values.
+
 17 Something like
 
    drbdx: WARNING disk sizes more than 10% different

From www-data at garcon.linbit.com  Mon Apr  4 17:19:43 2005
From: www-data at garcon.linbit.com (www-data)
Date: Mon Apr  4 17:19:44 2005
Subject: [DRBD-cvs] r1777 - in trunk: . drbd drbd/linux
Message-ID: <20050404151943.702DD14D2F@mail.linbit.com>

Author: phil
Date: 2005-04-04 17:19:41 +0200 (Mon, 04 Apr 2005)
New Revision: 1777

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_sizeof_sanity_check.c
   trunk/drbd/drbd_worker.c
   trunk/drbd/linux/drbd.h
   trunk/drbd/linux/drbd_config.h
Log:
Implemented the kernel part of item 16 (generation UUIDs)


Modified: trunk/ROADMAP
===================================================================
--- trunk/ROADMAP	2005-04-04 12:05:08 UTC (rev 1776)
+++ trunk/ROADMAP	2005-04-04 15:19:41 UTC (rev 1777)
@@ -468,6 +468,10 @@
            NB: If they are needed, I think they can be implemented
                as special UUID values.
 
+  50% DONE. Kernel part is implemented, not tested. But testing
+            will only be possible after drbdmeta was updated. 
+            Drbdmeta still has no clue of gen-UUIDs, not drbdsetup.
+
 17 Something like
 
    drbdx: WARNING disk sizes more than 10% different

Modified: trunk/drbd/drbd_fs.c
===================================================================
--- trunk/drbd/drbd_fs.c	2005-04-04 12:05:08 UTC (rev 1776)
+++ trunk/drbd/drbd_fs.c	2005-04-04 15:19:41 UTC (rev 1777)
@@ -703,7 +703,7 @@
 		nps = Outdated;
 		break;
 	case 5: /* peer was down, increase GENCNT ... */
-		drbd_md_inc(mdev,ConnectedCnt);
+		drbd_uuid_new_current(mdev);
 		nps = Outdated;
 		break;
 	case 6: /* Peer is primary, voluntarily outdate myself */
@@ -712,7 +712,7 @@
 		break;
 	default:
 		/* The script is broken ... */
-		drbd_md_inc(mdev,ConnectedCnt);
+		drbd_uuid_new_current(mdev);
 		nps = DUnknown;
 		ERR("outdate-peer helper returned %d (%d)\n",(r>>8)&0xff,r);
 	}
@@ -824,14 +824,9 @@
 			clear_bit(ON_PRI_INC_TIMEOUTEX,&mdev->flags);
 		}
 
-		if(newstate & Human) {
-			drbd_md_inc(mdev,HumanCnt);
-		} else if(newstate & TimeoutExpired ) {
-			drbd_md_inc(mdev,TimeoutCnt);
-		} else {
-			drbd_md_inc(mdev,
-				    mdev->state.s.conn >= Connected ?
-				    ConnectedCnt : ArbitraryCnt);
+		if ( (mdev->state.s.conn < WFReportParams &&
+		      mdev->uuid[Bitmap] == 0) || forced ) {
+			drbd_uuid_new_current(mdev);
 		}
 	}
 
@@ -982,10 +977,10 @@
 	return 0;
 }
 
-STATIC int drbd_ioctl_get_gen_cnt(struct Drbd_Conf *mdev, 
-				  struct ioctl_get_gen_cnt* arg)
+STATIC int drbd_ioctl_get_uuids(struct Drbd_Conf *mdev, 
+				struct ioctl_get_uuids* arg)
 {
-	struct ioctl_get_gen_cnt cn;
+	struct ioctl_get_uuids cn;
 	int i;
 
 	if( mdev->state.s.disk <= Failed ) {
@@ -994,10 +989,9 @@
 
 	memset(&cn,0,sizeof(cn));
 
-	for(i=Flags;i<=ArbitraryCnt;i++)
-		cn.gen_cnt[i]=mdev->gen_cnt[i];
-	cn.uuid = mdev->uuid;
-	cn.peer_uuid = mdev->peer_uuid;
+	for (i = Current; i < UUID_SIZE; i++) {
+		cn.uuid[i]=mdev->uuid[i];
+	}
 	cn.bits_set = drbd_bm_total_weight(mdev);
 	cn.current_size = drbd_get_capacity(mdev->this_bdev);
 
@@ -1307,8 +1301,8 @@
 		err = drbd_outdate_ioctl(mdev,(int *) arg);
 		break;
 
-	case DRBD_IOCTL_GET_GEN_CNT:
-		err=drbd_ioctl_get_gen_cnt(mdev,(void *)arg);
+	case DRBD_IOCTL_GET_UUIDS:
+		err=drbd_ioctl_get_uuids(mdev,(void *)arg);
 		break;
 
 	default:

Modified: trunk/drbd/drbd_int.h
===================================================================
--- trunk/drbd/drbd_int.h	2005-04-04 12:05:08 UTC (rev 1776)
+++ trunk/drbd/drbd_int.h	2005-04-04 15:19:41 UTC (rev 1777)
@@ -293,7 +293,7 @@
 	RSDataRequest, // Used to ask for a data block
 	SyncParam,
 	ReportProtocol,
-	ReportGenCnt,
+	ReportUUIDs,
 	ReportSizes,
 	ReportState,
 	AuthChallenge,
@@ -334,7 +334,7 @@
 		[RSDataRequest]    = "RSDataRequest",
 		[SyncParam]        = "SyncParam",
 		[ReportProtocol]   = "ReportProtocol",
-		[ReportGenCnt]     = "ReportGenCnt",
+		[ReportUUIDs]     = "ReportUUIDs",
 		[ReportSizes]      = "ReportSizes",
 		[ReportState]      = "ReportState",
 		[AuthChallenge]    = "AuthChallenge",
@@ -461,13 +461,12 @@
 
 typedef struct {
 	Drbd_Header head;
-	u64         uuid;
 	u32         protocol;
 } __attribute((packed)) Drbd_Protocol_Packet;
 
 typedef struct {
 	Drbd_Header head;
-	u32         gen_cnt[GEN_CNT_SIZE];
+	u64         uuid[UUID_SIZE];
 } __attribute((packed)) Drbd_GenCnt_Packet;
 
 typedef struct {
@@ -636,7 +635,6 @@
 	MD_IO_ALLOWED,		// EXPLAIN
 	MD_DIRTY,		// current gen counts and flags not yet on disk
 	SYNC_STARTED,		// Needed to agree on the exact point in time..
-	UUID_CHANGED,           // UUID changed. Need fullsync.
 	UNIQUE,                 // Set on one node, cleared on the peer!
 	SPLIT_BRAIN_FIX,        // Set if split-brain-fix is configured
 };
@@ -706,8 +704,6 @@
 	/* volatile */ drbd_state_t state;
 	wait_queue_head_t cstate_wait; // TODO Rename into "misc_wait". 
 	sector_t la_size;     // last agreed disk size in sectors.
-	u64 uuid;
-	u64 peer_uuid;
 	unsigned int send_cnt;
 	unsigned int recv_cnt;
 	unsigned int read_cnt;
@@ -742,8 +738,9 @@
 	struct lru_cache* resync; // Used to track operations of resync...
 	atomic_t resync_locked;   // Number of locked elements in resync LRU
 	int open_cnt;
-	u32 gen_cnt[GEN_CNT_SIZE];
-	u32 *p_gen_cnt;
+	unsigned int md_flags;
+	u64 uuid[UUID_SIZE];
+	u64 *p_uuid;
 	atomic_t epoch_size;
 	spinlock_t ee_lock;
 	struct list_head active_ee; // IO in progress
@@ -836,10 +833,10 @@
 // drbd_meta-data.c (still in drbd_main.c)
 extern void drbd_md_write(drbd_dev *mdev);
 extern int drbd_md_read(drbd_dev *mdev);
-extern int drbd_md_compare(drbd_dev *mdev);
-extern void drbd_dump_md(drbd_dev *, int );
 // maybe define them below as inline?
-extern void drbd_md_inc(drbd_dev *mdev, enum MetaDataIndex order);
+extern void drbd_uuid_set_current(drbd_dev *mdev, u64 val);
+extern void drbd_uuid_new_current(drbd_dev *mdev);
+extern void drbd_uuid_reset_bm(drbd_dev *mdev);
 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);

Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c	2005-04-04 12:05:08 UTC (rev 1776)
+++ trunk/drbd/drbd_main.c	2005-04-04 15:19:41 UTC (rev 1777)
@@ -50,6 +50,7 @@
 #include <linux/mm_inline.h>
 #include <linux/slab.h>
 #include <linux/devfs_fs_kernel.h>
+#include <linux/random.h>
 
 #define __KERNEL_SYSCALLS__
 #include <linux/unistd.h>
@@ -542,7 +543,6 @@
 int _drbd_set_state(drbd_dev* mdev, drbd_state_t ns,enum chg_state_flags flags)
 {
 	drbd_state_t os;
-	char pb[160], *pbp;
 	int rv=1,warn_sync_abort=0;
 
 	os = mdev->state;
@@ -667,10 +667,6 @@
 		mod_timer(&mdev->resync_timer,jiffies);
 	}
 
-	if ( os.s.peer == Secondary    && ns.s.peer == Primary ) {
-		drbd_md_inc(mdev,ConnectedCnt);
-	}
-
 	if ( os.s.disk == Diskless && os.s.peer == StandAlone &&
 	     (ns.s.disk >= Inconsistent || ns.s.peer > StandAlone) ) {
 		__module_get(THIS_MODULE);
@@ -681,6 +677,12 @@
 		drbd_panic("No access to good data anymore.\n");
 	}
 
+	if ( os.s.conn != Connected && ns.s.conn == Connected && 
+	     mdev->p_uuid ) {
+		kfree(mdev->p_uuid);
+		mdev->p_uuid = 0;
+	}
+
 	return rv;
 }
 
@@ -948,7 +950,6 @@
 {
 	Drbd_Protocol_Packet p;
 
-	p.uuid   = cpu_to_be64(mdev->uuid);
 	p.protocol = cpu_to_be32(mdev->conf.wire_protocol);
 
 	return drbd_send_cmd(mdev,mdev->data.socket,ReportProtocol,
@@ -960,11 +961,11 @@
 	Drbd_GenCnt_Packet p;
 	int i;
 
-	for (i = Flags; i < GEN_CNT_SIZE; i++) {
-		p.gen_cnt[i] = cpu_to_be32(mdev->gen_cnt[i]);
+	for (i = Current; i < UUID_SIZE; i++) {
+		p.uuid[i] = cpu_to_be64(mdev->uuid[i]);
 	}
 
-	return drbd_send_cmd(mdev,mdev->data.socket,ReportGenCnt,
+	return drbd_send_cmd(mdev,mdev->data.socket,ReportUUIDs,
 			     (Drbd_Header*)&p,sizeof(p));
 }
 
@@ -1722,7 +1723,7 @@
 	ZAP(mdev->sync_conf);
 	// ZAP(mdev->data); Not yet!
 	// ZAP(mdev->meta); Not yet!
-	ZAP(mdev->gen_cnt);
+	ZAP(mdev->uuid);
 #undef ZAP
 	mdev->al_writ_cnt  =
 	mdev->bm_writ_cnt  =
@@ -2212,9 +2213,8 @@
 
 struct meta_data_on_disk {
 	u64 la_size;           // last agreed size.
-	u64 uuid;              // universally unique identifier
-	u64 peer_uuid;         // universally unique identifier
-	u32 gc[GEN_CNT_SIZE];  // generation counter
+	u64 uuid[UUID_SIZE];   // UUIDs.
+	u32 flags;             // MDF
 	u32 magic;
 	u32 md_size;
 	u32 al_offset;         // offset to this block
@@ -2240,19 +2240,17 @@
 	buffer = (struct meta_data_on_disk *)page_address(mdev->md_io_page);
 	memset(buffer,0,512);
 
-	flags = mdev->gen_cnt[Flags] & ~(MDF_Consistent|MDF_PrimaryInd|
-					 MDF_ConnectedInd|MDF_WasUpToDate);
+	flags = mdev->md_flags & ~(MDF_Consistent|MDF_PrimaryInd|
+				   MDF_ConnectedInd|MDF_WasUpToDate);
 	if (mdev->state.s.role == Primary)        flags |= MDF_PrimaryInd;
 	if (mdev->state.s.conn >= WFReportParams) flags |= MDF_ConnectedInd;
 	if (mdev->state.s.disk >  Inconsistent)   flags |= MDF_Consistent;
 	if (mdev->state.s.disk >  Outdated)       flags |= MDF_WasUpToDate;
-	mdev->gen_cnt[Flags] = flags;
+	mdev->md_flags = flags;
 
-	for (i = Flags; i < GEN_CNT_SIZE; i++)
-		buffer->gc[i]=cpu_to_be32(mdev->gen_cnt[i]);
+	for (i = Current; i < UUID_SIZE; i++)
+		buffer->uuid[i]=cpu_to_be64(mdev->uuid[i]);
 	buffer->la_size=cpu_to_be64(drbd_get_capacity(mdev->this_bdev));
-	buffer->uuid=cpu_to_be64(mdev->uuid);
-	buffer->peer_uuid=cpu_to_be64(mdev->peer_uuid);
 
 	buffer->magic=cpu_to_be32(DRBD_MD_MAGIC);
 
@@ -2328,11 +2326,9 @@
 		goto err;
 	}
 
-	for(i=Flags;i<=ArbitraryCnt;i++)
-		mdev->gen_cnt[i]=be32_to_cpu(buffer->gc[i]);
+	for (i = Current; i < UUID_SIZE; i++)
+		mdev->uuid[i]=be64_to_cpu(buffer->uuid[i]);
 	mdev->la_size = be64_to_cpu(buffer->la_size);
-	mdev->uuid = be64_to_cpu(buffer->uuid);
-	mdev->peer_uuid = be64_to_cpu(buffer->peer_uuid);
 	mdev->sync_conf.al_extents = be32_to_cpu(buffer->al_nr_extents);
 	if (mdev->sync_conf.al_extents < 7)
 		mdev->sync_conf.al_extents = 127;
@@ -2349,105 +2345,60 @@
 	return rv;
 }
 
-#if DUMP_MD >= 1
-#define MeGC(x) mdev->gen_cnt[x]
-#define PeGC(x) mdev->p_gen_cnt[x]
 
-void drbd_dump_md(drbd_dev *mdev, int verbose)
+void drbd_uuid_set_current(drbd_dev *mdev, u64 val)
 {
-	INFO("I am(%c): %c:%08x:%08x:%08x:%08x:%c%c\n",
-		mdev->state.s.role == Primary ? 'P':'S',
-		MeGC(Flags) & MDF_Consistent ? '1' : '0',
-		MeGC(HumanCnt),
-		MeGC(TimeoutCnt),
-		MeGC(ConnectedCnt),
-		MeGC(ArbitraryCnt),
-		MeGC(Flags) & MDF_PrimaryInd   ? '1' : '0',
-		MeGC(Flags) & MDF_ConnectedInd ? '1' : '0');
-	if (mdev->p_gen_cnt) {
-		INFO("Peer(%c): %c:%08x:%08x:%08x:%08x:%c%c\n",
-			mdev->state.s.peer == Primary ? 'P':'S',
-			PeGC(Flags) & MDF_Consistent ? '1' : '0',
-			PeGC(HumanCnt),
-			PeGC(TimeoutCnt),
-			PeGC(ConnectedCnt),
-			PeGC(ArbitraryCnt),
-			PeGC(Flags) & MDF_PrimaryInd   ? '1' : '0',
-			PeGC(Flags) & MDF_ConnectedInd ? '1' : '0');
+	mdev->uuid[Current] = val;
+	if (mdev->state.s.role == Primary) {
+		mdev->uuid[Current] |= 1;
 	} else {
-		INFO("Peer Unknown.\n");
+		mdev->uuid[Current] &= ~((u64)1);
 	}
-	if (verbose) {
-		/* TODO
-		 * dump activity log and bitmap summary,
-		 * and maybe other statistics
-		 */
+}
+
+void drbd_uuid_new_current(drbd_dev *mdev)
+{
+	D_ASSERT(mdev->uuid[Bitmap] = 0);
+	mdev->uuid[Bitmap] = mdev->uuid[Current];
+	get_random_bytes(&mdev->uuid[Current], sizeof(u64));
+	if (mdev->state.s.role == Primary) {
+		mdev->uuid[Current] |= 1;
+	} else {
+		mdev->uuid[Current] &= ~((u64)1);
 	}
 }
 
-#undef MeGC
-#undef PeGC
-#else
-void drbd_dump_md(drbd_dev *mdev, Drbd_Parameter_Packet *peer, int verbose)
-{ /* do nothing */ }
-#endif
-
-//  Returns  1 if I have the good bits,
-//           0 if both are nice
-//          -1 if the partner has the good bits.
-int drbd_md_compare(drbd_dev *mdev)
+void drbd_uuid_reset_bm(drbd_dev *mdev)
 {
 	int i;
-	u32 self,peer;
 
-	self = mdev->gen_cnt[Flags] & MDF_Consistent;
-	peer = mdev->p_gen_cnt[Flags] & MDF_Consistent;
-	if( self > peer ) return 1;
-	if( self < peer ) return -1;
+	if (mdev->uuid[Bitmap] == 0) return;
 
-	self = mdev->gen_cnt[Flags] & MDF_WasUpToDate;
-	peer = mdev->p_gen_cnt[Flags] & MDF_WasUpToDate;
-	if( self > peer ) return 1;
-	if( self < peer ) return -1;
-
-	for(i=HumanCnt;i<=ArbitraryCnt;i++) {
-		self = mdev->gen_cnt[i];
-		peer = mdev->p_gen_cnt[i];
-		if( self > peer ) return 1;
-		if( self < peer ) return -1;
+	for ( i=History_start ; i<History_end ; i++ ) {
+		mdev->uuid[i+1] = mdev->uuid[i];
 	}
 
-	self = mdev->gen_cnt[Flags] & MDF_PrimaryInd;
-	peer = mdev->p_gen_cnt[Flags] & MDF_PrimaryInd;
-	if( self > peer ) return 1;
-	if( self < peer ) return -1;
-
-	return 0;
+	mdev->uuid[History_start]=mdev->uuid[Bitmap];
+	mdev->uuid[Bitmap]=0;
 }
 
-/* THINK do these have to be protected by some lock ? */
-void drbd_md_inc(drbd_dev *mdev, enum MetaDataIndex order)
-{
-	set_bit(MD_DIRTY,&mdev->flags);
-	mdev->gen_cnt[order]++;
-}
 void drbd_md_set_flag(drbd_dev *mdev, int flag)
 {
-	if ( (mdev->gen_cnt[Flags] & flag) != flag) {
+	if ( (mdev->md_flags & flag) != flag) {
 		set_bit(MD_DIRTY,&mdev->flags);
-		mdev->gen_cnt[Flags] |= flag;
+		mdev->md_flags |= flag;
 	}
 }
 void drbd_md_clear_flag(drbd_dev *mdev, int flag)
 {
-	if ( (mdev->gen_cnt[Flags] & flag) != 0 ) {
+	if ( (mdev->md_flags & flag) != 0 ) {
 		set_bit(MD_DIRTY,&mdev->flags);
-		mdev->gen_cnt[Flags] &= ~flag;
+		mdev->md_flags &= ~flag;
 	}
 }
 int drbd_md_test_flag(drbd_dev *mdev, int flag)
 {
-	return ((mdev->gen_cnt[Flags] & flag) != 0);
+	return ((mdev->md_flags & flag) != 0);
 }
 
 module_init(drbd_init)

Modified: trunk/drbd/drbd_receiver.c
===================================================================
--- trunk/drbd/drbd_receiver.c	2005-04-04 12:05:08 UTC (rev 1776)
+++ trunk/drbd/drbd_receiver.c	2005-04-04 15:19:41 UTC (rev 1777)
@@ -1257,123 +1257,133 @@
 	return TRUE;
 }
 
+/*
+  100   after split brain try auto recover
+    2   SyncSource set BitMap
+    1   SyncSource use BitMap
+    0   no Sync
+   -1   SyncTarget use BitMap
+   -2   SyncTarget set BitMap
+ -100   after split brain, disconnect
+-1000   unrelated data
+ */
+static int drbd_uuid_compare(drbd_dev *mdev)
+{
+	u64 self, peer;
+	int i,j;
+
+	self = mdev->uuid[Current] & ~((u64)1);
+	peer = mdev->p_uuid[Current] & ~((u64)1);
+
+	if (self == UUID_JUST_CREATED &&
+	    peer == UUID_JUST_CREATED) return 0;
+
+	if (self == UUID_JUST_CREATED && 
+	    peer != UUID_JUST_CREATED) return -2;
+
+	if (self != UUID_JUST_CREATED && 
+	    peer == UUID_JUST_CREATED) return 2;
+
+	if (self == peer) return 0;
+
+	peer = mdev->p_uuid[Bitmap] & ~((u64)1);
+	if (self == peer) return -1;
+
+	for ( i=History_start ; i<=History_end ; i++ ) {
+		peer = mdev->p_uuid[i];
+		if (self == peer) return -2;
+	}
+
+	self = mdev->uuid[Bitmap] & ~((u64)1);
+	peer = mdev->p_uuid[Current] & ~((u64)1);
+
+	if (self == peer) return 1;
+	
+	for ( i=History_start ; i<=History_end ; i++ ) {
+		self = mdev->uuid[i] & ~((u64)1);
+		if (self == peer) return 2;
+	}
+
+	self = mdev->uuid[Bitmap] & ~((u64)1);
+	peer = mdev->p_uuid[Bitmap] & ~((u64)1);
+
+	if (self == peer) return 100;
+
+	for ( i=History_start ; i<=History_end ; i++ ) {
+		self = mdev->p_uuid[i] & ~((u64)1);
+		for ( j=History_start ; j<=History_end ; j++ ) {
+			peer = mdev->p_uuid[j] & ~((u64)1);
+			if (self == peer) return -100;
+		}
+	}
+
+	return -1000;
+}
+
 /* drbd_sync_handshake() returns the new conn state on success, or 
    conn_mask (-1) on failure.
  */
 STATIC drbd_conns_t drbd_sync_handshake(drbd_dev *mdev)
 {
-	int have_good,sync;
+	int hg;
 	drbd_conns_t rv = conn_mask;
 
-	have_good = drbd_md_compare(mdev);
+	hg = drbd_uuid_compare(mdev);
 
-	if(have_good==0) {
-		if (drbd_md_test_flag(mdev,MDF_PrimaryInd)) {
-			/* gen counts compare the same, but I have the
-			 * PrimaryIndicator set.  so the peer has, too
-			 * (otherwise this would not compare the same).
-			 * so we had a split brain!
-			 *
-			 * FIXME maybe log MDF_SplitBran into metadata,
-			 * and refuse to do anything until told otherwise!
-			 *
-			 * for now: just go StandAlone.
-			 */
-			ALERT("Split-Brain detected, dropping connection!\n");
-			drbd_force_state(mdev,NS(conn,StandAlone));
-			drbd_thread_stop_nowait(&mdev->receiver);
-			return conn_mask;
-		}
-		sync=0;
-	} else {
-		sync=1;
+	if (abs(hg) >= 100) {
+		ALERT("Split-Brain detected, dropping connection!\n");
+		drbd_force_state(mdev,NS(conn,StandAlone));
+		drbd_thread_stop_nowait(&mdev->receiver);
+		return conn_mask;
 	}
 
-	drbd_dump_md(mdev,0);
-	// INFO("have_good=%d sync=%d\n", have_good, sync);
-
-	if (have_good > 0 && mdev->state.s.disk <= Inconsistent ) {
-		/* doh. I cannot become SyncSource when I am inconsistent!
-		 */
+	if (hg > 0 && mdev->state.s.disk <= Inconsistent ) {
 		ERR("I shall become SyncSource, but I am inconsistent!\n");
 		drbd_force_state(mdev,NS(conn,StandAlone));
 		drbd_thread_stop_nowait(&mdev->receiver);
 		return conn_mask;
 	}
-	if (have_good < 0 && !(mdev->p_gen_cnt[Flags] & MDF_Consistent) ) {
-		/* doh. Peer cannot become SyncSource when inconsistent
-		 */
-		ERR("I shall become SyncTarget, but Peer is inconsistent!\n");
+	if (hg < 0 && mdev->state.s.role == Primary ) {
+		ERR("I shall become SyncTarget, but I am primary!\n");
 		drbd_force_state(mdev,NS(conn,StandAlone));
 		drbd_thread_stop_nowait(&mdev->receiver);
 		return conn_mask;
 	}
 
-	if ( mdev->sync_conf.skip && sync ) {
-		return have_good == 1 ? SkippedSyncS : SkippedSyncT ;
+	if (abs(hg) >= 2) {
+		drbd_md_set_flag(mdev,MDF_FullSync);
+		drbd_md_write(mdev);
+
+		drbd_bm_set_all(mdev);
+		drbd_bm_write(mdev);
+
+		drbd_md_clear_flag(mdev,MDF_FullSync);
+		drbd_md_write(mdev);
 	}
 
-	if( sync ) {
-		if( test_bit(UUID_CHANGED,&mdev->flags) ) {
-			WARN("Peer presented a new UUID -> full sync.\n");
-			drbd_bm_set_all(mdev);
-			clear_bit(UUID_CHANGED, &mdev->flags);
-		}
-
-		if(have_good == 1) {
-			D_ASSERT(drbd_md_test_flag(mdev,MDF_Consistent));
-			rv = WFBitMapS;
-			wait_event(mdev->cstate_wait,
-			     atomic_read(&mdev->ap_bio_cnt)==0);
-			drbd_bm_lock(mdev);   // {
-			drbd_send_bitmap(mdev);
-			drbd_bm_unlock(mdev); // }
-		} else { // have_good == -1
-			if ( (mdev->state.s.role == Primary) &&
-			     drbd_md_test_flag(mdev,MDF_Consistent) ) {
-				/* FIXME
-				 * allow Primary become SyncTarget if it was
-				 * diskless, and now had a storage reattached.
-				 * only somewhere the MDF_Consistent flag is
-				 * set where it should not... I think.
-				 */
-				ERR("Current Primary shall become sync TARGET!"
-				    " Aborting to prevent data corruption.\n");
-				drbd_force_state(mdev,NS(conn,StandAlone));
-				drbd_thread_stop_nowait(&mdev->receiver);
-				return conn_mask;
-			}
-			drbd_md_clear_flag(mdev,MDF_Consistent);
-			rv = WFBitMapT;
-		}
+	if (hg > 0) { // become sync source.
+		D_ASSERT(drbd_md_test_flag(mdev,MDF_Consistent));
+		rv = WFBitMapS;
+		wait_event(mdev->cstate_wait,
+			   atomic_read(&mdev->ap_bio_cnt)==0);
+		drbd_bm_lock(mdev);   // {
+		drbd_send_bitmap(mdev);
+		drbd_bm_unlock(mdev); // }
+	} else if (hg < 0) { // become sync target
+		drbd_md_clear_flag(mdev,MDF_Consistent);
+		drbd_uuid_set_current(mdev,mdev->p_uuid[Bitmap]);
+		rv = WFBitMapT;		
 	} else {
 		rv = Connected;
 		drbd_bm_lock(mdev);   // {
 		if(drbd_bm_total_weight(mdev)) {
-			if (drbd_md_test_flag(mdev,MDF_Consistent)) {
-				/* We are not going to do a resync but there
-				   are marks in the bitmap.
-				   (Could be from the AL, or someone used
-				   the write_gc.pl program)
-				   Clean the bitmap...
-				 */
-				INFO("No resync -> clearing bit map.\n");
-				drbd_bm_clear_all(mdev);
-				drbd_bm_write(mdev);
-			} else {
-				WARN("I am inconsistent, but there is no sync? BOTH nodes inconsistent!\n");
-			}
+			INFO("No resync -> clearing bit map.\n");
+			drbd_bm_clear_all(mdev);
+			drbd_bm_write(mdev);
 		}
 		drbd_bm_unlock(mdev); // }
 	}
 
-	if (have_good == -1) {
-		/* Sync-Target has to adopt source's gen_cnt. */
-		int i;
-		for(i=HumanCnt;i<GEN_CNT_SIZE;i++) {
-			mdev->gen_cnt[i]=mdev->p_gen_cnt[i];
-		}
-	}
 	return rv;
 }
 
@@ -1403,11 +1413,6 @@
 		return FALSE;
 	}
 
-	if( mdev->peer_uuid != be64_to_cpu(p->uuid) ) {
-		mdev->peer_uuid = be64_to_cpu(p->uuid);
-		set_bit(UUID_CHANGED, &mdev->flags);
-	}
-
 	return TRUE;
 }
 
@@ -1459,10 +1464,8 @@
 	drbd_determin_dev_size(mdev);
 	drbd_bm_unlock(mdev); // }
 	
-	if (mdev->p_gen_cnt) {
+	if (mdev->p_uuid) {
 		nconn=drbd_sync_handshake(mdev);
-		kfree(mdev->p_gen_cnt);
-		mdev->p_gen_cnt = 0;
 		if(nconn == conn_mask) return FALSE;
 
 		if(drbd_request_state(mdev,NS(conn,nconn)) <= 0) {
@@ -1489,24 +1492,24 @@
 	return TRUE;
 }
 
-STATIC int receive_gen_cnt(drbd_dev *mdev, Drbd_Header *h)
+STATIC int receive_uuids(drbd_dev *mdev, Drbd_Header *h)
 {
 	Drbd_GenCnt_Packet *p = (Drbd_GenCnt_Packet*)h;
-	u32 *p_gen_cnt;
+	u64 *p_uuid;
 	int i;
 
 	ERR_IF(h->length != (sizeof(*p)-sizeof(*h))) return FALSE;
 	if (drbd_recv(mdev, h->payload, h->length) != h->length)
 		return FALSE;
 
-	p_gen_cnt = kmalloc(sizeof(u32)*GEN_CNT_SIZE, GFP_KERNEL);
+	p_uuid = kmalloc(sizeof(u64)*UUID_SIZE, GFP_KERNEL);
 
-	for (i = Flags; i < GEN_CNT_SIZE; i++) {
-		p_gen_cnt[i] = be32_to_cpu(p->gen_cnt[i]);
+	for (i = Current; i < UUID_SIZE; i++) {
+		p_uuid[i] = be64_to_cpu(p->uuid[i]);
 	}
 
-	if ( mdev->p_gen_cnt ) kfree(mdev->p_gen_cnt);
-	mdev->p_gen_cnt = p_gen_cnt;
+	if ( mdev->p_uuid ) kfree(mdev->p_uuid);
+	mdev->p_uuid = p_uuid;
 
 	return TRUE;
 }
@@ -1526,10 +1529,10 @@
 	nconn = mdev->state.s.conn;
 	if (nconn == WFReportParams ) nconn = Connected;
 
-	if (mdev->p_gen_cnt) {
+	if (mdev->p_uuid && mdev->state.s.conn == Connected) {
 		nconn=drbd_sync_handshake(mdev);
-		kfree(mdev->p_gen_cnt);
-		mdev->p_gen_cnt = 0;
+		kfree(mdev->p_uuid);
+		mdev->p_uuid = 0;
 		if(nconn == conn_mask) return FALSE;
 	}
 
@@ -1730,7 +1733,7 @@
 	[RSDataRequest]    = receive_DataRequest, //receive_RSDataRequest,
 	[SyncParam]        = receive_SyncParam,
 	[ReportProtocol]   = receive_protocol,
-	[ReportGenCnt]     = receive_gen_cnt,
+	[ReportUUIDs]     = receive_uuids,
 	[ReportSizes]      = receive_sizes,
 	[ReportState]      = receive_state,
 };
@@ -1876,10 +1879,13 @@
 		drbd_thread_start(&mdev->worker);
 	}
 
-	if ( test_bit(SPLIT_BRAIN_FIX,&mdev->flags) && 
-	     mdev->state.s.role == Primary) {
-		drbd_disks_t nps = drbd_try_outdate_peer(mdev);
-		drbd_request_state(mdev,NS(pdsk,nps));
+	if ( mdev->state.s.role == Primary ) {
+		if ( test_bit(SPLIT_BRAIN_FIX,&mdev->flags) ) {
+			drbd_disks_t nps = drbd_try_outdate_peer(mdev);
+			drbd_request_state(mdev,NS(pdsk,nps));
+		} else {
+			drbd_uuid_new_current(mdev);
+		}
 		drbd_md_write(mdev);
 	}
 

Modified: trunk/drbd/drbd_sizeof_sanity_check.c
===================================================================
--- trunk/drbd/drbd_sizeof_sanity_check.c	2005-04-04 12:05:08 UTC (rev 1776)
+++ trunk/drbd/drbd_sizeof_sanity_check.c	2005-04-04 15:19:41 UTC (rev 1777)
@@ -23,7 +23,7 @@
 	SZO(struct ioctl_syncer_config,	 32)
 	SZO(struct ioctl_wait,		 16)
 	SZO(struct ioctl_get_config,	560)
-	SZO(struct ioctl_get_gen_cnt,    48)
+	SZO(struct ioctl_get_uuids,      48)
 	if (err) printk("<3>ioctls won't work, aborting\n");
 	return err;
 }

Modified: trunk/drbd/drbd_worker.c
===================================================================
--- trunk/drbd/drbd_worker.c	2005-04-04 12:05:08 UTC (rev 1776)
+++ trunk/drbd/drbd_worker.c	2005-04-04 15:19:41 UTC (rev 1777)
@@ -390,6 +390,9 @@
 	mdev->rs_total  = 0;
 	mdev->rs_paused = 0;
 
+	drbd_uuid_set_current(mdev,mdev->p_uuid[Current]);
+	drbd_uuid_reset_bm(mdev);
+
 	drbd_request_state(mdev,NS3(conn,Connected,
 				    disk,UpToDate,
 				    pdsk,UpToDate));

Modified: trunk/drbd/linux/drbd.h
===================================================================
--- trunk/drbd/linux/drbd.h	2005-04-04 12:05:08 UTC (rev 1776)
+++ trunk/drbd/linux/drbd.h	2005-04-04 15:19:41 UTC (rev 1777)
@@ -273,6 +273,7 @@
 #define MDF_FullSync        (1<<__MDF_FullSync)
 #define MDF_WasUpToDate     (1<<__MDF_WasUpToDate)
 
+/* MetaDataIndex is scheduled for removal! */
 enum MetaDataIndex {
 	Flags,			/* Consistency flag,connected-ind,primary-ind */
 	HumanCnt,		/* human-intervention-count */
@@ -282,11 +283,19 @@
 	GEN_CNT_SIZE		/* MUST BE LAST! (and Flags must stay first...) */
 };
 
-struct ioctl_get_gen_cnt {
-	OUT __u64        uuid;
-	OUT __u64        peer_uuid;
+enum UuidIndex {
+	Current,
+	Bitmap,
+	History_start,
+	History_end,
+	UUID_SIZE
+};
+
+#define UUID_JUST_CREATED ((__u64)4)
+
+struct ioctl_get_uuids {
+	OUT __u64        uuid[UUID_SIZE];
 	OUT __u64        current_size;
-	OUT __u32        gen_cnt[GEN_CNT_SIZE];	/* generation counter */
 	OUT unsigned int bits_set;
 };
 
@@ -312,7 +321,7 @@
 #define DRBD_IOCTL_UNCONFIG_DISK    _IO ( DRBD_IOCTL_LETTER, 0x13 )
 #define DRBD_IOCTL_SET_STATE_FLAGS  _IOW( DRBD_IOCTL_LETTER, 0x14, drbd_role_t )
 #define DRBD_IOCTL_OUTDATE_DISK     _IOW( DRBD_IOCTL_LETTER, 0x15, int )
-#define DRBD_IOCTL_GET_GEN_CNT      _IOR( DRBD_IOCTL_LETTER, 0x15, struct ioctl_get_gen_cnt )
+#define DRBD_IOCTL_GET_UUIDS        _IOR( DRBD_IOCTL_LETTER, 0x16, struct ioctl_get_uuids )
 
 
 #endif

Modified: trunk/drbd/linux/drbd_config.h
===================================================================
--- trunk/drbd/linux/drbd_config.h	2005-04-04 12:05:08 UTC (rev 1776)
+++ trunk/drbd/linux/drbd_config.h	2005-04-04 15:19:41 UTC (rev 1777)
@@ -30,10 +30,6 @@
 
 //#define DBG_SPINLOCKS   // enables MUST_HOLD macro (assertions for spinlocks)
 //#define DBG_ASSERTS     // drbd_assert_breakpoint() function
-//#define DUMP_MD 1       // Dump metadata to syslog upon connect
-#define DUMP_MD 2       // Dump even all cstate changes (I like it!)
-//#define DUMP_MD 3       // Dump even all meta data access
-                          // (don't! unless we track down a bug...)
 
 //#define PARANOIA // some extra checks
 

From www-data at garcon.linbit.com  Tue Apr  5 14:30:22 2005
From: www-data at garcon.linbit.com (www-data)
Date: Tue Apr  5 14:30:22 2005
Subject: [DRBD-cvs] r1778 - branches/drbd-0.7/drbd
Message-ID: <20050405123022.5E9B414E50@mail.linbit.com>

Author: phil
Date: 2005-04-05 14:30:20 +0200 (Tue, 05 Apr 2005)
New Revision: 1778

Modified:
   branches/drbd-0.7/drbd/drbd_compat_wrappers.h
   branches/drbd-0.7/drbd/lru_cache.c
Log:
Make drbd-0.7 to compile on 2.4.18 again


Modified: branches/drbd-0.7/drbd/drbd_compat_wrappers.h
===================================================================
--- branches/drbd-0.7/drbd/drbd_compat_wrappers.h	2005-04-04 15:19:41 UTC (rev 1777)
+++ branches/drbd-0.7/drbd/drbd_compat_wrappers.h	2005-04-05 12:30:20 UTC (rev 1778)
@@ -14,8 +14,8 @@
  */
 static inline void dump_stack(void)
 {
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,9)
-	// It seems that on 2.4.9 even show_stack is not available.
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,18)
+	// It seems that before 2.4.18 even show_stack is not available.
         show_stack(0);
 #endif
 }

Modified: branches/drbd-0.7/drbd/lru_cache.c
===================================================================
--- branches/drbd-0.7/drbd/lru_cache.c	2005-04-04 15:19:41 UTC (rev 1777)
+++ branches/drbd-0.7/drbd/lru_cache.c	2005-04-05 12:30:20 UTC (rev 1778)
@@ -24,7 +24,7 @@
    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 
  */
-
+#include <linux/compiler.h> // for likely()
 #include <linux/bitops.h>
 #include <linux/vmalloc.h>
 #include <linux/string.h> // for memset

From www-data at garcon.linbit.com  Tue Apr  5 16:25:54 2005
From: www-data at garcon.linbit.com (www-data)
Date: Tue Apr  5 16:25:55 2005
Subject: [DRBD-cvs] r1779 - in trunk: . drbd drbd/linux user
Message-ID: <20050405142554.564E5144FF@mail.linbit.com>

Author: phil
Date: 2005-04-05 16:25:45 +0200 (Tue, 05 Apr 2005)
New Revision: 1779

Modified:
   trunk/ROADMAP
   trunk/drbd/drbd_fs.c
   trunk/drbd/drbd_receiver.c
   trunk/drbd/drbd_worker.c
   trunk/drbd/linux/drbd.h
   trunk/user/drbd_endian.h
   trunk/user/drbdadm_main.c
   trunk/user/drbdmeta.c
   trunk/user/drbdsetup.c
   trunk/user/drbdtool_common.c
   trunk/user/drbdtool_common.h
Log:
More work on item 16. Mostly implemented by now, needs
debugging.


Modified: trunk/ROADMAP
===================================================================
--- trunk/ROADMAP	2005-04-05 12:30:20 UTC (rev 1778)
+++ trunk/ROADMAP	2005-04-05 14:25:45 UTC (rev 1779)
@@ -468,9 +468,9 @@
            NB: If they are needed, I think they can be implemented
                as special UUID values.
 
-  50% DONE. Kernel part is implemented, not tested. But testing
-            will only be possible after drbdmeta was updated. 
-            Drbdmeta still has no clue of gen-UUIDs, not drbdsetup.
+  80% DONE. Kernel part is implemented, little tested. Userlang parts
+            implemented, seem to work. Known bugs: Upon connect
+            sync_handshake is not called, need to fix this.
 
 17 Something like
 

Modified: trunk/drbd/drbd_fs.c
===================================================================
--- trunk/drbd/drbd_fs.c	2005-04-05 12:30:20 UTC (rev 1778)
+++ trunk/drbd/drbd_fs.c	2005-04-05 14:25:45 UTC (rev 1779)
@@ -992,6 +992,7 @@
 	for (i = Current; i < UUID_SIZE; i++) {
 		cn.uuid[i]=mdev->uuid[i];
 	}
+	cn.flags = mdev->md_flags;
 	cn.bits_set = drbd_bm_total_weight(mdev);
 	cn.current_size = drbd_get_capacity(mdev->this_bdev);
 

Modified: trunk/drbd/drbd_receiver.c
===================================================================
--- trunk/drbd/drbd_receiver.c	2005-04-05 12:30:20 UTC (rev 1778)
+++ trunk/drbd/drbd_receiver.c	2005-04-05 14:25:45 UTC (rev 1779)
@@ -1529,10 +1529,8 @@
 	nconn = mdev->state.s.conn;
 	if (nconn == WFReportParams ) nconn = Connected;
 
-	if (mdev->p_uuid && mdev->state.s.conn == Connected) {
+	if (mdev->p_uuid && mdev->state.s.conn <= Connected) {
 		nconn=drbd_sync_handshake(mdev);
-		kfree(mdev->p_uuid);
-		mdev->p_uuid = 0;
 		if(nconn == conn_mask) return FALSE;
 	}
 

Modified: trunk/drbd/drbd_worker.c
===================================================================
--- trunk/drbd/drbd_worker.c	2005-04-05 12:30:20 UTC (rev 1778)
+++ trunk/drbd/drbd_worker.c	2005-04-05 14:25:45 UTC (rev 1779)
@@ -390,7 +390,9 @@
 	mdev->rs_total  = 0;
 	mdev->rs_paused = 0;
 
-	drbd_uuid_set_current(mdev,mdev->p_uuid[Current]);
+	if ( mdev->state.s.conn == SyncTarget ) {
+		drbd_uuid_set_current(mdev,mdev->p_uuid[Current]);
+	}
 	drbd_uuid_reset_bm(mdev);
 
 	drbd_request_state(mdev,NS3(conn,Connected,

Modified: trunk/drbd/linux/drbd.h
===================================================================
--- trunk/drbd/linux/drbd.h	2005-04-05 12:30:20 UTC (rev 1778)
+++ trunk/drbd/linux/drbd.h	2005-04-05 14:25:45 UTC (rev 1779)
@@ -296,6 +296,7 @@
 struct ioctl_get_uuids {
 	OUT __u64        uuid[UUID_SIZE];
 	OUT __u64        current_size;
+	OUT unsigned int flags;
 	OUT unsigned int bits_set;
 };
 

Modified: trunk/user/drbd_endian.h
===================================================================
--- trunk/user/drbd_endian.h	2005-04-05 12:30:20 UTC (rev 1778)
+++ trunk/user/drbd_endian.h	2005-04-05 14:25:45 UTC (rev 1779)
@@ -140,4 +140,30 @@
 	return sizeof(w) == 4 ? generic_hweight32(w) : generic_hweight64(w);
 }
 
+
+/*
+ * Format macros for printf()
+ */
+
+#if BITS_PER_LONG == 32
+# define X32 "%lX"
+//# define X64 "%llX"
+# define X64(a) "%"#a"llX"
+# define D32 "%ld"
+# define D64 "%lld"
+# define U32 "%lu"
+# define U64 "%llu"
+#elif BITS_PER_LONG == 64
+# define X32 "%X"
+//# define X64 "%lX"
+# define X64(a) "%"#a"lX"
+# define D32 "%d"
+# define D64 "%ld"
+# define U32 "%u"
+# define U64 "%lu"
+#else
+# error "sorry, weird endianness on this box"
 #endif
+
+#endif
+

Modified: trunk/user/drbdadm_main.c
===================================================================
--- trunk/user/drbdadm_main.c	2005-04-05 12:30:20 UTC (rev 1778)
+++ trunk/user/drbdadm_main.c	2005-04-05 14:25:45 UTC (rev 1779)
@@ -191,11 +191,10 @@
   { "cstate",            adm_generic_s,         1, 1 },
   { "dump",              adm_dump,              1, 1 },
   { "create-md",         admm_generic,          1, 1 },
-  { "show-gc",           adm_generic_b,         1, 1 },
-  { "get-gc",            adm_generic_b,         1, 1 },
+  { "show-gi",           adm_generic_b,         1, 1 },
+  { "get-gi",            adm_generic_b,         1, 1 },
   { "dump-md",           admm_generic,          1, 1 },
-  { "set-gc",            admm_generic,          0, 1 },
-  { "set-uuid",          admm_generic,          0, 1 },
+  { "set-gi",            admm_generic,          0, 1 },
   { "pri-on-incon-degr", adm_khelper,           0, 1 },
   { "pri-sees-sec-with-higher-gc", adm_khelper, 0, 1 },
   { "outdate-peer",      adm_khelper,           0, 1 },

Modified: trunk/user/drbdmeta.c
===================================================================
--- trunk/user/drbdmeta.c	2005-04-05 12:30:20 UTC (rev 1778)
+++ trunk/user/drbdmeta.c	2005-04-05 14:25:45 UTC (rev 1779)
@@ -137,13 +137,13 @@
 	 * 0.7 stores la_size on disk as kb, 0.8 in units of sectors.
 	 * we use sectors in our general working structure here */
 	u64 la_sect;		/* last agreed size. */
-	u64 uuid;
-	u64 peer_uuid;
 	u32 md_size;
 	u32 al_offset;		/* offset to this block */
 	u32 al_nr_extents;	/* important for restoring the AL */
 	u32 bm_offset;		/* offset to the bitmap, from here */
-	/* more to come eventually */
+	/* Since DRBD 0.8 we have uuid instead of gc */
+	u64 uuid[UUID_SIZE];
+	u32 flags;
 };
 
 /*
@@ -319,9 +319,8 @@
 
 struct __attribute__ ((packed)) md_on_disk_08 {
 	be_u64 la_sect;		/* last agreed size. */
-	be_u64 uuid;            /* universally unique identifier */
-	be_u64 peer_uuid;       /* universally unique identifier */
-	be_u32 gc[GEN_CNT_SIZE];	/* generation counter */
+	be_u64 uuid[UUID_SIZE];   // UUIDs.
+	be_u32 flags;
 	be_u32 magic;
 	be_u32 md_size;
 	be_u32 al_offset;	/* offset to this block */
@@ -334,10 +333,9 @@
 {
 	int i;
 	cpu->la_sect = be64_to_cpu(disk->la_sect.be);
-	cpu->uuid = be64_to_cpu(disk->uuid.be);
-	cpu->peer_uuid = be64_to_cpu(disk->peer_uuid.be);
-	for (i = 0; i < GEN_CNT_SIZE; i++)
-		cpu->gc[i] = be32_to_cpu(disk->gc[i].be);
+	for ( i=Current ; i<UUID_SIZE ; i++ )
+		cpu->uuid[i] = be64_to_cpu(disk->uuid[i].be);
+	cpu->flags = be32_to_cpu(disk->flags.be);
 	cpu->magic = be32_to_cpu(disk->magic.be);
 	cpu->md_size = be32_to_cpu(disk->md_size.be);
 	cpu->al_offset = be32_to_cpu(disk->al_offset.be);
@@ -349,10 +347,9 @@
 {
 	int i;
 	disk->la_sect.be = cpu_to_be64(cpu->la_sect);
-	disk->uuid.be  = cpu_to_be64(cpu->uuid);
-	disk->peer_uuid.be  = cpu_to_be64(cpu->peer_uuid);
-	for (i = 0; i < GEN_CNT_SIZE; i++)
-		disk->gc[i].be = cpu_to_be32(cpu->gc[i]);
+	for ( i=Current ; i<UUID_SIZE ; i++ )
+		disk->uuid[i].be = cpu_to_be64(cpu->uuid[i]);
+	disk->flags.be = cpu_to_be32(cpu->flags);
 	disk->magic.be = cpu_to_be32(cpu->magic);
 	disk->md_size.be = cpu_to_be32(cpu->md_size);
 	disk->al_offset.be = cpu_to_be32(cpu->al_offset);
@@ -446,6 +443,8 @@
 	int (*md_initialize) (struct format *);
 	int (*md_disk_to_cpu) (struct format *);
 	int (*md_cpu_to_disk) (struct format *);
+	void (*get_gi) (struct format *);
+	void (*show_gi) (struct format *);
 };
 
 /*
@@ -459,6 +458,31 @@
 	Drbd_Unknown,
 };
 
+/*
+ * Some glue
+ */
+
+void m_get_gc(struct format *cfg)
+{
+	dt_print_gc(cfg->md.gc);
+}
+
+void m_show_gc(struct format *cfg)
+{
+	dt_pretty_print_gc(cfg->md.gc);
+}
+
+void m_get_uuid(struct format *cfg)
+{
+	dt_print_uuids(cfg->md.uuid,cfg->md.flags);
+}
+
+void m_show_uuid(struct format *cfg)
+{
+	dt_pretty_print_uuids(cfg->md.uuid,cfg->md.flags);
+}
+
+
 /* pre declarations */
 int v06_md_close(struct format *cfg);
 int v06_md_cpu_to_disk(struct format *cfg);
@@ -489,6 +513,8 @@
 		     .md_initialize = v06_md_initialize,
 		     .md_disk_to_cpu = v06_md_disk_to_cpu,
 		     .md_cpu_to_disk = v06_md_cpu_to_disk,
+		     .get_gi = m_get_gc,
+		     .show_gi = m_show_gc,
 		     },
 	[Drbd_07] = {
 		     .name = "v07",
@@ -499,6 +525,8 @@
 		     .md_initialize = v07_md_initialize,
 		     .md_disk_to_cpu = v07_md_disk_to_cpu,
 		     .md_cpu_to_disk = v07_md_cpu_to_disk,
+		     .get_gi = m_get_gc,
+		     .show_gi = m_show_gc,
 		     },
 	[Drbd_08] = {
 		     .name = "v08",
@@ -509,6 +537,8 @@
 		     .md_initialize = v08_md_initialize,
 		     .md_disk_to_cpu = v08_md_disk_to_cpu,
 		     .md_cpu_to_disk = v08_md_cpu_to_disk,
+		     .get_gi = m_get_uuid,
+		     .show_gi = m_show_uuid,
 		     },
 };
 
@@ -533,16 +563,15 @@
 int meta_set_uuid(struct format *cfg, char **argv, int argc);
 
 struct meta_cmd cmds[] = {
-	{"get-gc", 0, meta_get_gc, 1},
-	{"show-gc", 0, meta_show_gc, 1},
+	{"get-gi", 0, meta_get_gc, 1},
+	{"show-gi", 0, meta_show_gc, 1},
 	{"dump-md", 0, meta_dump_md, 1},
 	{"create-md", 0, meta_create_md, 1},
 	/* FIXME convert still missing.
 	 * implicit convert from v07 to v08 by create-md
 	 * see comments there */
 	{"outdate", 0, meta_outdate_gc, 1},
-	{"set-uuid", 0, meta_set_uuid, 1},
-	{"set-gc", ":::VAL:VAL:...", meta_set_gc, 0},
+	{"set-gi", ":::VAL:VAL:...", meta_set_gc, 0},
 };
 
 /*
@@ -1021,15 +1050,15 @@
 int v08_md_initialize(struct format *cfg)
 {
 	u64 al_offset, bm_offset;
+	int i;
 
 	cfg->md.la_sect = 0;
-	get_real_random(&cfg->md.uuid,sizeof(u64));
-	cfg->md.peer_uuid = 0;
-	cfg->md.gc[Flags] = 0;
-	cfg->md.gc[HumanCnt] = 1;	/* THINK 0? 1? */
-	cfg->md.gc[TimeoutCnt] = 1;
-	cfg->md.gc[ConnectedCnt] = 1;
-	cfg->md.gc[ArbitraryCnt] = 1;
+	cfg->md.uuid[Current] = UUID_JUST_CREATED;
+	cfg->md.uuid[Bitmap] = 0;
+	for ( i=History_start ; i<=History_end ; i++ ) {
+		cfg->md.uuid[i]=0;
+	}
+	cfg->md.flags = 0;
 	cfg->md.magic = DRBD_MD_MAGIC_08;
 
 	/*
@@ -1072,7 +1101,6 @@
 /******************************************
   }}} end of v08
  ******************************************/
-
 int meta_get_gc(struct format *cfg, char **argv, int argc)
 {
 	if (argc > 0) {
@@ -1081,7 +1109,9 @@
 
 	if (cfg->ops->open(cfg))
 		return -1;
-	dt_print_gc(cfg->md.gc);
+
+	cfg->ops->get_gi(cfg);
+
 	return cfg->ops->close(cfg);
 }
 
@@ -1096,7 +1126,7 @@
 	if (cfg->ops->open(cfg))
 		return -1;
 
-	dt_pretty_print_gc(cfg->md.gc);
+	cfg->ops->show_gi(cfg);
 
 	if (cfg->md.la_sect) {
 		printf("last agreed size: %s\n",
@@ -1107,9 +1137,6 @@
 		printf("zero size device -- never seen peer yet?\n");
 	}
 
-	printf("local  uuid: %llX\n",cfg->md.uuid);
-	printf("peer's uuid: %llX\n",cfg->md.peer_uuid);
-
 	return cfg->ops->close(cfg);
 }
 
@@ -1128,23 +1155,21 @@
 	 * so we can safely restore it later */
 	printf("DRBD meta data dump version <FIXME drbdmeta dump version>\n");
 	printf("meta data version %s\n\n", cfg->ops->name);
-	printf("gc {");
-	for (i = 0; i < GEN_CNT_SIZE; i++) {
-		printf(" 0x%X;", cfg->md.gc[i]);
+	if (cfg->ops < f_ops + Drbd_08) {
+		printf("gc {");
+		for (i = 0; i < GEN_CNT_SIZE; i++) {
+			printf(" 0x%X;", cfg->md.gc[i]);
+		}
+	} else { // >= 08
+		printf("uuid {");
+		for ( i=Current ; i<UUID_SIZE ; i++ ) {
+			printf(" 0x"X64(016)";", cfg->md.uuid[i]);
+		}
 	}
 	printf(" }\n");
 
 	if (cfg->ops >= f_ops + Drbd_07) {
 		printf("la-size-sect %llu;\n", cfg->md.la_sect);
-	}
-
-	if (cfg->ops >= f_ops + Drbd_08) {
-		printf("uuid %llX;\n", cfg->md.uuid);
-		printf("peer-uuid %llX;\n", cfg->md.peer_uuid);
-		printf("# FIXME include offsets, once they are not fixed anymore\n");
-	}
-
-	if (cfg->ops >= f_ops + Drbd_07) {
 		printf("# bm-bytes %u;\n", cfg->bm_bytes);
 		printf("# bits-set %u;\n", cfg->bits_set);
 		if (cfg->on_disk.bm)
@@ -1168,14 +1193,15 @@
 	 * We only need to adjust the magic here. */
 	printf("Converting meta data...\n");
 	cfg->md.magic = DRBD_MD_MAGIC_08;
-	get_real_random(&cfg->md.uuid,sizeof(u64));
-	cfg->md.peer_uuid = 0;
+	// get_real_random(&cfg->md.uuid,sizeof(u64));
+	// cfg->md.peer_uuid = 0;
 	if (cfg->ops->md_cpu_to_disk(cfg)
 	    || cfg->ops->close(cfg)) {
 		fprintf(stderr, "conversion failed\n");
 		return -1;
 	}
-	printf("Successfully converted v07 meta data to v08 format.\n");
+	printf("Convertion Currently BROKEN!\n");
+	//printf("Successfully converted v07 meta data to v08 format.\n");
 	return 0;
 }
 
@@ -1269,32 +1295,6 @@
 	return rv;
 }
 
-int meta_set_uuid(struct format *cfg, char **argv, int argc)
-{
-	int err;
-
-	if (argc > 1) {
-		fprintf(stderr, "Ignoring additional arguments\n");
-	}
-	if (argc < 1) {
-		fprintf(stderr, "Required Argument missing\n");
-		exit(10);
-	}
-
-	if (cfg->ops->open(cfg))
-		return -1;
-
-	cfg->md.uuid = strtoll(argv[0],NULL,16);
-
-	err = cfg->ops->md_cpu_to_disk(cfg)
-	    || cfg->ops->close(cfg);
-	if (err)
-		fprintf(stderr, "update failed\n");
-
-	return err;
-	
-}
-
 int meta_set_gc(struct format *cfg, char **argv, int argc)
 {
 	struct md_cpu tmp;

Modified: trunk/user/drbdsetup.c
===================================================================
--- trunk/user/drbdsetup.c	2005-04-05 12:30:20 UTC (rev 1778)
+++ trunk/user/drbdsetup.c	2005-04-05 14:25:45 UTC (rev 1779)
@@ -114,8 +114,8 @@
 int cmd_detach(int drbd_fd,char** argv,int argc,struct option *options);
 int cmd_state(int drbd_fd,char** argv,int argc,struct option *options);
 int cmd_cstate(int drbd_fd,char** argv,int argc,struct option *options);
-int cmd_show_gc(int drbd_fd,char** argv,int argc,struct option *options);
-int cmd_get_gc(int drbd_fd,char** argv,int argc,struct option *options);
+int cmd_show_gi(int drbd_fd,char** argv,int argc,struct option *options);
+int cmd_get_gi(int drbd_fd,char** argv,int argc,struct option *options);
 
 struct drbd_cmd commands[] = {
   {"primary", cmd_primary,           0,
@@ -181,8 +181,8 @@
   {"disconnect", cmd_disconnect,     0, 0, },
   {"state", cmd_state,               0, 0, },
   {"cstate", cmd_cstate,             0, 0, },
-  {"show-gc", cmd_show_gc,           0, 0, },
-  {"get-gc", cmd_get_gc,             0, 0, },
+  {"show-gi", cmd_show_gi,           0, 0, },
+  {"get-gi", cmd_get_gi,             0, 0, },
   {"show", cmd_show,                 0, 0, },
 };
 
@@ -1349,45 +1349,42 @@
   return 0;
 }
 
-int cmd_get_gc(int drbd_fd,char** argv,int argc,struct option *options)
+int cmd_get_gi(int drbd_fd,char** argv,int argc,struct option *options)
 {
-  struct ioctl_get_gen_cnt cn;
+  struct ioctl_get_uuids cn;
   int err;
 
-  err=ioctl(drbd_fd,DRBD_IOCTL_GET_GEN_CNT,&cn);
+  err=ioctl(drbd_fd,DRBD_IOCTL_GET_UUIDS,&cn);
   if(err)
     {
-      PERROR("ioctl(,GET_GEN_CNT,) failed");
+      PERROR("ioctl(,GET_GEN_UUIDS,) failed");
       return 20;
     }
   
-  dt_print_gc(cn.gen_cnt);
+  dt_print_uuids(cn.uuid, cn.flags);
 
   return 0;
 }
 
-int cmd_show_gc(int drbd_fd,char** argv,int argc,struct option *options)
+int cmd_show_gi(int drbd_fd,char** argv,int argc,struct option *options)
 {
-  struct ioctl_get_gen_cnt cn;
+  struct ioctl_get_uuids cn;
   char ppb[10];
   int err;
 
-  err=ioctl(drbd_fd,DRBD_IOCTL_GET_GEN_CNT,&cn);
+  err=ioctl(drbd_fd,DRBD_IOCTL_GET_UUIDS,&cn);
   if(err)
     {
-      PERROR("ioctl(,GET_GEN_CNT,) failed");
+      PERROR("ioctl(,GET_GEN_UUIDS,) failed");
       return 20;
     }
   
-  dt_pretty_print_gc(cn.gen_cnt);
+  dt_pretty_print_uuids(cn.uuid, cn.flags);
 
   printf("current agreed size: %s\n", ppsize(ppb, cn.current_size >> 1));
   printf("%u bits set in the bitmap [ %s out of sync ]\n",
 	 cn.bits_set, ppsize(ppb, cn.bits_set * 4));
 
-  printf("local  uuid: %llX\n",cn.uuid);
-  printf("peer's uuid: %llX\n",cn.peer_uuid);
-
   return 0;
 }
 

Modified: trunk/user/drbdtool_common.c
===================================================================
--- trunk/user/drbdtool_common.c	2005-04-05 12:30:20 UTC (rev 1778)
+++ trunk/user/drbdtool_common.c	2005-04-05 14:25:45 UTC (rev 1779)
@@ -15,6 +15,7 @@
 #include <linux/drbd.h>
 
 #include "drbdtool_common.h"
+#include "drbd_endian.h"
 
 char* ppsize(char* buf, size_t size) 
 {
@@ -318,3 +319,25 @@
 	       gen_cnt[Flags] & MDF_ConnectedInd ? "1/c" : "0/n",
 	       gen_cnt[Flags] & MDF_FullSync ? "1/y" : "0/n");
 }
+
+void dt_print_uuids(const __u64* uuid, unsigned int flags)
+{
+	int i;
+	printf(X64(016)":"X64(016)":",
+	       uuid[Current],
+	       uuid[Bitmap]);
+	for ( i=History_start ; i<=History_end ; i++ ) {
+		printf(X64(016)":", uuid[i]);
+	}
+	printf("%d:%d:%d:%d:%d\n",
+	       flags & MDF_Consistent ? 1 : 0,
+	       flags & MDF_WasUpToDate ? 1 : 0,
+	       flags & MDF_PrimaryInd ? 1 : 0,
+	       flags & MDF_ConnectedInd ? 1 : 0,
+	       flags & MDF_FullSync ? 1 : 0);
+}
+
+void dt_pretty_print_uuids(const __u64* uuid, unsigned int flags)
+{
+	dt_print_uuids(uuid, flags);
+}

Modified: trunk/user/drbdtool_common.h
===================================================================
--- trunk/user/drbdtool_common.h	2005-04-05 12:30:20 UTC (rev 1778)
+++ trunk/user/drbdtool_common.h	2005-04-05 14:25:45 UTC (rev 1779)
@@ -22,6 +22,7 @@
 extern char* ppsize(char* buf, size_t size);
 extern void dt_print_gc(const __u32* gen_cnt);
 extern void dt_pretty_print_gc(const __u32* gen_cnt);
+extern void dt_print_uuids(const __u64* uuid, unsigned int flags);
+extern void dt_pretty_print_uuids(const __u64* uuid, unsigned int flags);
 
 #endif
-

From www-data at garcon.linbit.com  Wed Apr  6 10:57:04 2005
From: www-data at garcon.linbit.com (www-data)
Date: Wed Apr  6 10:57:12 2005
Subject: [DRBD-cvs] r1780 - in trunk: . drbd user
Message-ID: <20050406085709.5F68C1430E@mail.linbit.com>

Author: phil
Date: 2005-04-06 10:56:58 +0200 (Wed, 06 Apr 2005)
New Revision: 1780

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
   trunk/user/drbdtool_common.c
Log:
Some polish on the data generation UUID work...


Modified: trunk/ROADMAP
===================================================================
--- trunk/ROADMAP	2005-04-05 14:25:45 UTC (rev 1779)
+++ trunk/ROADMAP	2005-04-06 08:56:58 UTC (rev 1780)
@@ -171,9 +171,8 @@
   drbdadm is the nice front end. It always uses the right 
   back end (drbdmeta or drbdsetup)...
 
-  drbdadm md-set-gc 1:2:3:4:5:6 r0
-  drbdadm md-get-gc r0
-  drbdadm md-get/set-{la-size|consistent|etc...} resources....
+  drbdadm set-gi 1:2:3:4:5:6 r0
+  drbdadm get-gi r0
   drbdadm md-create r0
 
   md-create would ask nasty questions about whether you are really 
@@ -468,9 +467,9 @@
            NB: If they are needed, I think they can be implemented
                as special UUID values.
 
-  80% DONE. Kernel part is implemented, little tested. Userlang parts
-            implemented, seem to work. Known bugs: Upon connect
-            sync_handshake is not called, need to fix this.
+  90% DONE. Kernel part is implemented, userlang parts are implemented,
+	    only "drbdadm set-gi" is still unimplemented.
+	    Everything seems to work so far. Should be tested more.
 
 17 Something like
 

Modified: trunk/drbd/drbd_fs.c
===================================================================
--- trunk/drbd/drbd_fs.c	2005-04-05 14:25:45 UTC (rev 1779)
+++ trunk/drbd/drbd_fs.c	2005-04-06 08:56:58 UTC (rev 1780)
@@ -838,7 +838,7 @@
 
 	if (mdev->state.s.conn >= WFReportParams) {
 		/* if this was forced, we should consider sync */
-		if(forced) drbd_send_gen_cnt(mdev);
+		if(forced) drbd_send_uuids(mdev);
 		drbd_send_state(mdev);
 	}
 
@@ -1106,7 +1106,7 @@
 		drbd_md_write(mdev); // Write mdev->la_size to disk.
 		drbd_bm_unlock(mdev);
 		if (mdev->state.s.conn == Connected) {
-			drbd_send_gen_cnt(mdev); // to start sync...
+			drbd_send_uuids(mdev); // to start sync...
 			drbd_send_sizes(mdev);
 		}
 		break;

Modified: trunk/drbd/drbd_int.h
===================================================================
--- trunk/drbd/drbd_int.h	2005-04-05 14:25:45 UTC (rev 1779)
+++ trunk/drbd/drbd_int.h	2005-04-06 08:56:58 UTC (rev 1780)
@@ -740,6 +740,7 @@
 	int open_cnt;
 	unsigned int md_flags;
 	u64 uuid[UUID_SIZE];
+	u64 as_c_uuid;         // Store the peers c-uuid until resync finished.
 	u64 *p_uuid;
 	atomic_t epoch_size;
 	spinlock_t ee_lock;
@@ -800,7 +801,7 @@
 extern int drbd_send(drbd_dev *mdev, struct socket *sock,
 		     void* buf, size_t size, unsigned msg_flags);
 extern int drbd_send_protocol(drbd_dev *mdev);
-extern int drbd_send_gen_cnt(drbd_dev *mdev);
+extern int drbd_send_uuids(drbd_dev *mdev);
 extern int drbd_send_sizes(drbd_dev *mdev);
 extern int drbd_send_state(drbd_dev *mdev);
 extern int _drbd_send_cmd(drbd_dev *mdev, struct socket *sock,
@@ -834,7 +835,8 @@
 extern void drbd_md_write(drbd_dev *mdev);
 extern int drbd_md_read(drbd_dev *mdev);
 // maybe define them below as inline?
-extern void drbd_uuid_set_current(drbd_dev *mdev, u64 val);
+extern void drbd_uuid_set(drbd_dev *mdev,int idx, u64 val);
+extern void _drbd_uuid_set(drbd_dev *mdev, int idx, u64 val);
 extern void drbd_uuid_new_current(drbd_dev *mdev);
 extern void drbd_uuid_reset_bm(drbd_dev *mdev);
 extern void drbd_md_set_flag(drbd_dev *mdev, int flags);

Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c	2005-04-05 14:25:45 UTC (rev 1779)
+++ trunk/drbd/drbd_main.c	2005-04-06 08:56:58 UTC (rev 1780)
@@ -677,12 +677,6 @@
 		drbd_panic("No access to good data anymore.\n");
 	}
 
-	if ( os.s.conn != Connected && ns.s.conn == Connected && 
-	     mdev->p_uuid ) {
-		kfree(mdev->p_uuid);
-		mdev->p_uuid = 0;
-	}
-
 	return rv;
 }
 
@@ -956,7 +950,7 @@
 			     (Drbd_Header*)&p,sizeof(p));
 }
 
-int drbd_send_gen_cnt(drbd_dev *mdev)
+int drbd_send_uuids(drbd_dev *mdev)
 {
 	Drbd_GenCnt_Packet p;
 	int i;
@@ -2346,19 +2340,39 @@
 }
 
 
-void drbd_uuid_set_current(drbd_dev *mdev, u64 val)
+
+
+static void drbd_uuid_move_history(drbd_dev *mdev)
 {
-	mdev->uuid[Current] = val;
+	int i;
+
+	for ( i=History_start ; i<History_end ; i++ ) {
+		mdev->uuid[i+1] = mdev->uuid[i];
+	}
+}
+
+void _drbd_uuid_set(drbd_dev *mdev, int idx, u64 val)
+{
 	if (mdev->state.s.role == Primary) {
-		mdev->uuid[Current] |= 1;
+		mdev->uuid[idx] = val | 1;
 	} else {
-		mdev->uuid[Current] &= ~((u64)1);
+		mdev->uuid[idx] = val & ~((u64)1);
 	}
 }
 
+
+void drbd_uuid_set(drbd_dev *mdev, int idx, u64 val)
+{
+	if(mdev->uuid[idx]) {
+		drbd_uuid_move_history(mdev);
+		mdev->uuid[History_start]=mdev->uuid[idx];
+	}
+	_drbd_uuid_set(mdev,idx,val);
+}
+
 void drbd_uuid_new_current(drbd_dev *mdev)
 {
-	D_ASSERT(mdev->uuid[Bitmap] = 0);
+	D_ASSERT(mdev->uuid[Bitmap] == 0);
 	mdev->uuid[Bitmap] = mdev->uuid[Current];
 	get_random_bytes(&mdev->uuid[Current], sizeof(u64));
 	if (mdev->state.s.role == Primary) {
@@ -2370,14 +2384,9 @@
 
 void drbd_uuid_reset_bm(drbd_dev *mdev)
 {
-	int i;
-
 	if (mdev->uuid[Bitmap] == 0) return;
 
-	for ( i=History_start ; i<History_end ; i++ ) {
-		mdev->uuid[i+1] = mdev->uuid[i];
-	}
-
+	drbd_uuid_move_history(mdev);
 	mdev->uuid[History_start]=mdev->uuid[Bitmap];
 	mdev->uuid[Bitmap]=0;
 }

Modified: trunk/drbd/drbd_receiver.c
===================================================================
--- trunk/drbd/drbd_receiver.c	2005-04-05 14:25:45 UTC (rev 1779)
+++ trunk/drbd/drbd_receiver.c	2005-04-06 08:56:58 UTC (rev 1780)
@@ -717,7 +717,7 @@
 	drbd_send_protocol(mdev);
 	drbd_send_sync_param(mdev,&mdev->sync_conf);
 	drbd_send_sizes(mdev);
-	drbd_send_gen_cnt(mdev);
+	drbd_send_uuids(mdev);
 	drbd_send_state(mdev);
 
 	return 1;
@@ -1371,7 +1371,8 @@
 		drbd_bm_unlock(mdev); // }
 	} else if (hg < 0) { // become sync target
 		drbd_md_clear_flag(mdev,MDF_Consistent);
-		drbd_uuid_set_current(mdev,mdev->p_uuid[Bitmap]);
+		drbd_uuid_set(mdev,Current,mdev->p_uuid[Bitmap]);
+		mdev->as_c_uuid = mdev->p_uuid[Current];
 		rv = WFBitMapT;		
 	} else {
 		rv = Connected;
@@ -1466,6 +1467,8 @@
 	
 	if (mdev->p_uuid) {
 		nconn=drbd_sync_handshake(mdev);
+		kfree(mdev->p_uuid);
+		mdev->p_uuid = 0;
 		if(nconn == conn_mask) return FALSE;
 
 		if(drbd_request_state(mdev,NS(conn,nconn)) <= 0) {
@@ -1529,8 +1532,10 @@
 	nconn = mdev->state.s.conn;
 	if (nconn == WFReportParams ) nconn = Connected;
 
-	if (mdev->p_uuid && mdev->state.s.conn <= Connected) {
+	if (mdev->p_uuid) {
 		nconn=drbd_sync_handshake(mdev);
+		kfree(mdev->p_uuid);
+		mdev->p_uuid = 0;
 		if(nconn == conn_mask) return FALSE;
 	}
 
@@ -1539,7 +1544,7 @@
 	if (mdev->state.s.conn > WFReportParams ) {
 		if( nconn > Connected && peer_state.s.conn == Connected) {
 			// we want resync, peer has not yet decided to sync...
-			drbd_send_gen_cnt(mdev);
+			drbd_send_uuids(mdev);
 			drbd_send_state(mdev);
 		}
 	}
@@ -1731,7 +1736,7 @@
 	[RSDataRequest]    = receive_DataRequest, //receive_RSDataRequest,
 	[SyncParam]        = receive_SyncParam,
 	[ReportProtocol]   = receive_protocol,
-	[ReportUUIDs]     = receive_uuids,
+	[ReportUUIDs]      = receive_uuids,
 	[ReportSizes]      = receive_sizes,
 	[ReportState]      = receive_state,
 };

Modified: trunk/drbd/drbd_worker.c
===================================================================
--- trunk/drbd/drbd_worker.c	2005-04-05 14:25:45 UTC (rev 1779)
+++ trunk/drbd/drbd_worker.c	2005-04-06 08:56:58 UTC (rev 1780)
@@ -391,7 +391,9 @@
 	mdev->rs_paused = 0;
 
 	if ( mdev->state.s.conn == SyncTarget ) {
-		drbd_uuid_set_current(mdev,mdev->p_uuid[Current]);
+		/* Do not pushin the peer's Bitmap UUID into my History. */
+		_drbd_uuid_set(mdev,Current,mdev->as_c_uuid);
+		// mdev->as_c_uuid = 0xf0deadbeefbabe0fLL;
 	}
 	drbd_uuid_reset_bm(mdev);
 

Modified: trunk/user/drbdtool_common.c
===================================================================
--- trunk/user/drbdtool_common.c	2005-04-05 14:25:45 UTC (rev 1779)
+++ trunk/user/drbdtool_common.c	2005-04-06 08:56:58 UTC (rev 1780)
@@ -339,5 +339,20 @@
 
 void dt_pretty_print_uuids(const __u64* uuid, unsigned int flags)
 {
+	printf(
+"\n"
+"       +--<  Current data generation UUID  >-\n"
+"       |               +--<  Bitmap's base data generation UUID  >-\n"
+"       |               |                 +--<  younger historiy UUID  >-\n"
+"       |               |                 |         +-<  older history  >-\n"
+"       V               V                 V         V\n");               
 	dt_print_uuids(uuid, flags);
+	printf(
+"                                                                    ^ ^ ^ ^ ^\n"
+"                                      -<  Data consistancy flag  >--+ | | | |\n"
+"                             -<  Data was/is currently up-to-date  >--+ | | |\n"
+"                                  -<  Node was/is currently primary  >--+ | |\n"
+"                                  -<  Node was/is currently connected  >--+ |\n"
+"          -<  Node was in to progress of setting all bits in the bitmap  >--+\n"
+"\n");
 }

From www-data at garcon.linbit.com  Wed Apr  6 11:02:07 2005
From: www-data at garcon.linbit.com (www-data)
Date: Wed Apr  6 11:02:08 2005
Subject: [DRBD-cvs] r1781 - trunk
Message-ID: <20050406090207.202651430E@mail.linbit.com>

Author: phil
Date: 2005-04-06 11:02:06 +0200 (Wed, 06 Apr 2005)
New Revision: 1781

Modified:
   trunk/ROADMAP
Log:
Fixed an error in the Text...


Modified: trunk/ROADMAP
===================================================================
--- trunk/ROADMAP	2005-04-06 08:56:58 UTC (rev 1780)
+++ trunk/ROADMAP	2005-04-06 09:02:06 UTC (rev 1781)
@@ -449,7 +449,7 @@
 
   Upon start of resync:
    Clear the consistent-flag on the SyncTarget. The SyncTarget sets its
-   bitmap-UUID to the peer's current-UUID.
+   current-UUID to the peer's bitmap-UUID.
 
   Upon finish of resync:
    Set the bitmap-UUID to 0. The SyncTarget addopts the current-UUID

From www-data at garcon.linbit.com  Thu Apr 21 12:16:24 2005
From: www-data at garcon.linbit.com (www-data)
Date: Thu Apr 21 12:16:27 2005
Subject: [DRBD-cvs] r1782 - in trunk: . user
Message-ID: <20050421101624.BACE91590C@mail.linbit.com>

Author: phil
Date: 2005-04-21 12:16:23 +0200 (Thu, 21 Apr 2005)
New Revision: 1782

Modified:
   trunk/ROADMAP
   trunk/user/drbd_endian.h
   trunk/user/drbdmeta.c
Log:
Implemented set-gi in drbdmeta


Modified: trunk/ROADMAP
===================================================================
--- trunk/ROADMAP	2005-04-06 09:02:06 UTC (rev 1781)
+++ trunk/ROADMAP	2005-04-21 10:16:23 UTC (rev 1782)
@@ -411,7 +411,7 @@
 
   When the cluster is in Connected state, then the bitmpat gen-UUID
   is set to 0 (Since the Bitmap is empty). When we create a new current
-  gen-UUID while we are disconencted the (old) current gets backuped
+  gen-UUID while we are disconencted the (old) current gets backed-up
   to the bitmap gen-UUID. (This allowes us to identify the base of
   of the bitmap later)
 

Modified: trunk/user/drbd_endian.h
===================================================================
--- trunk/user/drbd_endian.h	2005-04-06 09:02:06 UTC (rev 1781)
+++ trunk/user/drbd_endian.h	2005-04-21 10:16:23 UTC (rev 1782)
@@ -162,8 +162,19 @@
 # define U32 "%u"
 # define U64 "%lu"
 #else
-# error "sorry, weird endianness on this box"
+# error "sorry, unsupported word length on this box"
 #endif
 
+
+
+#if BITS_PER_LONG == 32
+# define strto_u64 strtoull
+#elif BITS_PER_LONG == 64
+# define strto_u64 strtoul
+#else
+# error "sorry, unsupported word length on this box"
 #endif
 
+
+#endif
+

Modified: trunk/user/drbdmeta.c
===================================================================
--- trunk/user/drbdmeta.c	2005-04-06 09:02:06 UTC (rev 1781)
+++ trunk/user/drbdmeta.c	2005-04-21 10:16:23 UTC (rev 1782)
@@ -443,8 +443,9 @@
 	int (*md_initialize) (struct format *);
 	int (*md_disk_to_cpu) (struct format *);
 	int (*md_cpu_to_disk) (struct format *);
-	void (*get_gi) (struct format *);
-	void (*show_gi) (struct format *);
+	void (*get_gi) (struct md_cpu *md);
+	void (*show_gi) (struct md_cpu *md);
+	void (*set_gi) (struct md_cpu *md, char **argv, int argc);
 };
 
 /*
@@ -458,32 +459,14 @@
 	Drbd_Unknown,
 };
 
-/*
- * Some glue
- */
+/* pre declarations */
+void m_get_gc(struct md_cpu *md);
+void m_show_gc(struct md_cpu *md);
+void m_set_gc(struct md_cpu *md, char **argv, int argc);
+void m_get_uuid(struct md_cpu *md);
+void m_show_uuid(struct md_cpu *md);
+void m_set_uuid(struct md_cpu *md, char **argv, int argc);
 
-void m_get_gc(struct format *cfg)
-{
-	dt_print_gc(cfg->md.gc);
-}
-
-void m_show_gc(struct format *cfg)
-{
-	dt_pretty_print_gc(cfg->md.gc);
-}
-
-void m_get_uuid(struct format *cfg)
-{
-	dt_print_uuids(cfg->md.uuid,cfg->md.flags);
-}
-
-void m_show_uuid(struct format *cfg)
-{
-	dt_pretty_print_uuids(cfg->md.uuid,cfg->md.flags);
-}
-
-
-/* pre declarations */
 int v06_md_close(struct format *cfg);
 int v06_md_cpu_to_disk(struct format *cfg);
 int v06_md_disk_to_cpu(struct format *cfg);
@@ -515,6 +498,7 @@
 		     .md_cpu_to_disk = v06_md_cpu_to_disk,
 		     .get_gi = m_get_gc,
 		     .show_gi = m_show_gc,
+		     .set_gi = m_set_gc,
 		     },
 	[Drbd_07] = {
 		     .name = "v07",
@@ -527,6 +511,7 @@
 		     .md_cpu_to_disk = v07_md_cpu_to_disk,
 		     .get_gi = m_get_gc,
 		     .show_gi = m_show_gc,
+		     .set_gi = m_set_gc,
 		     },
 	[Drbd_08] = {
 		     .name = "v08",
@@ -539,6 +524,7 @@
 		     .md_cpu_to_disk = v08_md_cpu_to_disk,
 		     .get_gi = m_get_uuid,
 		     .show_gi = m_show_uuid,
+		     .set_gi = m_set_uuid,
 		     },
 };
 
@@ -554,24 +540,24 @@
 };
 
 /* pre declarations */
-int meta_get_gc(struct format *cfg, char **argv, int argc);
-int meta_show_gc(struct format *cfg, char **argv, int argc);
+int meta_get_gi(struct format *cfg, char **argv, int argc);
+int meta_show_gi(struct format *cfg, char **argv, int argc);
 int meta_dump_md(struct format *cfg, char **argv, int argc);
 int meta_create_md(struct format *cfg, char **argv, int argc);
-int meta_set_gc(struct format *cfg, char **argv, int argc);
-int meta_outdate_gc(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);
 
 struct meta_cmd cmds[] = {
-	{"get-gi", 0, meta_get_gc, 1},
-	{"show-gi", 0, meta_show_gc, 1},
+	{"get-gi", 0, meta_get_gi, 1},
+	{"show-gi", 0, meta_show_gi, 1},
 	{"dump-md", 0, meta_dump_md, 1},
 	{"create-md", 0, meta_create_md, 1},
 	/* FIXME convert still missing.
 	 * implicit convert from v07 to v08 by create-md
 	 * see comments there */
-	{"outdate", 0, meta_outdate_gc, 1},
-	{"set-gi", ":::VAL:VAL:...", meta_set_gc, 0},
+	{"outdate", 0, meta_outdate, 1},
+	{"set-gi", ":::VAL:VAL:...", meta_set_gi, 0},
 };
 
 /*
@@ -752,6 +738,144 @@
 	return 0;
 }
 
+void m_get_gc(struct md_cpu *md)
+{
+	dt_print_gc(md->gc);
+}
+
+void m_show_gc(struct md_cpu *md)
+{
+	dt_pretty_print_gc(md->gc);
+}
+
+void m_get_uuid(struct md_cpu *md)
+{
+	dt_print_uuids(md->uuid,md->flags);
+}
+
+void m_show_uuid(struct md_cpu *md)
+{
+	dt_pretty_print_uuids(md->uuid,md->flags);
+}
+
+int m_strsep_u32(char **s, u32 *val)
+{
+	char *t, *e;
+	u32 v;
+
+	if ((t = strsep(s, ":"))) {
+		if (strlen(t)) {
+			e = t;
+			v = strtol(t, &e, 0);
+			if (*e != 0) {
+				fprintf(stderr, "'%s' is not a number.\n", *s);
+				exit(10);
+			}
+			if (v < 0) {
+				fprintf(stderr, "'%s' is negative.\n", *s);
+				exit(10);
+			}
+			if (v > 0xFFffFFff) {
+				fprintf(stderr,
+					"'%s' is out of range (max 0xFFffFFff).\n",
+					*s);
+				exit(10);
+			}
+			*val = v;
+		}
+		return 1;
+	}
+	return 0;
+}
+
+int m_strsep_u64(char **s, u64 *val)
+{
+	char *t, *e;
+	u64 v;
+
+	if ((t = strsep(s, ":"))) {
+		if (strlen(t)) {
+			e = t;
+			v = strto_u64(t, &e, 16);
+			if (*e != 0) {
+				fprintf(stderr, "'%s' is not a number.\n", *s);
+				exit(10);
+			}
+			if (v < 0) {
+				fprintf(stderr, "'%s' is negative.\n", *s);
+				exit(10);
+			}
+			*val = v;
+		}
+		return 1;
+	}
+	return 0;
+}
+
+int m_strsep_bit(char **s, int *val, int mask)
+{
+	int d;
+	int rv;
+
+	d = *val & mask;
+
+	rv = m_strsep_u32(s, &d);
+
+	if (d > 1) {
+		fprintf(stderr, "'%d' is not 0 or 1.\n", d);
+		exit(10);
+	}
+
+	if (d)
+		*val |= mask;
+	else
+		*val &= ~mask;
+
+	return rv;
+}
+
+void m_set_gc(struct md_cpu *md, char **argv, int argc)
+{
+	char **str;
+
+	str = &argv[0];
+
+	do {
+		if (!m_strsep_bit(str, &md->gc[Flags], MDF_Consistent)) break;
+		if (!m_strsep_bit(str, &md->gc[Flags], MDF_WasUpToDate)) break;
+		if (!m_strsep_u32(str, &md->gc[HumanCnt])) break;
+		if (!m_strsep_u32(str, &md->gc[TimeoutCnt])) break;
+		if (!m_strsep_u32(str, &md->gc[ConnectedCnt])) break;
+		if (!m_strsep_u32(str, &md->gc[ArbitraryCnt])) break;
+		if (!m_strsep_bit(str, &md->gc[Flags], MDF_PrimaryInd)) break;
+		if (!m_strsep_bit(str, &md->gc[Flags], MDF_ConnectedInd)) break;
+		if (!m_strsep_bit(str, &md->gc[Flags], MDF_FullSync)) break;
+	} while (0);
+}
+
+void m_set_uuid(struct md_cpu *md, char **argv, int argc)
+{
+	char **str;
+	int i;
+
+	str = &argv[0];
+
+	do {
+		for ( i=Current ; i<UUID_SIZE ; i++ ) {
+			if (!m_strsep_u64(str, &md->uuid[i])) goto done;
+		}
+		if (!m_strsep_bit(str, &md->flags, MDF_Consistent)) break;
+		if (!m_strsep_bit(str, &md->flags, MDF_WasUpToDate)) break;
+		if (!m_strsep_bit(str, &md->flags, MDF_PrimaryInd)) break;
+		if (!m_strsep_bit(str, &md->flags, MDF_ConnectedInd)) break;
+		if (!m_strsep_bit(str, &md->flags, MDF_FullSync)) break;
+	} while (0);
+	done:
+}
+
+
+
+
 /******************************************
  begin of v06 {{{
  ******************************************/
@@ -1101,7 +1225,7 @@
 /******************************************
   }}} end of v08
  ******************************************/
-int meta_get_gc(struct format *cfg, char **argv, int argc)
+int meta_get_gi(struct format *cfg, char **argv, int argc)
 {
 	if (argc > 0) {
 		fprintf(stderr, "Ignoring additional arguments\n");
@@ -1110,12 +1234,12 @@
 	if (cfg->ops->open(cfg))
 		return -1;
 
-	cfg->ops->get_gi(cfg);
+	cfg->ops->get_gi(&cfg->md);
 
 	return cfg->ops->close(cfg);
 }
 
-int meta_show_gc(struct format *cfg, char **argv, int argc)
+int meta_show_gi(struct format *cfg, char **argv, int argc)
 {
 	char ppb[10];
 
@@ -1126,7 +1250,7 @@
 	if (cfg->ops->open(cfg))
 		return -1;
 
-	cfg->ops->show_gi(cfg);
+	cfg->ops->show_gi(&cfg->md);
 
 	if (cfg->md.la_sect) {
 		printf("last agreed size: %s\n",
@@ -1140,6 +1264,45 @@
 	return cfg->ops->close(cfg);
 }
 
+int meta_set_gi(struct format *cfg, char **argv, int argc)
+{
+	struct md_cpu tmp;
+	int err;
+
+	if (argc > 1) {
+		fprintf(stderr, "Ignoring additional arguments\n");
+	}
+	if (argc < 1) {
+		fprintf(stderr, "Required Argument missing\n");
+		exit(10);
+	}
+
+	if (cfg->ops->open(cfg))
+		return -1;
+
+	tmp = cfg->md;
+
+	cfg->ops->set_gi(&tmp,argv,argc);
+	printf("previously ");
+	cfg->ops->get_gi(&cfg->md);
+	printf("set GI to  ");
+	cfg->ops->get_gi(&tmp);
+
+	if (!confirmed("Write new GI to disk?")) {
+		printf("Operation cancelled.\n");
+		exit(0);
+	}
+
+	cfg->md = tmp;
+
+	err = cfg->ops->md_cpu_to_disk(cfg)
+	    || cfg->ops->close(cfg);
+	if (err)
+		fprintf(stderr, "update failed\n");
+
+	return err;
+}
+
 int meta_dump_md(struct format *cfg, char **argv, int argc)
 {
 	int i;
@@ -1243,115 +1406,10 @@
 	return err;
 }
 
-int m_strsep(char **s, int *val)
+int meta_outdate(struct format *cfg, char **argv, int argc)
 {
-	char *t, *e;
-	long v;
-
-	if ((t = strsep(s, ":"))) {
-		if (strlen(t)) {
-			e = t;
-			v = strtol(t, &e, 0);
-			if (*e != 0) {
-				fprintf(stderr, "'%s' is not a number.\n", *s);
-				exit(10);
-			}
-			if (v < 0) {
-				fprintf(stderr, "'%s' is negative.\n", *s);
-				exit(10);
-			}
-			if (v > 0xFFffFFff) {
-				fprintf(stderr,
-					"'%s' is out of range (max 0xFFffFFff).\n",
-					*s);
-				exit(10);
-			}
-			*val = v;
-		}
-		return 1;
-	}
-	return 0;
-}
-
-int m_strsep_b(char **s, int *val, int mask)
-{
-	int d;
-	int rv;
-
-	d = *val & mask;
-
-	rv = m_strsep(s, &d);
-
-	if (d > 1) {
-		fprintf(stderr, "'%d' is not 0 or 1.\n", d);
-		exit(10);
-	}
-
-	if (d)
-		*val |= mask;
-	else
-		*val &= ~mask;
-
-	return rv;
-}
-
-int meta_set_gc(struct format *cfg, char **argv, int argc)
-{
-	struct md_cpu tmp;
 	int err;
-	char **str;
 
-	if (argc > 1) {
-		fprintf(stderr, "Ignoring additional arguments\n");
-	}
-	if (argc < 1) {
-		fprintf(stderr, "Required Argument missing\n");
-		exit(10);
-	}
-
-	if (cfg->ops->open(cfg))
-		return -1;
-
-	tmp = cfg->md;
-	str = &argv[0];
-
-	do {
-		if (!m_strsep_b(str, &tmp.gc[Flags], MDF_Consistent)) break;
-		if (!m_strsep_b(str, &tmp.gc[Flags], MDF_WasUpToDate)) break;
-		if (!m_strsep(str, &tmp.gc[HumanCnt])) break;
-		if (!m_strsep(str, &tmp.gc[TimeoutCnt])) break;
-		if (!m_strsep(str, &tmp.gc[ConnectedCnt])) break;
-		if (!m_strsep(str, &tmp.gc[ArbitraryCnt])) break;
-		if (!m_strsep_b(str, &tmp.gc[Flags], MDF_PrimaryInd)) break;
-		if (!m_strsep_b(str, &tmp.gc[Flags], MDF_ConnectedInd)) break;
-		if (!m_strsep_b(str, &tmp.gc[Flags], MDF_FullSync)) break;
-	} while (0);
-
-	printf("  consistent:H:T:C:A:p:c:f\n");
-	printf("previously ");
-	dt_print_gc(cfg->md.gc);
-	printf("GCs set to ");
-	dt_print_gc(tmp.gc);
-
-	if (!confirmed("Write new GCs to disk?")) {
-		printf("Operation cancelled.\n");
-		exit(0);
-	}
-
-	cfg->md = tmp;
-
-	err = cfg->ops->md_cpu_to_disk(cfg)
-	    || cfg->ops->close(cfg);
-	if (err)
-		fprintf(stderr, "update failed\n");
-
-	return err;
-}
-
-int meta_outdate_gc(struct format *cfg, char **argv, int argc)
-{
-	int err;
-
 	if (argc > 0) {
 		fprintf(stderr, "Ignoring additional arguments\n");
 	}

From www-data at garcon.linbit.com  Thu Apr 21 12:18:54 2005
From: www-data at garcon.linbit.com (www-data)
Date: Thu Apr 21 12:18:56 2005
Subject: [DRBD-cvs] r1783 - in trunk: documentation user
Message-ID: <20050421101854.D4EC715C3C@mail.linbit.com>

Author: phil
Date: 2005-04-21 12:18:53 +0200 (Thu, 21 Apr 2005)
New Revision: 1783

Added:
   trunk/documentation/drbdmeta.sgml
   trunk/user/drbdmeta_parser.h
   trunk/user/drbdmeta_scanner.fl
Modified:
   trunk/documentation/drbdadm.sgml
   trunk/user/Makefile
   trunk/user/drbdmeta.c
   trunk/user/drbdtool_common.c
Log:
- man page for drbdmeta
- restore-md in drbdmeta


Modified: trunk/documentation/drbdadm.sgml
===================================================================
--- trunk/documentation/drbdadm.sgml	2005-04-21 10:16:23 UTC (rev 1782)
+++ trunk/documentation/drbdadm.sgml	2005-04-21 10:18:53 UTC (rev 1783)
@@ -18,6 +18,7 @@
       <arg>-d</arg>
       <arg>-c<arg choice="req"><replaceable>file</replaceable></arg></arg>
       <arg>-s<arg choice="req"><replaceable>cmd</replaceable></arg></arg>
+      <arg>-m<arg choice="req"><replaceable>cmd</replaceable></arg></arg>
       <arg choice="req"><replaceable>command</replaceable></arg>
       <group>
 	<arg choice="plain">all</arg>
@@ -30,8 +31,9 @@
     <title>Description</title>
     <para>
       Drbdadm is the high level tool of the DRBD program suite. Drbdadm is to 
-      drbdsetup what ifup/ifdown is to ifconfig. Drbdadm reads its configuration
-      file and performs the specified commands by calling the drbdsetup program.
+      drbdsetup and drbdmeta what ifup/ifdown is to ifconfig. Drbdadm reads its 
+      configuration file and performs the specified commands by calling the drbdsetup 
+      program.
     </para>    
   </refsect1>
   <refsect1>
@@ -61,6 +63,14 @@
 	  omitted, drbdadm will look for /sbin/drbdsetup and ./drbdsetup.
 	</para></listitem>
       </varlistentry>
+      <varlistentry>
+        <term><option>-m</option>, <option>--drbdmeta</option>
+          <replaceable>file</replaceable></term>
+        <listitem><para>
+          Specifies the full path to the drbdmeta program. If this option is
+	  omitted, drbdadm will look for /sbin/drbdmeta and ./drbdsetup.
+	</para></listitem>
+      </varlistentry>
     </variablelist>
   </refsect1>
   <refsect1>
@@ -154,6 +164,41 @@
         </para></listitem>
       </varlistentry>
       <varlistentry>
+        <term>create-md</term>
+        <listitem><para>
+          Create-md initializes the meta data storage. This needs to be
+	  done before a DRBD resource can be taken online for the first 
+	  time.
+        </para></listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>get-gi</term>
+        <listitem><para>
+          Get-gi shows a short textual repesentation of the data generation
+	  identifier.
+	</para></listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>show-gi</term>
+        <listitem><para>
+	  Show-gi prints a textual representation of the data generation
+	  identifiers including explanatory information.
+        </para></listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>dump-md</term>
+        <listitem><para>
+          Dumps the whole contents of the meta data storage including
+	  the stored bit-map and activity-log, in a textual representation.
+        </para></listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>outdate</term>
+        <listitem><para>
+          Sets the outdated flag in the meta data.
+        </para></listitem>
+      </varlistentry>
+      <varlistentry>
         <term>adjust</term>
         <listitem><para>
           Synchronizes the configuration of device with your configuration

Added: trunk/documentation/drbdmeta.sgml
===================================================================
--- trunk/documentation/drbdmeta.sgml	2005-04-21 10:16:23 UTC (rev 1782)
+++ trunk/documentation/drbdmeta.sgml	2005-04-21 10:18:53 UTC (rev 1783)
@@ -0,0 +1,144 @@
+<!DOCTYPE RefEntry PUBLIC "-//Davenport//DTD DocBook V3.0//EN">
+<refentry>
+  <docinfo><date>19 Apr 2005</date></docinfo>
+  
+  <refmeta>
+    <refentrytitle>drbdmeta</refentrytitle>
+    <manvolnum>8</manvolnum>
+  </refmeta>
+  
+  <refnamediv>
+    <refname>drbdmeta</refname>
+    <refpurpose>DRBD's meta data management tool</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <cmdsynopsis>
+      <command>drbdmeta</command>
+      <arg choice="req"><replaceable>device</replaceable></arg>
+      <group>
+	<arg choice="plain">v06<replaceable>minor</replaceable></arg>
+	<arg choice="plain">v07<replaceable>meta_dev index</replaceable></arg>
+	<arg choice="plain">v08<replaceable>meta_dev index</replaceable></arg>
+      </group>
+      <arg choice="req"><replaceable>command</replaceable></arg>
+      <arg rep="repeat"><replaceable>cmd args</replaceable></arg>
+    </cmdsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Description</title>
+    <para>
+      Drbdmeta is used to create, display and modify the contents of
+      DRBD's meta data storage. Usually you do not want to use this
+      command directly but use it through the front end drbdadm.
+    </para>
+    <para>
+      This command only works if the DRBD resource is currently down, 
+      or at least detached from its backing stoage. The first parameter
+      is the device node assosiated to the resource. With the second
+      parameter you select which the version of the meta data. Currently
+      all major DRBD releases (0.6, 0.7 and 0.8) are supported.
+    </para>    
+  </refsect1>
+  <refsect1>
+    <title>Commands</title>
+    <variablelist>
+      <varlistentry>
+        <term>create-md</term>
+        <listitem><para>
+          Create-md initializes the meta data storage. This needs to be
+	  done before a DRBD resource can be taken online for the first 
+	  time. In case there is already a meta data signature of an
+	  older format in place, drbdmeta will ask you if it should
+	  convert the older format to the selected format.
+	</para></listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>get-gi</term>
+        <listitem><para>
+          Get-gi shows a short textual repesentation of the data generation
+	  identifier. In version 0.6 and 0.7 this are generation counters,
+	  while in version 0.8 this is a set of UUIDs.
+	</para></listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>show-gi</term>
+        <listitem><para>
+	  Show-gi prints a textual representation of the data generation
+	  identifiers including explanatory information.
+        </para></listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>dump-md</term>
+        <listitem><para>
+          Dumps the whole contents of the meta data storage including
+	  the stored bit-map and activity-log, in a textual representation.
+        </para></listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>outdate</term>
+        <listitem><para>
+          Sets the outdated flag in the meta data. This is used by the
+	  peer node when it wants to become primary, but can not reach
+	  communicate with the DRBD stack on this host.
+        </para></listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+  <refsect1>
+    <title>Expert's commands</title>
+    <para>
+      Drbdmeta allows you to modifiy the meta data as well. This is
+      intetionally omitted for the commad's usage output, since you
+      should only use this if you really know what you are doing.
+      By setting the generation identifiers to wrong values you
+      risk to overwrite your up-to-data data by an older version 
+      of your data.
+    </para>
+    <variablelist>
+      <varlistentry>
+        <term>set-gi <replaceable>gi</replaceable></term>
+        <listitem><para>
+          Set-gi allows you to set the generation identifier. 
+	  <replaceable>Gi</replaceable> needs to be a generation 
+	  counter for the 0.6 and 0.7 format, and a UUID set for 0.8.
+	  Specify it in the same way as get-gi shows it.
+	</para></listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Version</title>
+    <simpara>
+      This document is correct for version 0.8 of the DRBD distribution.
+    </simpara>
+  </refsect1>
+
+  <refsect1>
+    <title>Author</title>
+    <simpara>Written by Philipp Reisner <email>philipp.reisner@linbit.com</email>.
+    </simpara>
+  </refsect1>
+  <refsect1>
+    <title>Reporting Bugs</title>
+    <simpara>Report bugs to <email>drbd-user@lists.linbit.com</email>.
+    </simpara>
+  </refsect1>
+  <refsect1>
+    <title>Copyright</title>
+    <simpara>
+      Copyright (c) 2004 Philipp Reisner. This  is  free software; 
+      see the source for copying conditions.  There is NO warranty; 
+      not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+    </simpara>
+  </refsect1>
+  <refsect1>
+    <title>See Also</title>
+    <para>
+      <citerefentry><refentrytitle>drbdadm</refentrytitle>
+      <manvolnum>8</manvolnum></citerefentry>
+    </para>
+  </refsect1>
+</refentry>

Modified: trunk/user/Makefile
===================================================================
--- trunk/user/Makefile	2005-04-21 10:16:23 UTC (rev 1782)
+++ trunk/user/Makefile	2005-04-21 10:18:53 UTC (rev 1783)
@@ -26,7 +26,7 @@
 drbdsetup-obj = drbdsetup.o drbdtool_common.o ../drbd/drbd_buildtag.o \
 	        ../drbd/drbd_strings.o
 
-drbdmeta-obj = drbdmeta.o drbdtool_common.o ../drbd/drbd_buildtag.o
+drbdmeta-obj = drbdmeta.o drbdmeta_scanner.o drbdtool_common.o ../drbd/drbd_buildtag.o
 
 all: drbdsetup drbdadm drbdmeta
 
@@ -36,6 +36,9 @@
 drbdadm_scanner.c: drbdadm_scanner.fl drbdadm_parser.h
 	flex -s -odrbdadm_scanner.c drbdadm_scanner.fl
 
+drbdmeta_scanner.c: drbdmeta_scanner.fl drbdmeta_parser.h
+	flex -odrbdmeta_scanner.c drbdmeta_scanner.fl
+
 # for debug:	flex -d -s -odrbdadm_scanner.c drbdadm_scanner.fl
 
 drbdadm_parser.h: drbdadm_parser.y

Modified: trunk/user/drbdmeta.c
===================================================================
--- trunk/user/drbdmeta.c	2005-04-21 10:16:23 UTC (rev 1782)
+++ trunk/user/drbdmeta.c	2005-04-21 10:18:53 UTC (rev 1783)
@@ -46,6 +46,10 @@
 #include "drbdtool_common.h"
 #include "drbd_endian.h"
 
+#include "drbdmeta_parser.h"
+extern FILE* yyin;
+YYSTYPE yylval;
+
 /* FIXME? should use sector_t and off_t, not long/u64 ... */
 /* FIXME? rename open -> mmap, close -> munmap */
 
@@ -543,6 +547,7 @@
 int meta_get_gi(struct format *cfg, char **argv, int argc);
 int meta_show_gi(struct format *cfg, char **argv, int argc);
 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);
@@ -552,6 +557,7 @@
 	{"get-gi", 0, meta_get_gi, 1},
 	{"show-gi", 0, meta_show_gi, 1},
 	{"dump-md", 0, meta_dump_md, 1},
+	{"restore-md", "file", meta_restore_md, 1},
 	{"create-md", 0, meta_create_md, 1},
 	/* FIXME convert still missing.
 	 * implicit convert from v07 to v08 by create-md
@@ -613,12 +619,6 @@
 	return size64;
 }
 
-#if BITS_PER_LONG == 32
-# define FMT " 0x%016llX;"
-#else
-# define FMT " 0x%016lX;"
-#endif
-
 /* le_u64, because we want to be able to hexdump it reliably
  * regardless of sizeof(long) */
 void printf_bm(const le_u64 * bm, const unsigned int n)
@@ -632,28 +632,11 @@
 			else
 				printf("\n   ");
 		}
-		printf(FMT, le64_to_cpu(bm[i].le));
+		printf(" 0x"X64(016)";", le64_to_cpu(bm[i].le));
 	}
 	printf("\n}\n");
 }
 
-#undef FMT
-
-
-int get_real_random(void * p, int size)
-{
-	int fd,rv;
-
-	fd = open("/dev/random", O_RDONLY);
-	if(fd == -1) {
-		PERROR("open('/dev/random',O_RDONLY)");
-		exit(20);
-	}
-	rv = size == read(fd,p,size);
-	close(fd);
-	return rv;
-}
-
 u64 new_style_offset(struct format * cfg)
 {
 	u64 offset;
@@ -1314,10 +1297,7 @@
 	if (cfg->ops->open(cfg))
 		return -1;
 
-	/* FIXME invent some sceme to identify this dump,
-	 * so we can safely restore it later */
-	printf("DRBD meta data dump version <FIXME drbdmeta dump version>\n");
-	printf("meta data version %s\n\n", cfg->ops->name);
+	printf("version \"%s\";\n\n", cfg->ops->name);
 	if (cfg->ops < f_ops + Drbd_08) {
 		printf("gc {");
 		for (i = 0; i < GEN_CNT_SIZE; i++) {
@@ -1347,8 +1327,81 @@
 	return cfg->ops->close(cfg);
 }
 
+void md_parse_error(const char *etext)
+{
+	fprintf(stderr,"Parse error '%s' expected.",etext);
+	exit(10);
+}
+
+#define EXP(TOKEN) if(yylex() != TOKEN) md_parse_error( #TOKEN );
+
+int meta_restore_md(struct format *cfg, char **argv, int argc)
+{
+	int i;
+	le_u64 *bm;
+
+	if (argc > 0) {
+		yyin = fopen(argv[0],"r");
+		if(yyin == NULL) {
+			fprintf(stderr, "open of '%s' failed.\n",argv[0]);
+			exit(20);
+		}
+	}
+
+	if (!cfg->ops->open(cfg)) {
+		if (!confirmed("Valid meta-data in place, overwrite?"))
+			return -1;
+	}
+
+	EXP(TK_VERSION); EXP(TK_STRING);
+	if(strcmp(yylval.txt,cfg->ops->name)) {
+		fprintf(stderr,"dump is '%s' you requested '%s'.\n",
+			yylval.txt,cfg->ops->name);
+		exit(10);
+	}
+	EXP(';');
+	if (cfg->ops < f_ops + Drbd_08) {
+		EXP(TK_GC); EXP('{');
+		for (i = 0; i < GEN_CNT_SIZE; i++) {
+			EXP(TK_U64); EXP(';');
+			cfg->md.gc[i] = yylval.u64;
+		}
+		EXP('}');
+	} else { // >? 08
+		EXP(TK_UUID); EXP('{');
+		for ( i=Current ; i<UUID_SIZE ; i++ ) {
+			EXP(TK_U64); EXP(';');
+			cfg->md.uuid[i] = yylval.u64;
+		}
+		EXP('}');
+	}
+	EXP(TK_LA_SIZE); EXP(TK_NUM); EXP(';');
+	cfg->md.la_sect = yylval.u64;
+	EXP(TK_BM); EXP('{');
+	bm = (le_u64 *)cfg->on_disk.bm;
+	i = 0;
+	while(yylex() == TK_U64) {
+		bm[i].le = cpu_to_le64(yylval.u64);
+		i++;
+		EXP(';');
+	}
+
+	if (cfg->ops->md_cpu_to_disk(cfg)
+	    || cfg->ops->close(cfg)) {
+		fprintf(stderr, "Writing failed\n");
+		return -1;
+	}
+
+	printf("Successfully restored meta data\n");
+
+	return 0;
+}
+
+#undef EXP
+
 int md_convert_07_to_08(struct format *cfg)
 {
+	int i,j=1;
 	/* Note that al and bm are not touched!
 	 * (they are currently not even mmaped)
 	 *
@@ -1356,15 +1409,31 @@
 	 * We only need to adjust the magic here. */
 	printf("Converting meta data...\n");
 	cfg->md.magic = DRBD_MD_MAGIC_08;
-	// get_real_random(&cfg->md.uuid,sizeof(u64));
-	// cfg->md.peer_uuid = 0;
+
+	// The MDF Flags are the same in 07 and 08
+	cfg->md.flags = cfg->md.gc[Flags];
+	/* 
+	 */
+	cfg->md.uuid[Current] = 
+		(u64)(cfg->md.gc[HumanCnt] & 0xffff) << 48 |
+		(u64)(cfg->md.gc[TimeoutCnt] & 0xffff) << 32 |
+		(u64)((cfg->md.gc[ConnectedCnt]+cfg->md.gc[ArbitraryCnt])
+		       & 0xffff) << 16 |
+		(u64)0xbabe;
+	cfg->md.uuid[Bitmap] = (u64)0;
+	if (cfg->bits_set) i = Bitmap;
+	else i = History_start;
+	for ( ; i<=History_end ; i++ ) {
+		cfg->md.uuid[i] = cfg->md.uuid[Current] - j*0x10000;
+		j++;
+	}
+
 	if (cfg->ops->md_cpu_to_disk(cfg)
 	    || cfg->ops->close(cfg)) {
 		fprintf(stderr, "conversion failed\n");
 		return -1;
 	}
-	printf("Convertion Currently BROKEN!\n");
-	//printf("Successfully converted v07 meta data to v08 format.\n");
+	printf("Successfully converted v07 meta data to v08 format.\n");
 	return 0;
 }
 

Added: trunk/user/drbdmeta_parser.h
===================================================================
--- trunk/user/drbdmeta_parser.h	2005-04-21 10:16:23 UTC (rev 1782)
+++ trunk/user/drbdmeta_parser.h	2005-04-21 10:18:53 UTC (rev 1783)
@@ -0,0 +1,21 @@
+typedef union YYSTYPE {
+  char* txt;
+  u64   u64;
+} YYSTYPE;
+
+#define YYSTYPE_IS_DECLARED 1
+#define YYSTYPE_IS_TRIVIAL 1
+
+extern YYSTYPE yylval;
+
+enum yytokentype {
+	TK_STRING = 258,
+	TK_U64,
+	TK_NUM,
+	TK_GC,
+	TK_BM,
+	TK_UUID,
+	TK_VERSION,
+	TK_LA_SIZE
+};
+

Added: trunk/user/drbdmeta_scanner.fl
===================================================================
--- trunk/user/drbdmeta_scanner.fl	2005-04-21 10:16:23 UTC (rev 1782)
+++ trunk/user/drbdmeta_scanner.fl	2005-04-21 10:18:53 UTC (rev 1783)
@@ -0,0 +1,53 @@
+%{
+
+#include "drbd_endian.h"
+#include "drbdmeta_parser.h"
+
+static void unescape(void);
+
+//#define DP printf("%s ",yytext);
+#define DP
+
+%}
+
+%option noyywrap
+
+WS		[ \t\n]
+COMMENT		\#[^\n]*
+NUM		[0-9]{1,9}
+U64		0x[0-9A-Fa-f]{16}
+OP		[{};]
+STRING		\"[^\"]*\"
+
+%%
+
+{WS}
+{COMMENT}
+{OP}		DP; return yytext[0];
+{STRING}	unescape(); yylval.txt=yytext; DP; return TK_STRING; 
+{U64}		yylval.u64 = strto_u64(yytext, NULL, 16); DP; return TK_U64;
+{NUM}		yylval.u64 = strto_u64(yytext, NULL, 10); DP; return TK_NUM;
+gc		DP; return TK_GC;
+bm		DP; return TK_BM;
+uuid		DP; return TK_UUID;
+version		DP; return TK_VERSION;
+la-size-sect	DP; return TK_LA_SIZE;
+
+%%
+
+static void unescape(void)
+{
+  /* backslash escapes from string */
+  char *ue, *e;
+  e = ue = yytext;
+  for (;;) {
+    if (*ue == '"')
+      ue++;
+    if (*ue == '\\')
+      ue++;
+    if (!*ue)
+      break;
+    *e++ = *ue++;
+  }
+  *e = '\0';
+}

Modified: trunk/user/drbdtool_common.c
===================================================================
--- trunk/user/drbdtool_common.c	2005-04-21 10:16:23 UTC (rev 1782)
+++ trunk/user/drbdtool_common.c	2005-04-21 10:18:53 UTC (rev 1783)
@@ -225,7 +225,7 @@
 	
 	dev_major = 147; //LANANA_DRBD_MAJOR;
 
-	if( stat(device, &drbd_stat) ) {
+	if( !stat(device, &drbd_stat) ) {
 
 		if(!S_ISBLK(drbd_stat.st_mode)) {
 			fprintf(stderr, "%s is not a block device!\n", device);
@@ -353,6 +353,6 @@
 "                             -<  Data was/is currently up-to-date  >--+ | | |\n"
 "                                  -<  Node was/is currently primary  >--+ | |\n"
 "                                  -<  Node was/is currently connected  >--+ |\n"
-"          -<  Node was in to progress of setting all bits in the bitmap  >--+\n"
+"         -<  Node was in the progress of setting all bits in the bitmap  >--+\n"
 "\n");
 }

From www-data at garcon.linbit.com  Thu Apr 21 17:46:53 2005
From: www-data at garcon.linbit.com (www-data)
Date: Thu Apr 21 17:46:59 2005
Subject: [DRBD-cvs] r1784 - in trunk/testing: . nfs-cross-mount
Message-ID: <20050421154653.0BCD215D29@mail.linbit.com>

Author: phil
Date: 2005-04-21 17:46:52 +0200 (Thu, 21 Apr 2005)
New Revision: 1784

Added:
   trunk/testing/nfs-cross-mount/
   trunk/testing/nfs-cross-mount/nfs-mount
   trunk/testing/nfs-cross-mount/nfs-mount-client
   trunk/testing/nfs-cross-mount/nfs-umount
Log:
Scripts to "cross" mount a filesystem to the standby-node
by nfs. Consider them as a rudimentary proof-of-concept hack.


Added: trunk/testing/nfs-cross-mount/nfs-mount
===================================================================
--- trunk/testing/nfs-cross-mount/nfs-mount	2005-04-21 10:18:53 UTC (rev 1783)
+++ trunk/testing/nfs-cross-mount/nfs-mount	2005-04-21 15:46:52 UTC (rev 1784)
@@ -0,0 +1,31 @@
+#!/bin/sh
+read cmd
+
+if [ $(uname -n) = 'curry' ]
+then
+  peer=wurst-i
+elif [ $(uname -n) = 'wurst' ]
+then
+  peer=curry-i
+else
+  echo "Fehler: Weder Host noch Peer bekannt." && exit 1
+fi
+
+if [ "$cmd" = 'start' ]
+then
+  if ! mount | grep -e " on /data/partner " >/dev/null
+  then
+    mount -o rsize=8192,wsize=8192,soft $peer:/data/partner /data/partner
+  fi
+elif [ "$cmd" = 'stop' ]
+then
+  # See if the device is currently mounted
+  if mount -t nfs | grep -e " on /data/partner " >/dev/null
+  then
+          # Kill all processes open on filesystem
+          fuser -mk /data/partner
+
+          # Unmount the filesystem
+          umount -f /data/partner
+  fi
+fi

Added: trunk/testing/nfs-cross-mount/nfs-mount-client
===================================================================
--- trunk/testing/nfs-cross-mount/nfs-mount-client	2005-04-21 10:18:53 UTC (rev 1783)
+++ trunk/testing/nfs-cross-mount/nfs-mount-client	2005-04-21 15:46:52 UTC (rev 1784)
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+if [ $(uname -n) = 'curry' ]
+then
+  peer=wurst-i
+elif [ $(uname -n) = 'wurst' ]
+then
+  peer=curry-i
+else
+  echo "Fehler: Weder Host noch Peer bekannt." && exit 1
+fi
+
+echo "$1"|ssh -i ~/.ssh/id_dsa_nfs-mount $peer

Added: trunk/testing/nfs-cross-mount/nfs-umount
===================================================================
--- trunk/testing/nfs-cross-mount/nfs-umount	2005-04-21 10:18:53 UTC (rev 1783)
+++ trunk/testing/nfs-cross-mount/nfs-umount	2005-04-21 15:46:52 UTC (rev 1784)
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+case "$1" in
+	start)
+        # See if the device is currently mounted
+        if
+          mount -t nfs | grep -e " on /data/partner " >/dev/null
+        then
+                # Kill all processes open on filesystem
+                fuser -mk /data/partner
+
+                # Unmount the filesystem
+                umount -f /data/partner
+	fi
+	;;
+	stop)
+	;;
+esac
+
+exit 0

From www-data at garcon.linbit.com  Thu Apr 21 23:54:02 2005
From: www-data at garcon.linbit.com (www-data)
Date: Thu Apr 21 23:54:04 2005
Subject: [DRBD-cvs] r1785 - in trunk: drbd drbd/linux user
Message-ID: <20050421215402.69445157A1@mail.linbit.com>

Author: lars
Date: 2005-04-21 23:53:53 +0200 (Thu, 21 Apr 2005)
New Revision: 1785

Modified:
   trunk/drbd/drbd_bitmap.c
   trunk/drbd/drbd_compat_wrappers.h
   trunk/drbd/drbd_fs.c
   trunk/drbd/drbd_int.h
   trunk/drbd/drbd_main.c
   trunk/drbd/linux/drbd.h
   trunk/user/drbd_endian.h
   trunk/user/drbdmeta.c
   trunk/user/drbdmeta_parser.h
   trunk/user/drbdtool_common.h
Log:
* fix drbd_md_read error return codes
  make it fail if there is no valid meta data block
  (you _have_ to use drbdmeta now)

* move enum MetaDataIndex into user/drbdtool_common.h,
  it is only needed to read/convert v06 and v07 meta data blocks in user space

* remove stale comment blocks

* added 16bit endian conversion (needed for xfs size detection)

* v08 al/bm offsets are signed (we may want to place the meta data block last,
  so it is easier to find when we have variable size meta data.
  al/bm byte offsets are part of the cfg struct now

* drbdmeta can refuse to operate now,
  if it detects existing data on the lower level device.
  see check_for_exiting_data and meta_create_md

* fix order of memset arguments in drbdmeta

* quieten bitmap code in case of out of memory condition

  * cannot allocate bitmap => la_size = 0
    still to do: should probably stay diskless in case it was connected.

  * cannot REallocate bitmap => la_size keeps the same as before.
     still a problem: actual size may now be smaller!
     what now??

  behaviour was tested with an explicit
     nmb = NULL; /* vmalloc(bytes); */,
  so it would fail always, and it turned out to be of size 0.  (single machine
  only).  behaviour NOT tested with connected devices (no test cluster available)

  it still does not fail the ioctl, so it might go unnoticed at first.
  anyways, it is a slight improvement to the existing code.

  but maybe we really want to fix the device setup procedure
  and do the right thing: fail the ioctl.


Modified: trunk/drbd/drbd_bitmap.c
===================================================================
--- trunk/drbd/drbd_bitmap.c	2005-04-21 15:46:52 UTC (rev 1784)
+++ trunk/drbd/drbd_bitmap.c	2005-04-21 21:53:53 UTC (rev 1785)
@@ -235,6 +235,12 @@
 	return 0;
 }
 
+sector_t drbd_bm_capacity(drbd_dev *mdev)
+{
+	ERR_IF(!mdev->bitmap) return 0;
+	return mdev->bitmap->bm_dev_capacity;
+}
+
 /* called on driver unload. TODO: call when a device is destroyed.
  */
 void drbd_bm_cleanup(drbd_dev *mdev)
@@ -270,7 +276,7 @@
 		cleared += hweight_long(b->bm[w]);
 		b->bm[w++]=0;
 	}
-	
+
 	return cleared;
 }
 
@@ -368,6 +374,7 @@
 			bytes = (words+1)*sizeof(long);
 			nbm = vmalloc(bytes);
 			if (!nbm) {
+				ERR("bitmap: failed to vmalloc %lu bytes\n",bytes);
 				err = -ENOMEM;
 				goto out;
 			}
@@ -375,6 +382,7 @@
 		spin_lock_irq(&b->bm_lock);
 		obm = b->bm;
 		// brgs. move several MB within spinlock...
+		// FIXME this should go into userspace!
 		if (obm) {
 			bm_set_surplus(b);
 			D_ASSERT(b->bm[b->bm_words] == DRBD_MAGIC);
@@ -382,8 +390,9 @@
 		}
 		growing = words > b->bm_words;
 		if (growing) { // set all newly allocated bits
-			memset( nbm+b->bm_words, -1,
-				(words - b->bm_words) * sizeof(long) );
+			// start at -1, just to be sure.
+			memset( nbm + (b->bm_words?:1)-1 , 0xff,
+				(words - ((b->bm_words?:1)-1)) * sizeof(long) );
 			b->bm_set  += bits - b->bm_bits;
 		}
 		nbm[words] = DRBD_MAGIC;
@@ -418,7 +427,9 @@
 	unsigned long s;
 	unsigned long flags;
 
-	D_BUG_ON(!(b && b->bm));
+	D_BUG_ON(!b);
+	if (b->bm_bits == 0) return 0;
+	D_BUG_ON(!b->bm);
 	// MUST_BE_LOCKED(); well. yes. but ...
 
 	spin_lock_irqsave(&b->bm_lock,flags);
@@ -431,7 +442,9 @@
 size_t drbd_bm_words(drbd_dev *mdev)
 {
 	struct drbd_bitmap *b = mdev->bitmap;
-	D_BUG_ON(!(b && b->bm));
+	D_BUG_ON(!b);
+	if (b->bm_words == 0) return 0;
+	D_BUG_ON(!b->bm);
 
 	/* FIXME
 	 * actually yes. really. otherwise it could just change its size ...
@@ -453,6 +466,7 @@
 	unsigned long word, bits;
 	size_t n = number;
 
+	if (number == 0) return;
 	D_BUG_ON(!(b && b->bm));
 	D_BUG_ON(offset        >= b->bm_words);
 	D_BUG_ON(offset+number >  b->bm_words);
@@ -492,6 +506,7 @@
 	unsigned long word, bits;
 	size_t n = number;
 
+	if (number == 0) return;
 	D_BUG_ON(!(b && b->bm));
 	D_BUG_ON(offset        >= b->bm_words);
 	D_BUG_ON(offset+number >  b->bm_words);
@@ -529,6 +544,7 @@
 	struct drbd_bitmap *b = mdev->bitmap;
 	unsigned long *bm;
 
+	if (number == 0) return;
 	D_BUG_ON(!(b && b->bm));
 	if ( (offset        >= b->bm_words) ||
 	     (offset+number >  b->bm_words) ||
@@ -555,13 +571,16 @@
 void drbd_bm_set_all(drbd_dev *mdev)
 {
 	struct drbd_bitmap *b = mdev->bitmap;
-	D_BUG_ON(!(b && b->bm));
 
+	D_BUG_ON(!b);
+	if (b->bm_bits == 0) return;
+	D_BUG_ON(!b->bm);
+
 	MUST_BE_LOCKED();
 
 	spin_lock_irq(&b->bm_lock);
 	BM_PARANOIA_CHECK();
-	memset(b->bm,-1,b->bm_words*sizeof(long));
+	memset(b->bm,0xff,b->bm_words*sizeof(long));
 	bm_clear_surplus(b);
 	b->bm_set = b->bm_bits;
 	spin_unlock_irq(&b->bm_lock);
@@ -699,8 +718,11 @@
 void drbd_bm_clear_all(drbd_dev *mdev)
 {
 	struct drbd_bitmap *b = mdev->bitmap;
-	D_BUG_ON(!(b && b->bm));
 
+	D_BUG_ON(!b);
+	if (b->bm_bits == 0) return;
+	D_BUG_ON(!b->bm);
+
 	MUST_BE_LOCKED();						\
 
 	spin_lock_irq(&b->bm_lock);
@@ -713,8 +735,9 @@
 void drbd_bm_reset_find(drbd_dev *mdev)
 {
 	struct drbd_bitmap *b = mdev->bitmap;
-	D_BUG_ON(!(b && b->bm));
 
+	D_BUG_ON(!b);
+
 	MUST_BE_LOCKED();
 
 	spin_lock_irq(&b->bm_lock);
@@ -733,8 +756,12 @@
 {
 	struct drbd_bitmap *b = mdev->bitmap;
 	unsigned long i = -1UL;
-	D_BUG_ON(!(b && b->bm));
 
+
+	D_BUG_ON(!b);
+	if (b->bm_bits == 0) return i;
+	D_BUG_ON(!b->bm);
+
 	spin_lock_irq(&b->bm_lock);
 	BM_PARANOIA_CHECK();
 	if (b->bm_fo < b->bm_bits) {

Modified: trunk/drbd/drbd_compat_wrappers.h
===================================================================
--- trunk/drbd/drbd_compat_wrappers.h	2005-04-21 15:46:52 UTC (rev 1784)
+++ trunk/drbd/drbd_compat_wrappers.h	2005-04-21 21:53:53 UTC (rev 1785)
@@ -28,7 +28,10 @@
 /* Returns the number of 512 byte sectors of the device */
 static inline sector_t drbd_get_capacity(struct block_device *bdev)
 {
-	return bdev ? bdev->bd_inode->i_size >> 9 : 0;
+	loff_t capacity = bdev ? bdev->bd_inode->i_size >> 9 : 0;
+	if ((sector_t)capacity != capacity)
+		printk(KERN_ERR "drbd: overflow in drbd_get_capacity\n");
+	return (sector_t)capacity;
 }
 
 /* sets the number of 512 byte sectors of our virtual device */

Modified: trunk/drbd/drbd_fs.c
===================================================================
--- trunk/drbd/drbd_fs.c	2005-04-21 15:46:52 UTC (rev 1784)
+++ trunk/drbd/drbd_fs.c	2005-04-21 21:53:53 UTC (rev 1785)
@@ -71,7 +71,7 @@
 char* ppsize(char* buf, size_t size) 
 {
 	// Needs 9 bytes at max.
-	static char units[] = { 'K','M','G','T' };
+	static char units[] = { 'K','M','G','T','P','E' };
 	int base = 0;
 	while (size >= 10000 ) {
 		size = size >> 10;
@@ -144,16 +144,23 @@
 		int err;
 		err = drbd_bm_resize(mdev,size);
 		if (unlikely(err)) {
-			ERR("BM resizing failed. "
-			    "Size unchanged = %s (%lu sect)\n", 
-			    ppsize(ppb,size>>1),(unsigned long)size);
-		} else {
-			// racy, see comments above.
-			drbd_set_my_capacity(mdev,size);
-			mdev->la_size = size;
-			INFO("size = %s (%lu sect)\n",ppsize(ppb,size>>1),
-			     (unsigned long)size);
+			/* currently there is only one error: ENOMEM! */
+			size = drbd_bm_capacity(mdev)>>1;
+			if (size == 0) {
+				ERR("Could not allocate bitmap! Set device size => 0\n");
+			} else {
+				/* FIXME this is problematic,
+				 * if we in fact are smaller now! */
+				ERR("BM resizing failed. "
+				    "Leaving size unchanged at size = %lu KB\n", 
+				    (unsigned long)size);
+			}
 		}
+		// racy, see comments above.
+		drbd_set_my_capacity(mdev,size<<1);
+		mdev->la_size = size;
+		INFO("size = %s (%lu KB)\n",ppsize(ppb,size),
+		     (unsigned long)size);
 	}
 
 	return rv;
@@ -345,6 +352,8 @@
 	}
 
 	if ((drbd_get_capacity(bdev)>>1) < new_conf.disk_size) {
+		/* FIXME maybe still allow,
+		 * but leave only DRBD_MAX_SECTORS usable */
 		retcode = LDDeviceTooSmall;
 		goto release_bdev2_fail_ioctl;
 	}
@@ -398,15 +407,16 @@
 
 	md_gc_valid = drbd_md_read(mdev);
 
-	if (md_gc_valid == -1 ) {
-		retcode = MDIOError;
+	if (md_gc_valid != NoError) {
+		retcode = md_gc_valid;
 		goto unset_fail_ioctl;
 	}
 
-	if (md_gc_valid == -2 ) {
-		retcode = MDInvalid;
-		goto unset_fail_ioctl;
-	}
+	/* We reach this only if we have a valid meta data block,
+	 * so we no longer create one here, if we don't find one.
+	 * That means that initially, you HAVE to use the drbdmeta
+	 * command to create one in user space.
+	 */
 
 	drbd_bm_lock(mdev); // racy...
 	drbd_determin_dev_size(mdev);
@@ -414,13 +424,13 @@
 	 * what if we now have la_size == 0 ?? eh?
 	 */
 
-	if (md_gc_valid <= 0) {
+	if (drbd_md_test_flag(mdev,MDF_FullSync)) {
 		INFO("Assuming that all blocks are out of sync (aka FullSync)\n");
 		drbd_bm_set_all(mdev);
 		drbd_bm_write(mdev);
 		drbd_md_clear_flag(mdev,MDF_FullSync);
 		drbd_md_write(mdev);
-	} else { // md_gc_valid > 0
+	} else {
 		/* FIXME this still does not propagate io errors! */
 		drbd_bm_read(mdev);
 	}

Modified: trunk/drbd/drbd_int.h
===================================================================
--- trunk/drbd/drbd_int.h	2005-04-21 15:46:52 UTC (rev 1784)
+++ trunk/drbd/drbd_int.h	2005-04-21 21:53:53 UTC (rev 1785)
@@ -556,16 +556,6 @@
 	drbd_work_cb cb;
 };
 
-/*
- * since we eventually don't want to "remap" any bhs, but allways need a
- * private bh, it may as well be part of the struct so we do not need to
- * allocate it separately.  it is only used as a clone, and since we own it, we
- * can abuse certain fields of if for our own needs.  and, since it is part of
- * the struct, we can use b_private for other things than the req, e.g. mdev,
- * since we get the request struct by means of the "container_of()" macro.
- *	-lge
- */
-
 struct drbd_barrier;
 struct drbd_request {
 	struct drbd_work w;
@@ -968,6 +958,7 @@
 extern void drbd_bm_write     (drbd_dev *mdev);
 extern unsigned long drbd_bm_ALe_set_all (drbd_dev *mdev, unsigned long al_enr);
 extern size_t        drbd_bm_words       (drbd_dev *mdev);
+extern sector_t      drbd_bm_capacity    (drbd_dev *mdev);
 extern unsigned long drbd_bm_find_next   (drbd_dev *mdev);
 extern unsigned long drbd_bm_total_weight(drbd_dev *mdev);
 extern int drbd_bm_rs_done(drbd_dev *mdev);
@@ -1485,7 +1476,7 @@
 
 static inline void drbd_suicide(void)
 {
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
+#ifdef TASK_ZOMBIE
 	set_current_state(TASK_ZOMBIE);
 #else
 	current->exit_state = EXIT_ZOMBIE;

Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c	2005-04-21 15:46:52 UTC (rev 1784)
+++ trunk/drbd/drbd_main.c	2005-04-21 21:53:53 UTC (rev 1785)
@@ -1105,7 +1105,16 @@
 	p.sector   = cpu_to_be64(drbd_ee_get_sector(e));
 	p.block_id = e->block_id;
 	p.blksize  = cpu_to_be32(drbd_ee_get_size(e));
+/*
+ * FIXME kernel source <= 2.6.8 don't have atomic_add_return!
+ */
+#if 0
+#warning "YES I KNOW. JUST SO IT COMPILES NOW."
+	atomic_inc(&mdev->packet_seq);
+	p.seq_num = atomic_read(&mdev->packet_seq);
+#else
 	p.seq_num  = cpu_to_be32(atomic_add_return(1,&mdev->packet_seq));
+#endif
 
 	if (!mdev->meta.socket || mdev->state.s.conn < Connected) return FALSE;
 	ok=drbd_send_cmd(mdev,mdev->meta.socket,cmd,(Drbd_Header*)&p,sizeof(p));
@@ -1335,8 +1344,14 @@
 
 		p.sector   = cpu_to_be64(drbd_req_get_sector(req));
 		p.block_id = (unsigned long)req;
+#if 0
+#warning "YES I KNOW. JUST SO IT COMPILES NOW."
+		atomic_inc(&mdev->packet_seq);
+		p.seq_num = atomic_read(&mdev->packet_seq);
+#else
 		p.seq_num  = cpu_to_be32( req->seq_num =
 				     atomic_add_return(1,&mdev->packet_seq) );
+#endif
 
 		dump_packet(mdev,mdev->data.socket,0,(void*)&p, __FILE__, __LINE__);
 		set_bit(UNPLUG_REMOTE,&mdev->flags);
@@ -2289,21 +2304,20 @@
 
 /*
  * return:
- *   < 0 if we had an error 
- *       -1  no meta data IO allowed
- *       -2  magic number not present
- *   = 0 if we need a FullSync because either the flag is set,
- *       or the gen counts are invalid
- *   > 0 if we could read valid gen counts,
+ *   = 0 if we could read valid gen counts,
  *       and reading the bitmap and act log does make sense.
+ *  != 0 if we had an error
+ *       MDIOError no meta data IO allowed
+ *       MDIOError IO not possible
+ *       MDInvalid no correct magic present
  */
 int drbd_md_read(drbd_dev *mdev)
 {
 	struct meta_data_on_disk * buffer;
 	sector_t sector;
-	int i,rv;
+	int i,rv = NoError;
 
-	if(!inc_local_md_only(mdev)) return -1;
+	if(!inc_local_md_only(mdev)) return MDIOError;
 
 	down(&mdev->md_io_mutex);
 	buffer = (struct meta_data_on_disk *)page_address(mdev->md_io_page);
@@ -2327,11 +2341,6 @@
 	if (mdev->sync_conf.al_extents < 7)
 		mdev->sync_conf.al_extents = 127;
 
-	up(&mdev->md_io_mutex);
-	dec_local(mdev);
-
-	return !drbd_md_test_flag(mdev,MDF_FullSync);
-
  err:
 	up(&mdev->md_io_mutex);
 	dec_local(mdev);
@@ -2341,7 +2350,6 @@
 
 
 
-
 static void drbd_uuid_move_history(drbd_dev *mdev)
 {
 	int i;

Modified: trunk/drbd/linux/drbd.h
===================================================================
--- trunk/drbd/linux/drbd.h	2005-04-21 15:46:52 UTC (rev 1784)
+++ trunk/drbd/linux/drbd.h	2005-04-21 21:53:53 UTC (rev 1785)
@@ -273,16 +273,6 @@
 #define MDF_FullSync        (1<<__MDF_FullSync)
 #define MDF_WasUpToDate     (1<<__MDF_WasUpToDate)
 
-/* MetaDataIndex is scheduled for removal! */
-enum MetaDataIndex {
-	Flags,			/* Consistency flag,connected-ind,primary-ind */
-	HumanCnt,		/* human-intervention-count */
-	TimeoutCnt,		/* timout-count */
-	ConnectedCnt,		/* connected-count */
-	ArbitraryCnt,		/* arbitrary-count */
-	GEN_CNT_SIZE		/* MUST BE LAST! (and Flags must stay first...) */
-};
-
 enum UuidIndex {
 	Current,
 	Bitmap,

Modified: trunk/user/drbd_endian.h
===================================================================
--- trunk/user/drbd_endian.h	2005-04-21 15:46:52 UTC (rev 1784)
+++ trunk/user/drbd_endian.h	2005-04-21 21:53:53 UTC (rev 1785)
@@ -20,8 +20,11 @@
 
 #define u64 uint64_t
 #define u32 uint32_t
+#define s32 int32_t
+#define u16 uint16_t
 #define __u64 uint64_t
 #define __u32 uint32_t
+#define __u16 uint16_t
 
 /* linux/byteorder/swab.h */
 
@@ -34,6 +37,14 @@
  * oh, well...
  */
 
+#define __swab16(x) \
+({ \
+	__u16 __x = (x); \
+	((__u16)( \
+		(((__u16)(__x) & (__u16)0x00ffUL) << 8) | \
+		(((__u16)(__x) & (__u16)0xff00UL) >> 8) )); \
+})
+
 #define __swab32(x) \
 ({ \
 	__u32 __x = (x); \
@@ -74,19 +85,27 @@
 #define le64_to_cpu(x) ((__u64)(x))
 #define cpu_to_le32(x) ((__u32)(x))
 #define le32_to_cpu(x) ((__u32)(x))
+#define cpu_to_le16(x) ((__u16)(x))
+#define le16_to_cpu(x) ((__u16)(x))
 #define cpu_to_be64(x) __swab64((x))
 #define be64_to_cpu(x) __swab64((x))
 #define cpu_to_be32(x) __swab32((x))
 #define be32_to_cpu(x) __swab32((x))
+#define cpu_to_be16(x) __swab16((x))
+#define be16_to_cpu(x) __swab16((x))
 #elif __BYTE_ORDER == __BIG_ENDIAN
 # define cpu_to_le64(x) __swab64((x))
 # define le64_to_cpu(x) __swab64((x))
 # define cpu_to_le32(x) __swab32((x))
 # define le32_to_cpu(x) __swab32((x))
+# define cpu_to_le16(x) __swab16((x))
+# define le16_to_cpu(x) __swab16((x))
 # define cpu_to_be64(x) ((__u64)(x))
 # define be64_to_cpu(x) ((__u64)(x))
 # define cpu_to_be32(x) ((__u32)(x))
 # define be32_to_cpu(x) ((__u32)(x))
+# define cpu_to_be16(x) ((__u16)(x))
+# define be16_to_cpu(x) ((__u16)(x))
 #else
 # error "sorry, weird endianness on this box"
 #endif

Modified: trunk/user/drbdmeta.c
===================================================================
--- trunk/user/drbdmeta.c	2005-04-21 15:46:52 UTC (rev 1784)
+++ trunk/user/drbdmeta.c	2005-04-21 21:53:53 UTC (rev 1785)
@@ -64,6 +64,46 @@
  */
 
 /*
+ * FIXME
+ *
+ * when configuring a drbd device:
+ *
+ * Require valid drbd meta data at the respective location.  A meta data
+ * block would only be created by the drbdmeta command.
+ *
+ * (How) do we want to implement this: A meta data block contains some
+ * reference to the physical device it belongs. Refuse to attach not
+ * corresponding meta data.
+ *
+ * THINK: put a checksum within the on-disk meta data block, too?
+ *
+ * When asked to create a new meta data block, the drbdmeta command
+ * warns loudly if either the data device or the meta data device seem
+ * to contain some data, and requires explicit confirmation anyways.
+ *
+ * See current implementation in check_for_exiting_data below.
+ *
+ * XXX should also be done for meta-data != internal, i.e.  refuse to
+ * create meta data blocks on a device that seems to be in use for
+ * something else.
+ *
+ * Maybe with an external meta data device, we want to require a "meta
+ * data device super block", which could also serve as TOC to the meta
+ * data, once we have variable size meta data.  Other option could be a
+ * /var/lib/drbd/md-toc plain file, and some magic block on every device
+ * that serves as md storage.
+ *
+ * For certain content on the lower level device, we should refuse
+ * allways.  e.g. refuse to be created on top of a LVM2 physical volume,
+ * or on top of swap space. This would require people to do an dd
+ * if=/dev/zero of=device.  Protects them from shooting themselves,
+ * and blaming us...
+ */
+
+/* reiserfs sb offset is 64k plus */
+#define HOW_MUCH (65*1024)
+
+/*
  * I think this block of declarations and definitions should be
  * in some common.h, too.
  * {
@@ -76,8 +116,8 @@
 #define MD_AL_OFFSET_07    8
 #define MD_AL_MAX_SIZE_07  64
 #define MD_BM_OFFSET_07    (MD_AL_OFFSET_07 + MD_AL_MAX_SIZE_07)
-#define MD_RESERVED_SIZE_07 ( (u64)128 * (1<<20) )
-#define MD_BM_MAX_SIZE_07  ( MD_RESERVED_SIZE_07 - MD_BM_OFFSET_07*512 )
+#define MD_RESERVED_SIZE_07 ( (u64)(128 * (1<<20)) )
+#define MD_BM_MAX_SIZE_07  ( (u64)(MD_RESERVED_SIZE_07 - MD_BM_OFFSET_07*512) )
 
 #define DRBD_MD_MAGIC_06   (DRBD_MAGIC+2)
 #define DRBD_MD_MAGIC_07   (DRBD_MAGIC+3)
@@ -127,6 +167,7 @@
 typedef struct { u64 be; } be_u64;
 typedef struct { u32 le; } le_u32;
 typedef struct { u32 be; } be_u32;
+typedef struct { s32 be; } be_s32;
 typedef struct { unsigned long le; } le_ulong;
 typedef struct { unsigned long be; } be_ulong;
 
@@ -142,9 +183,9 @@
 	 * we use sectors in our general working structure here */
 	u64 la_sect;		/* last agreed size. */
 	u32 md_size;
-	u32 al_offset;		/* offset to this block */
+	s32 al_offset;		/* signed sector offset to this block */
 	u32 al_nr_extents;	/* important for restoring the AL */
-	u32 bm_offset;		/* offset to the bitmap, from here */
+	s32 bm_offset;		/* signed sector offset to the bitmap, from here */
 	/* Since DRBD 0.8 we have uuid instead of gc */
 	u64 uuid[UUID_SIZE];
 	u32 flags;
@@ -168,6 +209,7 @@
 	int i;
 	u32 flags;
 
+	memset(cpu, 0, sizeof(*cpu));
 	for (i = 0; i < GEN_CNT_SIZE; i++)
 		cpu->gc[i] = be32_to_cpu(disk->gc[i].be);
 	cpu->magic = be32_to_cpu(disk->magic.be);
@@ -184,7 +226,7 @@
 	int i;
 	u32 flags;
 
-	/* Commulate the UpToDate flag into the consistent flag. */
+	/* clear Consistent flag if UpToDate is not set*/
 	flags = cpu->gc[Flags];
 	if(!((flags & MDF_Consistent) && (flags & MDF_WasUpToDate))) {
 		flags &= ~MDF_Consistent;
@@ -215,9 +257,9 @@
 	be_u32 gc[GEN_CNT_SIZE];	/* generation counter */
 	be_u32 magic;
 	be_u32 md_size;
-	be_u32 al_offset;	/* offset to this block */
+	be_s32 al_offset;	/* signed sector offset to this block */
 	be_u32 al_nr_extents;	/* important for restoring the AL */
-	be_u32 bm_offset;	/* offset to the bitmap, from here */
+	be_s32 bm_offset;	/* signed sector offset to the bitmap, from here */
 	char reserved[8 * 512 - 48];
 };
 
@@ -225,6 +267,8 @@
 {
 	int i;
 	u32 flags;
+
+	memset(cpu, 0, sizeof(*cpu));
 	cpu->la_sect = be64_to_cpu(disk->la_kb.be) << 1;
 	for (i = 0; i < GEN_CNT_SIZE; i++)
 		cpu->gc[i] = be32_to_cpu(disk->gc[i].be);
@@ -246,7 +290,7 @@
 	int i;
 	u32 flags;
 
-	/* Commulate the UpToDate flag into the consistent flag. */
+	/* clear Consistent flag if UpToDate is not set*/
 	flags = cpu->gc[Flags];
 	if(!((flags & MDF_Consistent) && (flags & MDF_WasUpToDate))) {
 		flags &= ~MDF_Consistent;
@@ -262,7 +306,7 @@
 	disk->al_offset.be = cpu_to_be32(cpu->al_offset);
 	disk->al_nr_extents.be = cpu_to_be32(cpu->al_nr_extents);
 	disk->bm_offset.be = cpu_to_be32(cpu->bm_offset);
-	memset(disk->reserved, sizeof(disk->reserved), 0);
+	memset(disk->reserved, 0, sizeof(disk->reserved));
 }
 
 int v07_validate_md(struct md_cpu *md)
@@ -317,8 +361,6 @@
 
 /*
  * -- DRBD 0.8 --------------------------------------
- *  even though they now differ only by la-size being kb or sectors,
- *  I expect them to diverge, so lets have different structures.
  */
 
 struct __attribute__ ((packed)) md_on_disk_08 {
@@ -327,15 +369,17 @@
 	be_u32 flags;
 	be_u32 magic;
 	be_u32 md_size;
-	be_u32 al_offset;	/* offset to this block */
+	be_s32 al_offset;	/* signed sector offset to this block */
 	be_u32 al_nr_extents;	/* important for restoring the AL */
-	be_u32 bm_offset;	/* offset to the bitmap, from here */
-	char reserved[8 * 512 - 56];
+	be_s32 bm_offset;	/* signed sector offset to the bitmap, from here */
+	char reserved[8 * 512 - (8*(UUID_SIZE+1)+4*6)];
 };
 
 void md_disk_08_to_cpu(struct md_cpu *cpu, const struct md_on_disk_08 *disk)
 {
 	int i;
+
+	memset(cpu, 0, sizeof(*cpu));
 	cpu->la_sect = be64_to_cpu(disk->la_sect.be);
 	for ( i=Current ; i<UUID_SIZE ; i++ )
 		cpu->uuid[i] = be64_to_cpu(disk->uuid[i].be);
@@ -351,15 +395,16 @@
 {
 	int i;
 	disk->la_sect.be = cpu_to_be64(cpu->la_sect);
-	for ( i=Current ; i<UUID_SIZE ; i++ )
+	for ( i=Current ; i<UUID_SIZE ; i++ ) {
 		disk->uuid[i].be = cpu_to_be64(cpu->uuid[i]);
+	}
 	disk->flags.be = cpu_to_be32(cpu->flags);
 	disk->magic.be = cpu_to_be32(cpu->magic);
 	disk->md_size.be = cpu_to_be32(cpu->md_size);
 	disk->al_offset.be = cpu_to_be32(cpu->al_offset);
 	disk->al_nr_extents.be = cpu_to_be32(cpu->al_nr_extents);
 	disk->bm_offset.be = cpu_to_be32(cpu->bm_offset);
-	memset(disk->reserved, sizeof(disk->reserved), 0);
+	memset(disk->reserved, 0, sizeof(disk->reserved));
 }
 
 int v08_validate_md(struct md_cpu *md)
@@ -400,11 +445,13 @@
 	char *drbd_dev_name;
 	int lock_fd;
 	int drbd_fd;
-	int ll_fd;
+	int ll_fd;		/* not yet used here */
 	int md_fd;
 
-	/* byte offset of our "super block", within fd */
+	/* byte offsets of our "super block" and other data, within fd */
 	u64 md_offset;
+	u64 al_offset;
+	u64 bm_offset;
 
 	/* unused in 06 */
 	int md_index;
@@ -429,6 +476,9 @@
 		 * which may be partially unused
 		 * use le_long for now. */
 		le_ulong *bm;
+
+		/* to check for existing data on physical devices */
+		void *ll_data;
 	} on_disk;
 };
 
@@ -572,14 +622,18 @@
 
 int confirmed(const char *text)
 {
-	char answer[16];
-	int rr;
+	const char yes[] = "yes";
+	const ssize_t N = sizeof(yes);
+	char *answer = NULL;
+	size_t n = 0;
+	int ok;
 
-	do {
-		printf("%s [yes/no] ", text);
-		rr = scanf("%15s", answer);
-	} while (rr != 1);
-	return !strcmp(answer, "yes");
+	printf("\n%s\n[need to type '%s' to confirm] ", text, yes);
+	ok = getline(&answer,&n,stdin) == N &&
+	     strncmp(answer,yes,N-1) == 0;
+	if (answer) free(answer);
+	printf("\n");
+	return ok;
 }
 
 unsigned long bm_words(u64 sectors)
@@ -642,7 +696,7 @@
 	u64 offset;
 
 	if (cfg->md_index == -1) {
-		offset = (bdev_size(cfg->md_fd) & ~((1 << 12) - 1))
+		offset = (bdev_size(cfg->md_fd) & ~((1LLU << 12) - 1))
 		    - MD_RESERVED_SIZE_07;
 	} else {
 		offset = MD_RESERVED_SIZE_07 * cfg->md_index;
@@ -654,7 +708,7 @@
 {
 	struct stat sb;
 	unsigned long words;
-	u64 offset, al_offset, bm_offset;
+	u64 offset;
 
 	cfg->md_fd = open(cfg->md_device_name, O_RDWR);
 
@@ -689,23 +743,37 @@
 	}
 	cfg->md_offset = offset;
 
+	/* in case this is internal meta data, mmap first <some>KB of device,
+	 * so we can try and detect existing file systems on the physical
+	 * device, and warn about that.
+	 */
+	if (cfg->md_index == -1) {
+		cfg->on_disk.ll_data =
+		    mmap(NULL, HOW_MUCH, PROT_READ | PROT_WRITE, MAP_SHARED,
+			 cfg->md_fd, 0);
+		if (cfg->on_disk.ll_data == NULL) {
+			PERROR("mmap(ll_data) failed");
+			exit(20);
+		}
+	}
+
 	if (cfg->ops->md_disk_to_cpu(cfg)) {
 		return -1;
 	}
 
-	al_offset = offset + cfg->md.al_offset * 512;
-	bm_offset = offset + cfg->md.bm_offset * 512;
+	cfg->al_offset = offset + cfg->md.al_offset * 512;
+	cfg->bm_offset = offset + cfg->md.bm_offset * 512;
 
 	cfg->on_disk.al =
 	    mmap(NULL, MD_AL_MAX_SIZE_07 * 512, PROT_READ | PROT_WRITE,
-		 MAP_SHARED, cfg->md_fd, al_offset);
+		 MAP_SHARED, cfg->md_fd, cfg->al_offset);
 	if (cfg->on_disk.al == NULL) {
 		PERROR("mmap(al_on_disk) failed");
 		exit(20);
 	}
 
 	cfg->on_disk.bm = mmap(NULL, MD_BM_MAX_SIZE_07, PROT_READ | PROT_WRITE,
-			       MAP_SHARED, cfg->md_fd, bm_offset);
+			       MAP_SHARED, cfg->md_fd, cfg->bm_offset);
 	if (cfg->on_disk.bm == NULL) {
 		PERROR("mmap(bm_on_disk) failed");
 		exit(20);
@@ -845,7 +913,7 @@
 
 	do {
 		for ( i=Current ; i<UUID_SIZE ; i++ ) {
-			if (!m_strsep_u64(str, &md->uuid[i])) goto done;
+			if (!m_strsep_u64(str, &md->uuid[i])) return;
 		}
 		if (!m_strsep_bit(str, &md->flags, MDF_Consistent)) break;
 		if (!m_strsep_bit(str, &md->flags, MDF_WasUpToDate)) break;
@@ -853,7 +921,6 @@
 		if (!m_strsep_bit(str, &md->flags, MDF_ConnectedInd)) break;
 		if (!m_strsep_bit(str, &md->flags, MDF_FullSync)) break;
 	} while (0);
-	done:
 }
 
 
@@ -1043,37 +1110,40 @@
 
 int v07_md_close(struct format *cfg)
 {
+	int err = 0;
+	if (cfg->on_disk.ll_data && munmap(cfg->on_disk.ll_data, HOW_MUCH)) {
+		PERROR("munmap(ll_data) failed");
+		err = -1;
+	}
 	if (munmap(cfg->on_disk.bm, MD_BM_MAX_SIZE_07)) {
 		PERROR("munmap(bm_on_disk) failed");
-		return -1;
+		err = -1;
 	}
 	if (munmap(cfg->on_disk.al, MD_AL_MAX_SIZE_07 * 512)) {
 		PERROR("munmap(al_on_disk) failed");
-		return -1;
+		err = -1;
 	}
 	if (munmap(cfg->on_disk.md7, 8 * 512)) {
 		PERROR("munmap(md_on_disk) failed");
-		return -1;
+		err = -1;
 	}
 	if (fsync(cfg->md_fd) == -1) {
 		PERROR("fsync() failed");
-		return -1;
+		err = -1;
 	}
 	if (ioctl(cfg->md_fd, BLKFLSBUF) == -1) {
 		PERROR("ioctl(,BLKFLSBUF,) failed");
-		return -1;
+		err = -1;
 	}
 	if (close(cfg->md_fd)) {
 		PERROR("close() failed");
-		return -1;
+		err = -1;
 	}
-	return 0;
+	return err;
 }
 
 int v07_md_initialize(struct format *cfg)
 {
-	u64 al_offset, bm_offset;
-
 	cfg->md.la_sect = 0;
 	cfg->md.gc[Flags] = 0;
 	cfg->md.gc[HumanCnt] = 1;	/* THINK 0? 1? */
@@ -1090,12 +1160,12 @@
 	cfg->md.al_nr_extents = 257;	/* arbitrary. */
 	cfg->md.bm_offset = MD_BM_OFFSET_07;
 
-	al_offset = cfg->md_offset + cfg->md.al_offset * 512;
-	bm_offset = cfg->md_offset + cfg->md.bm_offset * 512;
+	cfg->al_offset = cfg->md_offset + cfg->md.al_offset * 512;
+	cfg->bm_offset = cfg->md_offset + cfg->md.bm_offset * 512;
 	if (cfg->on_disk.al == NULL) {
 		cfg->on_disk.al =
 		    mmap(NULL, MD_AL_MAX_SIZE_07 * 512, PROT_READ | PROT_WRITE,
-			 MAP_SHARED, cfg->md_fd, al_offset);
+			 MAP_SHARED, cfg->md_fd, cfg->al_offset);
 		if (cfg->on_disk.al == NULL) {
 			PERROR("mmap(al_on_disk) failed");
 			exit(20);
@@ -1105,15 +1175,15 @@
 	if (cfg->on_disk.bm == NULL) {
 		cfg->on_disk.bm =
 		    mmap(NULL, MD_BM_MAX_SIZE_07, PROT_READ | PROT_WRITE,
-			 MAP_SHARED, cfg->md_fd, bm_offset);
+			 MAP_SHARED, cfg->md_fd, cfg->bm_offset);
 		if (cfg->on_disk.bm == NULL) {
 			PERROR("mmap(bm_on_disk) failed");
 			exit(20);
 		}
 	}
 
-	memset(cfg->on_disk.al, MD_AL_MAX_SIZE_07, 0);
-	memset(cfg->on_disk.bm, MD_BM_MAX_SIZE_07, 0xff);
+	memset(cfg->on_disk.al, 0x00, MD_AL_MAX_SIZE_07);
+	memset(cfg->on_disk.bm, 0xff, MD_BM_MAX_SIZE_07);
 	return 0;
 }
 
@@ -1140,6 +1210,7 @@
 		return -1;
 	}
 	md_cpu_to_disk_08(cfg->on_disk.md8, &cfg->md);
+	fprintf(stderr,"msync\n");
 	err = msync(cfg->on_disk.md8, sizeof(*cfg->on_disk.md8),
 		    MS_SYNC | MS_INVALIDATE);
 	if (err) {
@@ -1156,7 +1227,6 @@
 
 int v08_md_initialize(struct format *cfg)
 {
-	u64 al_offset, bm_offset;
 	int i;
 
 	cfg->md.la_sect = 0;
@@ -1177,12 +1247,12 @@
 	cfg->md.al_nr_extents = 257;	/* arbitrary. */
 	cfg->md.bm_offset = MD_BM_OFFSET_07;
 
-	al_offset = cfg->md_offset + cfg->md.al_offset * 512;
-	bm_offset = cfg->md_offset + cfg->md.bm_offset * 512;
+	cfg->al_offset = cfg->md_offset + cfg->md.al_offset * 512;
+	cfg->bm_offset = cfg->md_offset + cfg->md.bm_offset * 512;
 	if (cfg->on_disk.al == NULL) {
 		cfg->on_disk.al =
 		    mmap(NULL, MD_AL_MAX_SIZE_07 * 512, PROT_READ | PROT_WRITE,
-			 MAP_SHARED, cfg->md_fd, al_offset);
+			 MAP_SHARED, cfg->md_fd, cfg->al_offset);
 		if (cfg->on_disk.al == NULL) {
 			PERROR("mmap(al_on_disk) failed");
 			exit(20);
@@ -1192,7 +1262,7 @@
 	if (cfg->on_disk.bm == NULL) {
 		cfg->on_disk.bm =
 		    mmap(NULL, MD_BM_MAX_SIZE_07, PROT_READ | PROT_WRITE,
-			 MAP_SHARED, cfg->md_fd, bm_offset);
+			 MAP_SHARED, cfg->md_fd, cfg->bm_offset);
 		if (cfg->on_disk.bm == NULL) {
 			PERROR("mmap(bm_on_disk) failed");
 			exit(20);
@@ -1200,8 +1270,10 @@
 	}
 
 	/* do you want to initilize al to something more usefull? */
-	memset(cfg->on_disk.al, MD_AL_MAX_SIZE_07, 0);
-	memset(cfg->on_disk.bm, MD_BM_MAX_SIZE_07, 0xff);
+	//fprintf(stderr,"memset al\n");
+	memset(cfg->on_disk.al, 0x00, MD_AL_MAX_SIZE_07);
+	//fprintf(stderr,"memset bm\n");
+	memset(cfg->on_disk.bm, 0xff, MD_BM_MAX_SIZE_07);
 	return 0;
 }
 
@@ -1437,6 +1509,207 @@
 	return 0;
 }
 
+int md_convert_08_to_07(struct format *cfg)
+{
+	/* Note that al and bm are not touched!
+	 * (they are currently not even mmaped)
+	 *
+	 * KB <-> sectors is done in the md disk<->cpu functions.
+	 * We only need to adjust the magic here. */
+	printf("Converting meta data...\n");
+	cfg->md.magic = DRBD_MD_MAGIC_07;
+	// somehow generate GCs in a sane way
+	if (cfg->ops->md_cpu_to_disk(cfg)
+	    || cfg->ops->close(cfg)) {
+		fprintf(stderr, "conversion failed\n");
+		return -1;
+	}
+	printf("Conversion Currently BROKEN!\n");
+	//printf("Successfully converted v08 meta data to v07 format.\n");
+	return 0;
+}
+
+/* if on the physical device we find some data we can interpret,
+ * print some informational message about what we found,
+ * and what we think how much room it needs.
+ *
+ * look into /usr/share/misc/magic for inspiration
+ * also consider e.g. xfsprogs/libdisk/fstype.c,
+ * and of course the linux kernel headers...
+ */
+struct fstype_s {
+	const char * type;
+	unsigned long long bnum, bsize;
+};
+
+int may_be_extX(char *data, struct fstype_s *f)
+{
+	unsigned int size;
+	if (le16_to_cpu(*(u16*)(data+0x438)) == 0xEF53) {
+		if ( (le32_to_cpu(*(data+0x45c)) & 4) == 4 )
+			f->type = "ext3 filesystem";
+		else
+			f->type = "ext2 filesystem";
+		f->bnum  = le32_to_cpu(*(u32*)(data+0x404));
+		size     = le32_to_cpu(*(u32*)(data+0x418));
+		f->bsize = size == 0 ? 1024 :
+			size == 1 ? 2048 :
+			size == 2 ? 4096 :
+			4096; /* DEFAULT */
+		return 1;
+	}
+	return 0;
+}
+
+int may_be_xfs(char *data, struct fstype_s *f)
+{
+	if (be32_to_cpu(*(u32*)(data+0)) == 0x58465342) {
+		f->type = "xfs filesystem";
+		f->bsize = be32_to_cpu(*(u32*)(data+4));
+		f->bnum  = be64_to_cpu(*(u64*)(data+8));
+		return 1;
+	}
+	return 0;
+}
+
+int may_be_reiserfs(char *data, struct fstype_s *f)
+{
+	if (strncmp("ReIsErFs",data+0x10034,8) == 0 ||
+	    strncmp("ReIsEr2Fs",data+0x10034,9) == 0) {
+		f->type = "reiser filesystem";
+		f->bnum  = le32_to_cpu(*(u32*)(data+0x10000));
+		f->bsize = le16_to_cpu(*(u16*)(data+0x1002c));
+		return 1;
+	}
+	return 0;
+}
+
+int may_be_jfs(char *data, struct fstype_s *f)
+{
+	if (strncmp("JFS1",data+0x8000,4) == 0) {
+		f->type = "JFS filesystem";
+		f->bnum = le64_to_cpu(*(u64*)(data+0x8008));
+		f->bsize = le32_to_cpu(*(u32*)(data+0x8018));
+		return 1;
+	}
+	return 0;
+}
+
+/* really large block size,
+ * will always refuse */
+#define REFUSE_BSIZE 0xFFFFffffFFFF0000LLU
+#define REFUSE_IT    f->bnum = 1; f->bsize = REFUSE_BSIZE;
+int may_be_swap(char *data, struct fstype_s *f)
+{
+	int looks_like_swap =
+		strncmp(data+(1<<12)-10, "SWAP-SPACE", 10) == 0 ||
+		strncmp(data+(1<<12)-10, "SWAPSPACE2", 10) == 0 ||
+		strncmp(data+(1<<13)-10, "SWAP-SPACE", 10) == 0 ||
+		strncmp(data+(1<<13)-10, "SWAPSPACE2", 10) == 0;
+	if (looks_like_swap) {
+		f->type = "swap space signature";
+		REFUSE_IT
+		return 1;
+	}
+	return 0;
+}
+
+int may_be_LVM(char *data, struct fstype_s *f)
+{
+	if (strncmp("LVM2",data+0x218,4) == 0) {
+		f->type = "LVM2 physical volume signature";
+		REFUSE_IT
+		return 1;
+	}
+	return 0;
+}
+
+void check_for_exiting_data(struct format *cfg)
+{
+	char *data = cfg->on_disk.ll_data;
+	struct fstype_s f;
+	int i;
+	if (data == NULL)
+		return;
+
+	for (i = 0; i < HOW_MUCH/sizeof(long); i++) {
+		if (((long*)(data))[i] != 0LU) break;
+	}
+	/* all zeros? no message */
+	if (i == HOW_MUCH/sizeof(long)) return;
+
+	f.type = "some data";
+	f.bnum = 0;
+	f.bsize = 0;
+
+/* FIXME add more detection magic
+ */
+
+	may_be_swap     (data,&f) ||
+	may_be_LVM      (data,&f) ||
+
+	may_be_extX     (data,&f) ||
+	may_be_xfs      (data,&f) ||
+	may_be_jfs      (data,&f) ||
+	may_be_reiserfs (data,&f);
+
+	printf("\nFound %s ", f.type);
+	if (f.bnum) {
+		/* FIXME overflow check missing!
+		 * relevant for ln2(bsize) + ln2(bnum) >= 64, thus only for
+		 * device sizes of more than several exa byte.
+		 * seems irrelevant to me for now.
+		 */
+		u64 fs_kB = ((f.bsize * f.bnum) + (1<<10)-1) >> 10;
+		u64 max_usable_kB;
+
+		if (f.bsize == REFUSE_BSIZE) {
+			printf(
+"\nDevice size would be truncated, which\n"
+"would corrupt data and result in\n"
+"'access beyond end of device' errors.\n"
+"If you want me to do this, you need to zero out the first part\n"
+"of the device (destroy the content).\n"
+"You should be very sure that you mean it.\n"
+"Operation refused.\n\n");
+			exit(40); /* FIXME sane exit code! */
+		}
+
+#if 0
+#define min(x,y) ((x) < (y) ? (x) : (y))
+		max_usable_kB =
+			min( cfg->md_offset,
+			min( cfg->al_offset,
+			     cfg->bm_offset )) >> 10;
+#undef min
+
+		printf("md_offset %llu\n", cfg->md_offset);
+		printf("al_offset %llu\n", cfg->al_offset);
+		printf("bm_offset %llu\n", cfg->bm_offset);
+#else
+		/* for now (we still have no flexible size meta data) */
+		max_usable_kB = cfg->md_offset >> 10;
+#endif
+
+		/* looks like file system data */
+		printf("which uses %llu kB\n", fs_kB);
+		printf("current configuration leaves usable %llu kB\n", max_usable_kB);
+		if (fs_kB > max_usable_kB) {
+			printf(
+"\nDevice size would be truncated, which\n"
+"would corrupt data and result in\n"
+"'access beyond end of device' errors.\n"
+"You need to either\n"
+"   * use external meta data (recommended)\n"
+"   * shrink that filesystem first\n"
+"   * zero out the device (destroy the filesystem)\n"
+"Operation refused.\n\n");
+			exit(40); /* FIXME sane exit code! */
+		}
+	}
+}
+
+
 /* FIXME create v07 replaces a valid v08 block without confirmation!
  * we need better format auto-detection */
 int meta_create_md(struct format *cfg, char **argv, int argc)
@@ -1454,23 +1727,44 @@
 		 */
 		virgin = v07_md_disk_to_cpu(cfg);
 		if (!virgin) {
-			if (confirmed("Valid v07 meta-data found, convert?"))
+			if (confirmed("Valid v07 meta-data found, convert to v08?"))
 				return md_convert_07_to_08(cfg);
 		}
 	}
+	if (virgin && cfg->ops == f_ops + Drbd_07) {
+		/* don't just overwrite existing v08 with v07
+		 */
+		virgin = v08_md_disk_to_cpu(cfg);
+		if (!virgin) {
+			if (confirmed("Valid v08 meta-data found, convert back to v07?"))
+				return md_convert_08_to_07(cfg);
+		}
+	}
+
 	if (!virgin) {
-		if (!confirmed("Valid meta-data already in place, create new?")) {
+		if (!confirmed("Valid meta-data already in place, recreate new?")) {
 			printf("Operation cancelled.\n");
 			exit(0);
 		}
+	} else {
+		printf("About to create a new drbd meta data block\non %s.\n",
+				cfg->md_device_name);
+		check_for_exiting_data(cfg);
+
+		if (!confirmed(" ==> This might destroy existing data! <==\n\n"
+				"Do you want to proceed?")) {
+			printf("Operation cancelled.\n");
+			exit(0);
+		}
 	}
 
 	printf("Creating meta data...\n");
+	memset(&cfg->md, 0, sizeof(cfg->md));
 	err = cfg->ops->md_initialize(cfg)
 	    || cfg->ops->md_cpu_to_disk(cfg)
 	    || cfg->ops->close(cfg);
 	if (err)
-		fprintf(stderr, "conversion failed\n");
+		fprintf(stderr, "operation failed\n");
 
 	return err;
 }
@@ -1577,7 +1871,7 @@
 #endif
 
 char *progname = NULL;
-void print_usage()
+void print_usage_and_exit()
 {
 	char **args;
 	int i;
@@ -1640,13 +1934,13 @@
 
 	pr = fopen("/proc/drbd","r");
 	if(!pr) return rv;
-	
+
 	while(fgets(line,120,pr)) {
 		if(sscanf(line,"%2d: %s",&m,tok)) {
 			if( m == minor ) {
 				rv = strcmp(tok,"Unconfigured");
 				break;
-			}			
+			}
 		}
 	}
 	fclose(pr);
@@ -1660,6 +1954,21 @@
 	struct format *cfg;
 	int i, ai;
 
+#if 1
+	if (sizeof(struct md_on_disk_07) != 4096) {
+		fprintf(stderr, "Where did you get this broken build!?\n"
+			        "sizeof(md_on_disk_07) == %u, should be 4096\n",
+				sizeof(struct md_on_disk_07));
+		exit(111);
+	}
+	if (sizeof(struct md_on_disk_08) != 4096) {
+		fprintf(stderr, "Where did you get this broken build!?\n"
+			        "sizeof(md_on_disk_08) == %u, should be 4096\n",
+				sizeof(struct md_on_disk_08));
+		exit(111);
+	}
+#endif
+
 	if ((progname = strrchr(argv[0], '/'))) {
 		argv[0] = ++progname;
 	} else {
@@ -1667,21 +1976,13 @@
 	}
 
 	if (argc < 4)
-		print_usage();
+		print_usage_and_exit();
 
 	/* FIXME should have a "drbd_cfg_new" and a "drbd_cfg_free"
 	 * function, maybe even a "get" and "put" ?
 	 */
 	cfg = calloc(1, sizeof(struct format));
 	cfg->drbd_dev_name = argv[1];
-	cfg->drbd_fd = dt_lock_open_drbd(cfg->drbd_dev_name, &cfg->lock_fd, 1);
-	if (cfg->drbd_fd > -1) {
-		if (is_configured(dt_minor_of_dev(cfg->drbd_dev_name))) {
-			fprintf(stderr, "Device '%s' is configured!\n",
-				cfg->drbd_dev_name);
-			exit(20);
-		}
-	}
 
 	/* argv[0] is progname, argv[1] was drbd_dev_name. */
 	ai = 2;
@@ -1695,6 +1996,16 @@
 		exit(20);
 	}
 
+	cfg->drbd_fd = dt_lock_open_drbd(cfg->drbd_dev_name, &cfg->lock_fd, 1);
+	if (cfg->drbd_fd > -1) {
+		if (is_configured(dt_minor_of_dev(cfg->drbd_dev_name))) {
+			fprintf(stderr, "Device '%s' is configured!\n",
+				cfg->drbd_dev_name);
+			exit(20);
+		}
+	}
+
+
 	for (i = 0; i < ARRY_SIZE(cmds); i++) {
 		if (!strcmp(cmds[i].name, argv[ai])) {
 			command = cmds + i;

Modified: trunk/user/drbdmeta_parser.h
===================================================================
--- trunk/user/drbdmeta_parser.h	2005-04-21 15:46:52 UTC (rev 1784)
+++ trunk/user/drbdmeta_parser.h	2005-04-21 21:53:53 UTC (rev 1785)
@@ -5,6 +5,7 @@
 
 #define YYSTYPE_IS_DECLARED 1
 #define YYSTYPE_IS_TRIVIAL 1
+#define YY_NO_UNPUT 1
 
 extern YYSTYPE yylval;
 
@@ -19,3 +20,5 @@
 	TK_LA_SIZE
 };
 
+/* avoid compiler warnings about implicit declaration */
+int yylex(void);

Modified: trunk/user/drbdtool_common.h
===================================================================
--- trunk/user/drbdtool_common.h	2005-04-21 15:46:52 UTC (rev 1784)
+++ trunk/user/drbdtool_common.h	2005-04-21 21:53:53 UTC (rev 1785)
@@ -5,6 +5,17 @@
 
 #define ARRY_SIZE(A) (sizeof(A)/sizeof(A[0]))
 
+
+/* MetaDataIndex for v06 / v07 style meta data blocks */
+enum MetaDataIndex {
+	Flags,			/* Consistency flag,connected-ind,primary-ind */
+	HumanCnt,		/* human-intervention-count */
+	TimeoutCnt,		/* timout-count */
+	ConnectedCnt,		/* connected-count */
+	ArbitraryCnt,		/* arbitrary-count */
+	GEN_CNT_SIZE		/* MUST BE LAST! (and Flags must stay first...) */
+};
+
 /*
 #define PERROR(fmt, args...) \
 do { fprintf(stderr,fmt ": " , ##args); perror(0); } while (0)

From www-data at garcon.linbit.com  Fri Apr 22 11:29:57 2005
From: www-data at garcon.linbit.com (www-data)
Date: Fri Apr 22 11:29:59 2005
Subject: [DRBD-cvs] r1786 - trunk/user
Message-ID: <20050422092957.93733144E2@mail.linbit.com>

Author: lars
Date: 2005-04-22 11:29:54 +0200 (Fri, 22 Apr 2005)
New Revision: 1786

Modified:
   trunk/user/drbdmeta.c
Log:
remove some debug messages again...

Modified: trunk/user/drbdmeta.c
===================================================================
--- trunk/user/drbdmeta.c	2005-04-21 21:53:53 UTC (rev 1785)
+++ trunk/user/drbdmeta.c	2005-04-22 09:29:54 UTC (rev 1786)
@@ -1210,7 +1210,6 @@
 		return -1;
 	}
 	md_cpu_to_disk_08(cfg->on_disk.md8, &cfg->md);
-	fprintf(stderr,"msync\n");
 	err = msync(cfg->on_disk.md8, sizeof(*cfg->on_disk.md8),
 		    MS_SYNC | MS_INVALIDATE);
 	if (err) {
@@ -1270,9 +1269,7 @@
 	}
 
 	/* do you want to initilize al to something more usefull? */
-	//fprintf(stderr,"memset al\n");
 	memset(cfg->on_disk.al, 0x00, MD_AL_MAX_SIZE_07);
-	//fprintf(stderr,"memset bm\n");
 	memset(cfg->on_disk.bm, 0xff, MD_BM_MAX_SIZE_07);
 	return 0;
 }

From www-data at garcon.linbit.com  Sat Apr 23 19:52:45 2005
From: www-data at garcon.linbit.com (www-data)
Date: Sat Apr 23 19:52:47 2005
Subject: [DRBD-cvs] r1787 - trunk/drbd
Message-ID: <20050423175245.D889A15057@mail.linbit.com>

Author: phil
Date: 2005-04-23 19:52:45 +0200 (Sat, 23 Apr 2005)
New Revision: 1787

Modified:
   trunk/drbd/drbd_fs.c
Log:
The logic in some lines in do_determin_dev_size() still
assumed that size is in KB while it is now in secotrs.
BTW, was triggered by Lars' BM_PARANOIA_CHECK. 


Modified: trunk/drbd/drbd_fs.c
===================================================================
--- trunk/drbd/drbd_fs.c	2005-04-22 09:29:54 UTC (rev 1786)
+++ trunk/drbd/drbd_fs.c	2005-04-23 17:52:45 UTC (rev 1787)
@@ -131,12 +131,11 @@
 	}
 
 	if(u_size) {
-		/* FIXME size now in sectors, user still provides KB */
-		if(u_size > size) {
+		if(u_size<<1 > size) {
 			ERR("Requested disk size is too big (%lu > %lu)\n",
-			    (unsigned long)u_size, (unsigned long)size);
+			    (unsigned long)u_size, (unsigned long)size>>1);
 		} else {
-			size = u_size;
+			size = u_size<<1;
 		}
 	}
 
@@ -157,10 +156,10 @@
 			}
 		}
 		// racy, see comments above.
-		drbd_set_my_capacity(mdev,size<<1);
+		drbd_set_my_capacity(mdev,size);
 		mdev->la_size = size;
-		INFO("size = %s (%lu KB)\n",ppsize(ppb,size),
-		     (unsigned long)size);
+		INFO("size = %s (%lu KB)\n",ppsize(ppb,size>>1),
+		     (unsigned long)size>>1);
 	}
 
 	return rv;

From www-data at garcon.linbit.com  Tue Apr 26 21:43:56 2005
From: www-data at garcon.linbit.com (www-data)
Date: Tue Apr 26 21:43:57 2005
Subject: [DRBD-cvs] r1788 - trunk/drbd
Message-ID: <20050426194356.233571519C@mail.linbit.com>

Author: phil
Date: 2005-04-26 21:43:54 +0200 (Tue, 26 Apr 2005)
New Revision: 1788

Modified:
   trunk/drbd/drbd_main.c
   trunk/drbd/drbd_receiver.c
Log:
Some testing, found and fixed two bugs:
- I forgot to write/read the flags word of the metadata in the module.
- In the drbd_uuid_compare() function the outmasking of the lowest bit
  was missing in one place.


Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c	2005-04-23 17:52:45 UTC (rev 1787)
+++ trunk/drbd/drbd_main.c	2005-04-26 19:43:54 UTC (rev 1788)
@@ -2257,12 +2257,12 @@
 	if (mdev->state.s.disk >  Outdated)       flags |= MDF_WasUpToDate;
 	mdev->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->uuid[i]);
-	buffer->la_size=cpu_to_be64(drbd_get_capacity(mdev->this_bdev));
+	buffer->flags = cpu_to_be32(flags);
+	buffer->magic = cpu_to_be32(DRBD_MD_MAGIC);
 
-	buffer->magic=cpu_to_be32(DRBD_MD_MAGIC);
-
 	buffer->md_size = __constant_cpu_to_be32(MD_RESERVED_SIZE);
 	buffer->al_offset = __constant_cpu_to_be32(MD_AL_OFFSET);
 	buffer->al_nr_extents = cpu_to_be32(mdev->act_log->nr_elements);
@@ -2334,9 +2334,10 @@
 		goto err;
 	}
 
+	mdev->la_size = be64_to_cpu(buffer->la_size);
 	for (i = Current; i < UUID_SIZE; i++)
 		mdev->uuid[i]=be64_to_cpu(buffer->uuid[i]);
-	mdev->la_size = be64_to_cpu(buffer->la_size);
+	mdev->md_flags = be32_to_cpu(buffer->flags);
 	mdev->sync_conf.al_extents = be32_to_cpu(buffer->al_nr_extents);
 	if (mdev->sync_conf.al_extents < 7)
 		mdev->sync_conf.al_extents = 127;

Modified: trunk/drbd/drbd_receiver.c
===================================================================
--- trunk/drbd/drbd_receiver.c	2005-04-23 17:52:45 UTC (rev 1787)
+++ trunk/drbd/drbd_receiver.c	2005-04-26 19:43:54 UTC (rev 1788)
@@ -1290,7 +1290,7 @@
 	if (self == peer) return -1;
 
 	for ( i=History_start ; i<=History_end ; i++ ) {
-		peer = mdev->p_uuid[i];
+		peer = mdev->p_uuid[i] & ~((u64)1);
 		if (self == peer) return -2;
 	}
 

