[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