[DRBD-cvs] svn commit by phil - r2064 - branches/drbd-0.7/drbd - It is no longer possible that a consistent device shrin

drbd-cvs at lists.linbit.com drbd-cvs at lists.linbit.com
Thu Feb 9 13:40:52 CET 2006


Author: phil
Date: 2006-02-09 13:40:48 +0100 (Thu, 09 Feb 2006)
New Revision: 2064

Modified:
   branches/drbd-0.7/drbd/drbd_fs.c
   branches/drbd-0.7/drbd/drbd_int.h
   branches/drbd-0.7/drbd/drbd_receiver.c
Log:
It is no longer possible that a consistent device shrinks due to
successfull connection to the peer or due to successfull attach.



Modified: branches/drbd-0.7/drbd/drbd_fs.c
===================================================================
--- branches/drbd-0.7/drbd/drbd_fs.c	2006-02-09 11:26:18 UTC (rev 2063)
+++ branches/drbd-0.7/drbd/drbd_fs.c	2006-02-09 12:40:48 UTC (rev 2064)
@@ -68,19 +68,70 @@
 }
 #endif
 
-STATIC int do_determin_dev_size(struct Drbd_Conf* mdev);
+char* ppsize(char* buf, size_t size) 
+{
+	// Needs 9 bytes at max.
+	static char units[] = { 'K','M','G','T' };
+	int base = 0;
+	while (size >= 10000 ) {
+		size = size >> 10;
+		base++;
+	}
+	sprintf(buf,"%ld %cB",(long)size,units[base]);
+
+	return buf;
+}
+
+/* Returns -ENOMEM if we could not allocate the bitmap
+ *
+ * currently *_size is in KB.
+ *
+ * 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.
+ */
 int drbd_determin_dev_size(struct Drbd_Conf* mdev)
 {
 	sector_t pmdss; // previous meta data start sector
 	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));
 	pmdss = drbd_md_ss(mdev);
 	la_size = mdev->la_size;
 
-	rv = do_determin_dev_size(mdev);
+	size = drbd_new_dev_size(mdev);
+
+	if( (drbd_get_capacity(mdev->this_bdev)>>1) != size ) {
+		int err;
+		err = drbd_bm_resize(mdev,size<<1); // wants sectors
+		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<<1);
+		mdev->la_size = size;
+		INFO("size = %s (%lu KB)\n",ppsize(ppb,size),
+		     (unsigned long)size);
+	}
 	if (rv < 0) goto out;
 
 	la_size_changed = (la_size != mdev->la_size);
@@ -103,46 +154,16 @@
 	return rv;
 }
 
