[DRBD-cvs] r1636 - in trunk: drbd drbd/linux user

svn at svn.drbd.org svn at svn.drbd.org
Fri Nov 12 12:51:58 CET 2004


Author: phil
Date: 2004-11-12 12:51:55 +0100 (Fri, 12 Nov 2004)
New Revision: 1636

Modified:
   trunk/drbd/drbd_fs.c
   trunk/drbd/drbd_int.h
   trunk/drbd/drbd_main.c
   trunk/drbd/drbd_receiver.c
   trunk/drbd/drbd_req.c
   trunk/drbd/drbd_strings.c
   trunk/drbd/drbd_worker.c
   trunk/drbd/linux/drbd.h
   trunk/drbd/linux/drbd_config.h
   trunk/user/drbdadm_main.c
   trunk/user/drbdmeta.c
   trunk/user/drbdsetup.c
Log:
Implemented "drbdadm outdate" and the implications on DRBD's
state switching mechanisms.


Modified: trunk/drbd/drbd_fs.c
===================================================================
--- trunk/drbd/drbd_fs.c	2004-11-12 08:42:23 UTC (rev 1635)
+++ trunk/drbd/drbd_fs.c	2004-11-12 11:51:55 UTC (rev 1636)
@@ -222,6 +222,7 @@
 	struct file *filp2 = 0;
 	struct inode *inode, *inode2;
 	struct block_device *bdev, *bdev2;
+	drbd_disks_t nds;
 
 	minor=(int)(mdev-drbd_conf);
 
@@ -434,9 +435,22 @@
 
 	drbd_set_blocksize(mdev,INITIAL_BLOCK_SIZE);
 
-	if(drbd_request_state(mdev,NS(disk,
-				      drbd_md_test_flag(mdev,MDF_Consistent)
-				      ? Consistent : Inconsistent )) > 0) {
+	/* If MDF_Consistent is not set go into inconsistent state, otherwise
+	   investige MDF_UpToDate...
+	   If MDF_UpToDate is not set go into Outdated disk state, otherwise
+	   into Consistent state.
+	*/
+	if(drbd_md_test_flag(mdev,MDF_Consistent)) {
+		if(drbd_md_test_flag(mdev,MDF_UpToDate)) {
+			nds = Consistent;
+		} else {
+			nds = Outdated;
+		}
+	} else {
+		nds = Inconsistent;
+	}
+
+	if(drbd_request_state(mdev,NS(disk,nds)) > 0) {
 		drbd_thread_start(&mdev->worker);
 	}
 
@@ -615,10 +629,10 @@
 		}
 
 		/* --do-what-I-say*/
-		if (mdev->state.s.disk < Consistent) {
-			WARN("Forcefully set consistent!");
+		if (mdev->state.s.disk < UpToDate) {
+			WARN("Forcefully set to UpToDate!");
 			r = drbd_request_state(mdev,NS2(role,newstate & 0x3,
-							disk,Consistent));
+							disk,UpToDate));
 			if(r<=0) return -EIO;
 
 			forced = 1;
@@ -1032,7 +1046,6 @@
 		drbd_bm_lock(mdev); // racy...
 
 		drbd_md_set_flag(mdev,MDF_FullSync);
-		drbd_md_clear_flag(mdev,MDF_Consistent);
 		drbd_md_write(mdev);
 
 		drbd_bm_set_all(mdev);
@@ -1086,6 +1099,18 @@
 
 		break;
 
+	case DRBD_IOCTL_OUTDATE_DISK:
+		r = drbd_request_state(mdev,NS(disk,Outdated));
+		if( r == 2 ) break;
+		if( r <= 0 ) {
+			err = -EISCONN;
+			break;
+		}
+
+		drbd_md_write(mdev);
+		
+		break;
+
 	default:
 		err = -EINVAL;
 	}

