[DRBD-cvs] svn commit by phil - r2080 - in trunk/drbd: . linux - Forward ported the patch that prevents shrinking of con

drbd-cvs at lists.linbit.com drbd-cvs at lists.linbit.com
Fri Feb 24 15:20:21 CET 2006


Author: phil
Date: 2006-02-24 15:20:19 +0100 (Fri, 24 Feb 2006)
New Revision: 2080

Modified:
   trunk/drbd/drbd_fs.c
   trunk/drbd/drbd_int.h
   trunk/drbd/drbd_main.c
   trunk/drbd/drbd_receiver.c
   trunk/drbd/linux/drbd.h
Log:
Forward ported the patch that prevents shrinking of consistent devices.


Modified: trunk/drbd/drbd_fs.c
===================================================================
--- trunk/drbd/drbd_fs.c	2006-02-24 11:43:09 UTC (rev 2079)
+++ trunk/drbd/drbd_fs.c	2006-02-24 14:20:19 UTC (rev 2080)
@@ -87,15 +87,32 @@
 		break;
 	}
 }
+
+char* ppsize(char* buf, size_t size)
+{
+	// Needs 9 bytes at max.
+	static char units[] = { 'K','M','G','T','P','E' };
+	int base = 0;
+	while (size >= 10000 ) {
+		size = size >> 10;
+		base++;
+	}
+	sprintf(buf,"%ld %cB",(long)size,units[base]);
+
+	return buf;
+}
+
 /* You should call drbd_md_sync() after calling this.
  */
