[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