Modified: trunk/drbd/drbd_int.h
===================================================================
--- trunk/drbd/drbd_int.h	2004-11-12 08:42:23 UTC (rev 1635)
+++ trunk/drbd/drbd_int.h	2004-11-12 11:51:55 UTC (rev 1636)
@@ -246,11 +246,13 @@
 	__MDF_PrimaryInd,
 	__MDF_ConnectedInd,
 	__MDF_FullSync,
+	__MDF_UpToDate,
 };
 #define MDF_Consistent      (1<<__MDF_Consistent)
 #define MDF_PrimaryInd      (1<<__MDF_PrimaryInd)
 #define MDF_ConnectedInd    (1<<__MDF_ConnectedInd)
 #define MDF_FullSync        (1<<__MDF_FullSync)
+#define MDF_UpToDate        (1<<__MDF_UpToDate)
 
 /* drbd_meta-data.c (still in drbd_main.c) */
 enum MetaDataIndex {

Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c	2004-11-12 08:42:23 UTC (rev 1635)
+++ trunk/drbd/drbd_main.c	2004-11-12 11:51:55 UTC (rev 1636)
@@ -431,10 +431,14 @@
 		    ns.s.conn < Connected ) rv=-3;
 
 		if( ns.s.conn > Connected && 
-		    ns.s.disk < Consistent && ns.s.pdsk < Consistent ) rv=-4;
+		    ns.s.disk < UpToDate && ns.s.pdsk < UpToDate ) rv=-4;
 
 		if( ns.s.conn > Connected && 
 		    (ns.s.disk == Diskless || ns.s.pdsk == Diskless ) ) rv=-5;
+
+		if( (ns.s.conn >= Connected && ns.s.conn != PausedSyncT) &&
+		    ns.s.disk == Outdated ) rv=-6;
+
 	}
 
 	/*  State sanitising  */
@@ -446,6 +450,48 @@
 		ns.s.conn = Connected;
 	}
 
+	if( ns.s.conn >= Connected && ns.s.disk == Consistent ) {
+		switch(ns.s.conn) {
+		case SkippedSyncT:
+		case WFBitMapT:
+		case PausedSyncT:
+			ns.s.disk = Outdated;
+			break;
+		case Connected:
+		case SkippedSyncS:
+		case WFBitMapS:
+		case SyncSource:
+		case PausedSyncS:
+			ns.s.disk = UpToDate;
+			break;
+		case SyncTarget:
+			ns.s.disk = Inconsistent;
+			WARN("Implicit set disk state Inconsistent!\n");
+			break;
+		}
+	}
+
+	if( ns.s.conn >= Connected && ns.s.pdsk == Consistent ) {
+		switch(ns.s.conn) {
+		case Connected:
+		case SkippedSyncT:
+		case WFBitMapT:
+		case PausedSyncT:
+		case SyncTarget:
+			ns.s.pdsk = UpToDate;
+			break;
+		case SkippedSyncS:
+		case WFBitMapS:
+		case PausedSyncS:
+			ns.s.pdsk = Outdated;
+			break;
+		case SyncSource:
+			ns.s.disk = Inconsistent;
+			WARN("Implicit set pdsk Inconsistent!\n");
+			break;
+		}
+	}
+
 	if(rv <= 0) {
 		if( flags & ChgStateVerbose ) print_st_err(mdev,os,ns,rv);
 		return rv;
@@ -483,7 +529,7 @@
 	}
 
 	if ( ns.s.role == Primary && ns.s.conn < Connected &&
-	     ns.s.disk < Consistent ) {
+	     ns.s.disk < UpToDate ) {
 		drbd_panic("No access to good data anymore.\n");
 	}
 
@@ -506,18 +552,6 @@
 	     ns.s.conn >= Connected ) {
 		drbd_send_param(mdev,0);
 	}