-STATIC int do_determin_dev_size(struct Drbd_Conf* mdev);
 int drbd_determin_dev_size(struct Drbd_Conf* mdev)
 {
 	sector_t prev_first_sect, prev_size; // previous meta location
 	sector_t la_size;
+	sector_t size;
+	char ppb[10];
+
 	int md_moved, la_size_changed;
-	int rv;
+	int rv=0;
 
 	wait_event(mdev->al_wait, lc_try_lock(mdev->act_log));
 
@@ -105,7 +122,32 @@
 
 	// TODO: should only be some assert here, not (re)init...
 	drbd_md_set_sector_offsets(mdev,mdev->bc);
-	rv = do_determin_dev_size(mdev);
+
+	size = drbd_new_dev_size(mdev,mdev->bc);
+
+	if( drbd_get_capacity(mdev->this_bdev) != size ) {
+		int err;
+		err = drbd_bm_resize(mdev,size);
+		if (unlikely(err)) {
+			/* currently there is only one error: ENOMEM! */
+			size = drbd_bm_capacity(mdev)>>1;
+			if (size == 0) {
+				ERR("OUT OF MEMORY! 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);
+			}
+			rv = err;
+		}
+		// racy, see comments above.
+		drbd_set_my_capacity(mdev,size);
+		mdev->bc->md.la_size_sect = size;
+		INFO("size = %s (%lu KB)\n",ppsize(ppb,size>>1),
+		     (unsigned long)size>>1);
+	}
 	if (rv < 0) goto out;
 
 	la_size_changed = (la_size != mdev->bc->md.la_size_sect);
@@ -120,7 +162,7 @@
 	}
 
 	if ( la_size_changed || md_moved ) {
-		if( inc_local_md_only(mdev)) {
+		if( inc_md_only(mdev,Attaching) ) {
 			drbd_al_shrink(mdev); // All extents inactive.
 			drbd_bm_write(mdev);  // write bitmap
 			// Write mdev->la_size to on disk.
@@ -134,52 +176,20 @@
 	return rv;
 }
 
-char* ppsize(char* buf, size_t size)
+sector_t 
+drbd_new_dev_size(struct Drbd_Conf* mdev, struct drbd_backing_dev *bdev)
 {
-	// Needs 9 bytes at max.
-	static char units[] = { 'K','M','G','T','P','E' };
-	int base = 0;
-	while (size >= 10000 ) {
-		size = size >> 10;
-		base++;
-	}
-	sprintf(buf,"%ld %cB",(long)size,units[base]);
-
-	return buf;
-}
-
-
-/* Returns 1 if there is a disk-less node, 0 if both nodes have a disk.
- * -ENOMEM if we could not allocate the bitmap
- */
-/*
- * *_size is in sectors.
- *
- * FIXME
- * since this is done by drbd receiver as well as from drbdsetup,
- * this actually needs proper locking!
- * drbd_bm_resize already protects itself with a mutex.
- * but again, this is a state change, and thus should be serialized with other
- * state changes on a more general level already.
- */
-STATIC int do_determin_dev_size(struct Drbd_Conf* mdev)
-{
 	sector_t p_size = mdev->p_size;   // partner's disk size.
-	sector_t la_size = mdev->bc->md.la_size_sect; // last agreed size.
+	sector_t la_size = bdev->md.la_size_sect; // last agreed size.
 	sector_t m_size; // my size
-	sector_t u_size = mdev->bc->u_size; // size requested by user.
+	sector_t u_size = bdev->u_size; // size requested by user.
 	sector_t size=0;
-	int rv;
-	char ppb[10];
 
-	m_size = drbd_get_max_capacity(mdev);
-	INFO("msize = %llu\n", (unsigned long long) m_size);
+	m_size = drbd_get_max_capacity(bdev);
 
 	if(p_size && m_size) {
-		rv=0;
 		size=min_t(sector_t,p_size,m_size);
 	} else {
-		rv=1;
 		if(la_size) {
 			size=la_size;
 			if(m_size && m_size < size) size=m_size;
@@ -203,31 +213,7 @@
 		}
 	}
 
-	if( drbd_get_capacity(mdev->this_bdev) != size ) {
-		int err;
-		err = drbd_bm_resize(mdev,size);
-		if (unlikely(err)) {
-			/* currently there is only one error: ENOMEM! */
-			size = drbd_bm_capacity(mdev)>>1;
-			if (size == 0) {
-				ERR("OUT OF MEMORY! 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);
-			}
-			rv = err;
-		}
-		// racy, see comments above.
-		drbd_set_my_capacity(mdev,size);
-		mdev->bc->md.la_size_sect = size;
-		INFO("size = %s (%lu KB)\n",ppsize(ppb,size>>1),
-		     (unsigned long)size>>1);
-	}
-
-	return rv;
+	return size;
 }
 
 /** 
@@ -456,6 +442,13 @@
 		goto release_bdev3_fail_ioctl;
 	}
 
+	// Prevent shrinking of consistent devices !
+	if(drbd_md_test_flag(nbc,MDF_Consistent) &&
+	   drbd_new_dev_size(mdev,nbc) < nbc->md.la_size_sect) {
+		retcode = LDDeviceTooSmall;
+		goto release_bdev3_fail_ioctl;
+	}
+
 	// Point of no return reached.
 
 	D_ASSERT(mdev->bc == NULL);
@@ -490,16 +483,16 @@
 	 * degraded but active "cluster" after a certain timeout.
 	 */
 	clear_bit(USE_DEGR_WFC_T,&mdev->flags);
-	if ( mdev->state != Primary &&
-	     drbd_md_test_flag(mdev,MDF_PrimaryInd) &&
-	    !drbd_md_test_flag(mdev,MDF_ConnectedInd) ) {
+	if ( mdev->state.role != Primary &&
+	     drbd_md_test_flag(mdev->bc,MDF_PrimaryInd) &&
+	    !drbd_md_test_flag(mdev->bc,MDF_ConnectedInd) ) {
 		set_bit(USE_DEGR_WFC_T,&mdev->flags);
 	}
 
 	drbd_bm_lock(mdev); // racy...
 	drbd_determin_dev_size(mdev);
 
-	if (drbd_md_test_flag(mdev,MDF_FullSync)) {
+	if (drbd_md_test_flag(mdev->bc,MDF_FullSync)) {
 		INFO("Assuming that all blocks are out of sync (aka FullSync)\n");
 		drbd_bm_set_all(mdev);
 		drbd_bm_write(mdev);
@@ -510,7 +503,7 @@
 	}
 
 	drbd_al_read_log(mdev);
-	if (drbd_md_test_flag(mdev,MDF_PrimaryInd)) {
+	if (drbd_md_test_flag(mdev->bc,MDF_PrimaryInd)) {
 		drbd_al_apply_to_bm(mdev);
 		drbd_al_to_on_disk_bm(mdev);
 	}
@@ -530,8 +523,8 @@
 		   If MDF_WasUpToDate 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_WasUpToDate)) {
+		if(drbd_md_test_flag(mdev->bc,MDF_Consistent)) {
+			if(drbd_md_test_flag(mdev->bc,MDF_WasUpToDate)) {
 				nds = Consistent;
 			} else {
 				nds = Outdated;

Modified: trunk/drbd/drbd_int.h
===================================================================
--- trunk/drbd/drbd_int.h	2006-02-24 11:43:09 UTC (rev 2079)
+++ trunk/drbd/drbd_int.h	2006-02-24 14:20:19 UTC (rev 2080)
@@ -874,7 +874,7 @@
 extern void drbd_uuid_set_bm(drbd_dev *mdev, u64 val);
 extern void drbd_md_set_flag(drbd_dev *mdev, int flags);
 extern void drbd_md_clear_flag(drbd_dev *mdev, int flags);
-extern int drbd_md_test_flag(drbd_dev *mdev, int flag);
+extern int drbd_md_test_flag(struct drbd_backing_dev *, int);
 extern void drbd_md_mark_dirty(drbd_dev *mdev);
 
 /* Meta data layout
@@ -1068,6 +1068,7 @@
 
 // drbd_fs.c
 extern char* ppsize(char* buf, size_t size);
+extern sector_t drbd_new_dev_size(struct Drbd_Conf*, struct drbd_backing_dev*);
 extern int drbd_determin_dev_size(drbd_dev*);
 extern void drbd_setup_queue_param(drbd_dev *mdev, unsigned int);
 extern int drbd_set_role(drbd_dev *mdev, int *arg);
@@ -1275,17 +1276,17 @@
 }
 
 /* returns the capacity we announce to out peer */
-static inline sector_t drbd_get_max_capacity(drbd_dev *mdev)
+static inline sector_t drbd_get_max_capacity(struct drbd_backing_dev *bdev)
 {
-	switch (mdev->bc->md_index) {
+	switch (bdev->md_index) {
 	case DRBD_MD_INDEX_INTERNAL:
 	case DRBD_MD_INDEX_FLEX_INT:
-		return drbd_get_capacity(mdev->bc->backing_bdev)
-			? drbd_md_first_sector(mdev->bc)
+		return drbd_get_capacity(bdev->backing_bdev)
+			? drbd_md_first_sector(bdev)
 			: 0;
 	case DRBD_MD_INDEX_FLEX_EXT:
 	default:
-		return drbd_get_capacity(mdev->bc->backing_bdev);
+		return drbd_get_capacity(bdev->backing_bdev);
 	}
 }
 

Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c	2006-02-24 11:43:09 UTC (rev 2079)
+++ trunk/drbd/drbd_main.c	2006-02-24 14:20:19 UTC (rev 2080)
@@ -504,8 +504,8 @@
 	ok = drbd_send_state(mdev);
 	WARN("Notified peer that my disk is broken.\n");
 
-	D_ASSERT(drbd_md_test_flag(mdev,MDF_FullSync));
-	D_ASSERT(!drbd_md_test_flag(mdev,MDF_Consistent));
+	D_ASSERT(drbd_md_test_flag(mdev->bc,MDF_FullSync));
+	D_ASSERT(!drbd_md_test_flag(mdev->bc,MDF_Consistent));
 	drbd_md_sync(mdev);
 
 	if ( wait_event_interruptible_timeout(mdev->cstate_wait,
@@ -1109,7 +1109,7 @@
 
 	if(inc_md_only(mdev,Attaching)) {
 		D_ASSERT(mdev->bc->backing_bdev);
-		d_size = drbd_get_max_capacity(mdev);
+		d_size = drbd_get_max_capacity(mdev->bc);
 		p.u_size = cpu_to_be64(mdev->bc->u_size);
 		dec_local(mdev);
 	} else d_size = 0;
@@ -1160,7 +1160,7 @@
 	p  = vmalloc(PAGE_SIZE); // sleeps. cannot fail.
 	buffer = (unsigned long*)p->payload;
 
-	if (drbd_md_test_flag(mdev,MDF_FullSync)) {
+	if (drbd_md_test_flag(mdev->bc,MDF_FullSync)) {
 		drbd_bm_set_all(mdev);
 		drbd_bm_write(mdev);
 		if (unlikely(mdev->state.disk <= Failed )) {
@@ -2630,10 +2630,9 @@
 		mdev->bc->md.flags &= ~flag;
 	}
 }
-int drbd_md_test_flag(drbd_dev *mdev, int flag)
+int drbd_md_test_flag(struct drbd_backing_dev *bdev, int flag)
 {
-	MUST_HOLD(mdev->req_lock);
-	return ((mdev->bc->md.flags & flag) != 0);
+	return ((bdev->md.flags & flag) != 0);
 }
 
 STATIC void md_sync_timer_fn(unsigned long data)

Modified: trunk/drbd/drbd_receiver.c
===================================================================
--- trunk/drbd/drbd_receiver.c	2006-02-24 11:43:09 UTC (rev 2079)
+++ trunk/drbd/drbd_receiver.c	2006-02-24 14:20:19 UTC (rev 2080)
@@ -1717,7 +1717,7 @@
 	}
 
 	if (hg > 0) { // become sync source.
-		D_ASSERT(drbd_md_test_flag(mdev,MDF_Consistent));
+		D_ASSERT(drbd_md_test_flag(mdev->bc,MDF_Consistent));
 		rv = WFBitMapS;
 	} else if (hg < 0) { // become sync target
 		drbd_md_clear_flag(mdev,MDF_Consistent);
@@ -1831,7 +1831,7 @@
 {
 	Drbd_Sizes_Packet *p = (Drbd_Sizes_Packet*)h;
 	unsigned int max_seg_s;
-	sector_t p_size, p_usize;
+	sector_t p_size, p_usize, my_usize;
 	drbd_conns_t nconn;
 
 	ERR_IF(h->length != (sizeof(*p)-sizeof(*h))) return FALSE;
@@ -1861,11 +1861,25 @@
 			p_usize = min_not_zero(mdev->bc->u_size, p_usize);
 		}
 
+		my_usize = mdev->bc->u_size;
+
 		if( mdev->bc->u_size != p_usize ) {
 			mdev->bc->u_size = p_usize;
 			INFO("Peer sets u_size to %lu KB\n",
 			     (unsigned long)mdev->bc->u_size);
 		}
+
+		// Never shrink a device with usable data.
+		if(drbd_new_dev_size(mdev,mdev->bc) < 
+		   drbd_get_capacity(mdev->this_bdev) &&
+		   mdev->state.disk >= Outdated ) {
+			dec_local(mdev);
+			ERR("The peer's disk size is too small!\n");
+			drbd_force_state(mdev,NS(conn,StandAlone));
+			drbd_thread_stop_nowait(&mdev->receiver);
+			mdev->bc->u_size = my_usize;
+			return FALSE;
+		}
 		dec_local(mdev);
 	}
 #undef min_not_zero

Modified: trunk/drbd/linux/drbd.h
===================================================================
--- trunk/drbd/linux/drbd.h	2006-02-24 11:43:09 UTC (rev 2079)
+++ trunk/drbd/linux/drbd.h	2006-02-24 14:20:19 UTC (rev 2080)
@@ -232,7 +232,7 @@
 	Attaching,      /* In the process of reading the meta-data */
 	Inconsistent,
 	Outdated,
-	DUnknown,
+	DUnknown,       /* Only used for the peer, never for myself */
 	Consistent,     /* Might be Outdated, might be UpToDate ... */
 	UpToDate,
 	disk_mask=15



More information about the drbd-cvs mailing list