-char* ppsize(char* buf, size_t size) 
-{
-	// Needs 9 bytes at max.
-	static char units[] = { 'K','M','G','T' };
-	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
- */
 /*
- * THINK do we want the size to be KB or sectors ?
- * note, *_capacity operates in 512 byte sectors!!
- *
  * currently *_size is in KB.
- *
- * 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 drbd_new_dev_size(struct Drbd_Conf* mdev)
 {
 	sector_t p_size = mdev->p_size;  // partner's disk size.
 	sector_t la_size = mdev->la_size; // last agreed size.
 	sector_t m_size; // my size
 	sector_t u_size = mdev->lo_usize; // size requested by user.
 	sector_t size=0;
-	int rv;
-	char ppb[10];
 
 	m_size = drbd_get_capacity(mdev->backing_bdev)>>1;
 
@@ -152,10 +173,8 @@
 	}
 
 	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;
@@ -179,31 +198,7 @@
 		}
 	}
 
-	if( (drbd_get_capacity(mdev->this_bdev)>>1) != size ) {
-		int err;
-		err = drbd_bm_resize(mdev,size<<1); // wants sectors
-		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<<1);
-		mdev->la_size = size;
-		INFO("size = %s (%lu KB)\n",ppsize(ppb,size),
-		     (unsigned long)size);
-	}
-
-	return rv;
+	return size;
 }
 
 /* checks that the al lru is of requested size, and if neccessary tries to
@@ -507,6 +502,21 @@
 	}
 
 	drbd_bm_lock(mdev); // racy...
+
+	if(drbd_md_test_flag(mdev,MDF_Consistent) &&
+	   drbd_new_dev_size(mdev) < mdev->la_size ) {
+		D_ASSERT(mdev->cstate == Unconfigured);
+		D_ASSERT(mput == 1);
+		/* Do not attach a too small disk.*/
+		drbd_bm_unlock(mdev);
+		ERR("Lower device smaller than last agreed size!\n");
+		drbd_free_ll_dev(mdev);
+		set_cstate(mdev,Unconfigured);
+		retcode = LDDeviceTooSmall;
+		module_put(THIS_MODULE);
+		if (put_user(retcode, &arg->ret_code)) return -EFAULT;
+		return -EINVAL;
+	}
 	if (drbd_determin_dev_size(mdev) < 0) {
 		/* could not allocate bitmap.
 		 * try to undo ... */

Modified: branches/drbd-0.7/drbd/drbd_int.h
===================================================================
--- branches/drbd-0.7/drbd/drbd_int.h	2006-02-09 11:26:18 UTC (rev 2063)
+++ branches/drbd-0.7/drbd/drbd_int.h	2006-02-09 12:40:48 UTC (rev 2064)
@@ -1044,6 +1044,7 @@
 // drbd_fs.c
 extern char* ppsize(char* buf, size_t size);
 extern int drbd_determin_dev_size(drbd_dev*);
+extern sector_t drbd_new_dev_size(struct Drbd_Conf*);
 extern int drbd_set_state(drbd_dev *mdev,Drbd_State newstate);
 extern int drbd_ioctl(struct inode *inode, struct file *file,
 		      unsigned int cmd, unsigned long arg);
@@ -1145,6 +1146,14 @@
 
 #include "drbd_compat_wrappers.h"
 
+static inline int drbd_disk_less_node_present(struct Drbd_Conf* mdev)
+{
+	sector_t p_size = mdev->p_size;
+	sector_t m_size = drbd_get_capacity(mdev->backing_bdev);
+
+	return ! ( p_size && m_size ) ;
+}
+
 static inline void
 drbd_flush_signals(struct task_struct *t)
 {

Modified: branches/drbd-0.7/drbd/drbd_receiver.c
===================================================================
--- branches/drbd-0.7/drbd/drbd_receiver.c	2006-02-09 11:26:18 UTC (rev 2063)
+++ branches/drbd-0.7/drbd/drbd_receiver.c	2006-02-09 12:40:48 UTC (rev 2064)
@@ -1379,7 +1379,7 @@
 	Drbd_Parameter_Packet *p = (Drbd_Parameter_Packet*)h;
 	int consider_sync;
 	int oo_state,i;
-	sector_t p_size, p_usize;
+	sector_t p_size, p_usize, my_usize;
 
 	if (h->length != (sizeof(*p)-sizeof(*h))) {
 		ERR("Incompatible packet size of Parameter packet!\n");
@@ -1472,22 +1472,28 @@
 		 * just do what the peer suggests */
 	}
 #undef min_not_zero
-	if( mdev->lo_usize != p_usize ) {
+
+	my_usize = mdev->lo_usize;
+
+	if( mdev->lo_usize > p_usize ) {
 		mdev->lo_usize = p_usize;
 		INFO("Peer sets u_size to %lu KB\n",
 		     (unsigned long)mdev->lo_usize);
 	}
 
+	if( drbd_new_dev_size(mdev) <
+	    (drbd_get_capacity(mdev->this_bdev)>>1) &&
+	    mdev->gen_cnt[Flags] & MDF_Consistent ) {
+		ERR("The peer's disk size is too small!\n");
+		set_cstate(mdev,StandAlone);
+		drbd_thread_stop_nowait(&mdev->receiver);
+		mdev->lo_usize = my_usize;
+		return FALSE;
+	}
 
-/*lge:
- * FIXME
- * please get the order of tests (re)settings for consider_sync
- * right, and comment them!
- */
-
 	consider_sync = (mdev->cstate == WFReportParams);
-	if(drbd_determin_dev_size(mdev)) consider_sync=0;
-
+	drbd_determin_dev_size(mdev);
+	if(drbd_disk_less_node_present(mdev)) consider_sync=0;
 	if(test_bit(DISKLESS, &mdev->flags)) consider_sync=0;
 
 	drbd_bm_unlock(mdev); // }



More information about the drbd-cvs mailing list