-
-	/*  Update MDF_Consistent in the meta-data  */
-	if ( os.s.disk != ns.s.disk && ns.s.disk > Failed ) {
-		if(ns.s.disk >= Outdated ) {
-			drbd_md_set_flag(mdev,MDF_Consistent);
-		} else {
-			drbd_md_clear_flag(mdev,MDF_Consistent);
-		}
-		/* TODO metadata, to support everything that 
-		   drbd_disk_t can express... */
-	}
-
 }
 
 
@@ -1964,9 +1998,12 @@
 	buffer = (struct meta_data_on_disk *)page_address(mdev->md_io_page);
 	memset(buffer,0,512);
 
-	flags = mdev->gen_cnt[Flags] & ~(MDF_PrimaryInd|MDF_ConnectedInd);
+	flags = mdev->gen_cnt[Flags] & ~(MDF_Consistent|MDF_PrimaryInd|
+					 MDF_ConnectedInd|MDF_UpToDate);
 	if (mdev->state.s.role == Primary)        flags |= MDF_PrimaryInd;
 	if (mdev->state.s.conn >= WFReportParams) flags |= MDF_ConnectedInd;
+	if (mdev->state.s.disk >= Consistent)     flags |= MDF_Consistent;
+	if (mdev->state.s.disk >= UpToDate)       flags |= MDF_UpToDate;
 	mdev->gen_cnt[Flags] = flags;
 
 	for (i = Flags; i < GEN_CNT_SIZE; i++)
@@ -2127,15 +2164,7 @@
 	u32 me,other;
 
 	/* FIXME
-	 * we should not only rely on the consistent bit, but at least check
-	 * whether the rest of the gencounts is plausible, to detect a previous
-	 * split brain situation, and refuse anything until we are told
-	 * otherwise!
-	 *
-	 * And we should refuse to become SyncSource if we are not consistent!
-	 *
-	 * though DRBD is not to blame for it,
-	 * someone eventually will try to blame it ...
+	 * Take the UpToDate flag into account.
 	 */
 
 	me=mdev->gen_cnt[Flags] & MDF_Consistent;

Modified: trunk/drbd/drbd_receiver.c
===================================================================
--- trunk/drbd/drbd_receiver.c	2004-11-12 08:42:23 UTC (rev 1635)
+++ trunk/drbd/drbd_receiver.c	2004-11-12 11:51:55 UTC (rev 1636)
@@ -1102,7 +1102,7 @@
 	list_add(&e->w.list,&mdev->read_ee);
 	spin_unlock_irq(&mdev->ee_lock);
 
-	if(!inc_local(mdev) || (mdev->gen_cnt[Flags] & MDF_Consistent) == 0) {
+	if(!inc_local(mdev) || mdev->state.s.disk < UpToDate ) {
 		if (DRBD_ratelimit(5*HZ,5))
 			ERR("Can not satisfy peer's read request, no local data.\n");
 		drbd_send_ack(mdev,NegDReply,e);
@@ -1206,7 +1206,7 @@
 	drbd_dump_md(mdev,p,0);
 	// INFO("have_good=%d sync=%d\n", have_good, sync);
 
-	if (have_good > 0 && !drbd_md_test_flag(mdev,MDF_Consistent)) {
+	if (have_good > 0 && mdev->state.s.disk < Consistent ) {
 		/* doh. I cannot become SyncSource when I am inconsistent!
 		 */
 		ERR("I shall become SyncSource, but I am inconsistent!\n");
@@ -1290,8 +1290,7 @@
 {
 	Drbd_Parameter_Packet *p = (Drbd_Parameter_Packet*)h;
 	drbd_conns_t nconn;
-	drbd_disks_t npdsk;
-	drbd_state_t ns;
+	drbd_state_t ns,peer_state;
 	int consider_sync,rv;
 	sector_t p_size;
 
@@ -1388,16 +1387,6 @@
 		     (unsigned long)mdev->lo_usize);
 	}
 
-
-	if(p_size ) {
-		npdsk = Inconsistent;
- 		if (be32_to_cpu(p->gen_cnt[Flags]) & MDF_Consistent) {
-			npdsk = Consistent;
-		}
-	} else {
-		npdsk = Diskless;
-	}
-
 	if (mdev->state.s.conn == WFReportParams) {
 		INFO("Connection established.\n");
 	}
@@ -1408,11 +1397,13 @@
 			return FALSE;
 	}
 
+	peer_state.i = be32_to_cpu(p->state);
+
 	spin_lock_irq(&mdev->req_lock);
 	ns.i = mdev->state.i;
 	ns.s.conn = nconn;
-	ns.s.peer = be32_to_cpu(p->state);
-	ns.s.pdsk = npdsk;
+	ns.s.peer = peer_state.s.role;
+	ns.s.pdsk = peer_state.s.disk;
 	rv = _drbd_set_state(mdev,ns,ChgStateVerbose);
 	spin_unlock_irq(&mdev->req_lock);
 

Modified: trunk/drbd/drbd_req.c
===================================================================
--- trunk/drbd/drbd_req.c	2004-11-12 08:42:23 UTC (rev 1635)
+++ trunk/drbd/drbd_req.c	2004-11-12 11:51:55 UTC (rev 1636)
@@ -144,7 +144,7 @@
 	unsigned long sbnr,ebnr,bnr;
 	sector_t esector, nr_sectors;
 
-	if (drbd_md_test_flag(mdev,MDF_Consistent)) return 1;
+	if (mdev->state.s.disk == UpToDate) return 1;
 
 	nr_sectors = drbd_get_capacity(mdev->this_bdev);
 	esector = sector + (size>>9) -1;
@@ -255,7 +255,7 @@
 				dec_local(mdev);
 			}
 		}
-		remote = !local && mdev->state.s.pdsk >= Consistent;
+		remote = !local && mdev->state.s.pdsk >= UpToDate;//Consistent;
 	} else {
 		remote = 1;
 	}

Modified: trunk/drbd/drbd_strings.c
===================================================================
--- trunk/drbd/drbd_strings.c	2004-11-12 08:42:23 UTC (rev 1635)
+++ trunk/drbd/drbd_strings.c	2004-11-12 11:51:55 UTC (rev 1636)
@@ -64,6 +64,7 @@
 	[3] = "Refusing to make peer Primary without data",
 	[4] = "Refusing to be inconsistent on both nodes",
 	[5] = "Refusing to be syncing and diskless",
+	[6] = "Refusing to be Outdated while Connected",
 };
 
 const char* conns_to_name(drbd_conns_t s) {

Modified: trunk/drbd/drbd_worker.c
===================================================================
--- trunk/drbd/drbd_worker.c	2004-11-12 08:42:23 UTC (rev 1635)
+++ trunk/drbd/drbd_worker.c	2004-11-12 11:51:55 UTC (rev 1636)
@@ -401,8 +401,8 @@
 	mdev->rs_paused = 0;
 
 	drbd_request_state(mdev,NS3(conn,Connected,
-				    disk,Consistent,
-				    pdsk,Consistent));
+				    disk,UpToDate,
+				    pdsk,UpToDate));
 
 	drbd_md_write(mdev);
 
@@ -711,14 +711,7 @@
 	} else if (side == SyncSource) {
 		r = drbd_request_state(mdev,NS2(conn,SyncSource,
 						pdsk,Inconsistent));
-		/* If we are SyncSource we must be consistent.
-		 * FIXME this should be an assertion only,
-		 * otherwise it masks a logic bug somewhere else...
-		 */
-		ERR_IF (!drbd_md_test_flag(mdev,MDF_Consistent)) {
-			// FIXME this is actually a BUG()!
-			drbd_md_set_flag(mdev,MDF_Consistent);
-		}
+		D_ASSERT(mdev->state.s.disk == UpToDate);
 	}
 
 	if(r != 1) return;

Modified: trunk/drbd/linux/drbd.h
===================================================================
--- trunk/drbd/linux/drbd.h	2004-11-12 08:42:23 UTC (rev 1635)
+++ trunk/drbd/linux/drbd.h	2004-11-12 11:51:55 UTC (rev 1636)
@@ -204,8 +204,8 @@
 	Diskless,
 	Failed,         /* Becomes Diskless as soon as we told it the peer */
 	Inconsistent,
+	Consistent,     /* Might be Outdated, might be UpToDate ... */
 	Outdated,
-	Consistent,     /* Might be outdated, might be UpToDate ... */
 	UpToDate,
 	disk_mask=7
 } drbd_disks_t;
@@ -270,6 +270,7 @@
 #define DRBD_IOCTL_WAIT_SYNC        _IOR( DRBD_IOCTL_LETTER, 0x12, struct ioctl_wait )
 #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     _IO ( DRBD_IOCTL_LETTER, 0x15 )
 
 
 #endif

Modified: trunk/drbd/linux/drbd_config.h
===================================================================
--- trunk/drbd/linux/drbd_config.h	2004-11-12 08:42:23 UTC (rev 1635)
+++ trunk/drbd/linux/drbd_config.h	2004-11-12 11:51:55 UTC (rev 1636)
@@ -23,7 +23,7 @@
 extern const char * drbd_buildtag(void);
 
 #define REL_VERSION "0.8-pre1"
-#define API_VERSION 77
+#define API_VERSION 80
 #define PRO_VERSION 74
 
 //#define DBG_ALL_SYMBOLS // no static functs, improves quality of OOPS traces

Modified: trunk/user/drbdadm_main.c
===================================================================
--- trunk/user/drbdadm_main.c	2004-11-12 08:42:23 UTC (rev 1635)
+++ trunk/user/drbdadm_main.c	2004-11-12 11:51:55 UTC (rev 1636)
@@ -126,6 +126,7 @@
   { "secondary",         adm_generic_s,"secondary"       ,1,1 },
   { "invalidate",        adm_generic_l,"invalidate"      ,1,1 },
   { "invalidate_remote", adm_generic_l,"invalidate_remote",1,1 },
+  { "outdate",           adm_generic_s,"outdate"         ,1,1 },
   { "resize",            adm_resize,  0                  ,1,1 },
   { "syncer",            adm_syncer,  0                  ,1,1 },
   { "adjust",            adm_adjust,  0                  ,1,1 },

Modified: trunk/user/drbdmeta.c
===================================================================
--- trunk/user/drbdmeta.c	2004-11-12 08:42:23 UTC (rev 1635)
+++ trunk/user/drbdmeta.c	2004-11-12 11:51:55 UTC (rev 1636)
@@ -84,11 +84,13 @@
 	__MDF_PrimaryInd,
 	__MDF_ConnectedInd,
 	__MDF_FullSync,
+	__MDF_UpToDate,
 };
 #define MDF_Consistent      (1<<__MDF_Consistent)
 #define MDF_PrimaryInd      (1<<__MDF_PrimaryInd)
 #define MDF_ConnectedInd    (1<<__MDF_ConnectedInd)
 #define MDF_FullSync        (1<<__MDF_FullSync)
+#define MDF_UpToDate        (1<<__MDF_UpToDate)
 
 enum MetaDataIndex {
 	Flags,			/* Consistency flag,connected-ind,primary-ind */
@@ -180,14 +182,32 @@
 void md_disk_06_to_cpu(struct md_cpu *cpu, const struct md_on_disk_06 *disk)
 {
 	int i;
+	u32 flags;
+
 	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);
+
+	/* 06 does not have the UpToDate flag, set it according to
+	   the Consistent Flag */
+	flags = cpu->gc[Flags];
+	if( flags & MDF_Consistent) flags = flags | MDF_UpToDate;
+	cpu->gc[Flags]=flags;
 }
 
-void md_cpu_to_disk_06(struct md_on_disk_06 *disk, const struct md_cpu *cpu)
+void md_cpu_to_disk_06(struct md_on_disk_06 *disk, struct md_cpu *cpu)
 {
 	int i;
+	u32 flags;
+
+	/* Commulate the UpToDate flag into the consistent flag. */
+	flags = cpu->gc[Flags];
+	if(!((flags & MDF_Consistent) && (flags & MDF_UpToDate))) {
+		flags &= ~MDF_Consistent;
+	}
+	flags &= ~MDF_UpToDate;
+	cpu->gc[Flags]=flags;
+
 	for (i = 0; i < GEN_CNT_SIZE; i++)
 		disk->gc[i].be = cpu_to_be32(cpu->gc[i]);
 	disk->magic.be = cpu_to_be32(cpu->magic);
@@ -220,6 +240,7 @@
 void md_disk_07_to_cpu(struct md_cpu *cpu, const struct md_on_disk_07 *disk)
 {
 	int i;
+	u32 flags;
 	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);
@@ -228,11 +249,27 @@
 	cpu->al_offset = be32_to_cpu(disk->al_offset.be);
 	cpu->al_nr_extents = be32_to_cpu(disk->al_nr_extents.be);
 	cpu->bm_offset = be32_to_cpu(disk->bm_offset.be);
+
+	/* 07 does not have the UpToDate flag, set it according to
+	   the Consistent Flag */
+	flags = cpu->gc[Flags];
+	if( flags & MDF_Consistent) flags = flags | MDF_UpToDate;
+	cpu->gc[Flags]=flags;
 }
 
-void md_cpu_to_disk_07(struct md_on_disk_07 *disk, const struct md_cpu *cpu)
+void md_cpu_to_disk_07(struct md_on_disk_07 *disk, struct md_cpu *cpu)
 {
 	int i;
+	u32 flags;
+
+	/* Commulate the UpToDate flag into the consistent flag. */
+	flags = cpu->gc[Flags];
+	if(!((flags & MDF_Consistent) && (flags & MDF_UpToDate))) {
+		flags &= ~MDF_Consistent;
+	}
+	flags &= ~MDF_UpToDate;
+	cpu->gc[Flags]=flags;
+
 	disk->la_kb.be = cpu_to_be64(cpu->la_sect >> 1);
 	for (i = 0; i < GEN_CNT_SIZE; i++)
 		disk->gc[i].be = cpu_to_be32(cpu->gc[i]);
@@ -596,7 +633,7 @@
 
 void printf_gc(const struct md_cpu *md)
 {
-	printf("%d:%d:%d:%d:%d:%d:%d:%d\n",
+	printf("%d:%d:%d:%d:%d:%d:%d:%d:%d\n",
 	       md->gc[Flags] & MDF_Consistent ? 1 : 0,
 	       md->gc[HumanCnt],
 	       md->gc[TimeoutCnt],
@@ -604,7 +641,8 @@
 	       md->gc[ArbitraryCnt],
 	       md->gc[Flags] & MDF_PrimaryInd ? 1 : 0,
 	       md->gc[Flags] & MDF_ConnectedInd ? 1 : 0,
-	       md->gc[Flags] & MDF_FullSync ? 1 : 0);
+	       md->gc[Flags] & MDF_FullSync ? 1 : 0,
+	       md->gc[Flags] & MDF_UpToDate ? 1 : 0);
 }
 
 /******************************************
@@ -1053,16 +1091,17 @@
 		return -1;
 
 	printf("\n"
-	       "                                        WantFullSync |\n"
-	       "                                  ConnectedInd |     |\n"
-	       "                               lastState |     |     |\n"
-	       "                      ArbitraryCnt |     |     |     |\n"
-	       "                ConnectedCnt |     |     |     |     |\n"
-	       "            TimeoutCnt |     |     |     |     |     |\n"
-	       "        HumanCnt |     |     |     |     |     |     |\n"
-	       "Consistent |     |     |     |     |     |     |     |\n"
-	       "   --------+-----+-----+-----+-----+-----+-----+-----+\n"
-	       "       %3s | %3d | %3d | %3d | %3d | %3s | %3s | %3s  \n"
+	       "                                                  UpToDate |\n"
+	       "                                        WantFullSync |     |\n"
+	       "                                  ConnectedInd |     |     |\n"
+	       "                               lastState |     |     |     |\n"
+	       "                      ArbitraryCnt |     |     |     |     |\n"
+	       "                ConnectedCnt |     |     |     |     |     |\n"
+	       "            TimeoutCnt |     |     |     |     |     |     |\n"
+	       "        HumanCnt |     |     |     |     |     |     |     |\n"
+	       "Consistent |     |     |     |     |     |     |     |     |\n"
+	       "   --------+-----+-----+-----+-----+-----+-----+-----+-----+\n"
+	       "       %3s | %3d | %3d | %3d | %3d | %3s | %3s | %3s | %3s  \n"
 	       "\n",
 	       cfg->md.gc[Flags] & MDF_Consistent ? "1/c" : "0/i",
 	       cfg->md.gc[HumanCnt],
@@ -1071,8 +1110,10 @@
 	       cfg->md.gc[ArbitraryCnt],
 	       cfg->md.gc[Flags] & MDF_PrimaryInd ? "1/p" : "0/s",
 	       cfg->md.gc[Flags] & MDF_ConnectedInd ? "1/c" : "0/n",
-	       cfg->md.gc[Flags] & MDF_FullSync ? "1/y" : "0/n");
+	       cfg->md.gc[Flags] & MDF_FullSync ? "1/y" : "0/n",
+	       cfg->md.gc[Flags] & MDF_UpToDate ? "1/y" : "0/n");
 
+
 	if (cfg->md.la_sect) {
 		printf("last agreed size: %s\n",
 		       ppsize(ppb, cfg->md.la_sect >> 1));

Modified: trunk/user/drbdsetup.c
===================================================================
--- trunk/user/drbdsetup.c	2004-11-12 08:42:23 UTC (rev 1635)
+++ trunk/user/drbdsetup.c	2004-11-12 11:51:55 UTC (rev 1636)
@@ -105,6 +105,7 @@
 int cmd_net_conf(int drbd_fd,char** argv,int argc,struct option *options);
 int cmd_disk_conf(int drbd_fd,char** argv,int argc,struct option *options);
 int cmd_disk_size(int drbd_fd,char** argv,int argc,struct option *options);
+int cmd_outdate(int drbd_fd,char** argv,int argc,struct option *options);
 int cmd_disconnect(int drbd_fd,char** argv,int argc,struct option *options);
 int cmd_show(int drbd_fd,char** argv,int argc,struct option *options);
 int cmd_syncer(int drbd_fd,char** argv,int argc,struct option *options);
@@ -168,6 +169,7 @@
    (struct option[]) {
      { "size",  required_argument,      0, 'd' },
      { 0,            0,                 0, 0 } } },
+  {"outdate", cmd_outdate,           0, 0, },
   {"disconnect", cmd_disconnect,     0, 0, },
   {"state", cmd_state,               0, 0, },
   {"cstate", cmd_cstate,              0, 0, },
@@ -960,6 +962,22 @@
   return 0;
 }
 
+int cmd_outdate(int drbd_fd,char** argv,int argc,struct option *options)
+{
+  int err;
+
+  err=ioctl(drbd_fd,DRBD_IOCTL_OUTDATE_DISK);
+  if(err)
+    {
+      err=errno;
+      PERROR("ioctl(,OUTDATE_DISK,) failed");
+      if(err==EISCONN)
+	fprintf(stderr,"Only possible when not connected to the peer.\n");
+      return 20;
+    }
+  return 0;
+}
+
 int cmd_down(int drbd_fd,char** argv,int argc,struct option *options)
 {
   int err;



More information about the drbd-cvs mailing list