[DRBD-cvs] drbd by phil; Finally fixed the bitmap problems: * drb...
drbd-user@lists.linbit.com
drbd-user@lists.linbit.com
Mon, 5 Jul 2004 21:04:16 +0200 (CEST)
DRBD CVS committal
Author : phil
Module : drbd
Dir : drbd/drbd
Modified Files:
Tag: rel-0_7-branch
drbd_bitmap.c
Log Message:
Finally fixed the bitmap problems:
* drbd_bm_merge_lel() and drbd_bm_set_lel() had a serious bug. The
number parameter was used as counter in the while loop, and
afterwards in the if statement. Fixed with the new variable "n".
* Made drbd_clear_surplus() more convenient. Now it returns the number
of bits it cleared.
* Made drbd_clear_surplus() deal with a bitmap array which is one
word too big. [We do this to be compatible to 64 bit machines.]
===================================================================
RCS file: /var/lib/cvs/drbd/drbd/drbd/Attic/drbd_bitmap.c,v
retrieving revision 1.1.2.8
retrieving revision 1.1.2.9
diff -u -3 -r1.1.2.8 -r1.1.2.9
--- drbd_bitmap.c 5 Jul 2004 13:57:44 -0000 1.1.2.8
+++ drbd_bitmap.c 5 Jul 2004 19:04:11 -0000 1.1.2.9
@@ -142,7 +142,20 @@
#endif
// }
+/* debugging aid
+STATIC void bm_end_info(drbd_dev *mdev)
+{
+ struct drbd_bitmap *b = mdev->bitmap;
+ size_t w = b->bm_bits >> LN2_BPL;
+
+ INFO("bm_set=%lu\n",b->bm_set);
+ INFO("bm[%d]=0x%lX\n",w,b->bm[w++]);
+ if ( w < b->bm_words ) {
+ INFO("bm[%d]=0x%lX\n",w,b->bm[w++]);
+ }
+}
+*/
/* long word offset of _bitmap_ sector */
#define S2W(s) ((s)<<(BM_EXT_SIZE_B-BM_BLOCK_SIZE_B-LN2_BPL))
@@ -195,11 +208,23 @@
/*
* since (b->bm_bits % BITS_PER_LONG) != 0,
* this masks out the remaining bits.
+ * Rerturns the number of bits cleared.
*/
-static inline void bm_clear_surplus(struct drbd_bitmap * b)
+STATIC int bm_clear_surplus(struct drbd_bitmap * b)
{
const unsigned long mask = (1 << (b->bm_bits & (BITS_PER_LONG-1))) -1;
- if (mask) b->bm[b->bm_words-1] &= mask;
+ size_t w = b->bm_bits >> LN2_BPL;
+ int cleared;
+
+ cleared = hweight_long(b->bm[w] & ~mask);
+ b->bm[w++] &= mask;
+
+ if ( w < b->bm_words ) {
+ cleared += hweight_long(b->bm[w]);
+ b->bm[w++]=0;
+ }
+
+ return cleared;
}
#define BM_SECTORS_PER_BIT (BM_BLOCK_SIZE/512)
@@ -243,7 +268,7 @@
bits = ALIGN(capacity,BM_SECTORS_PER_BIT)
>> (BM_BLOCK_SIZE_B-9);
- /* if we would use
+ /* if we would use
words = ALIGN(bits,BITS_PER_LONG) >> LN2_BPL;
a 32bit host could present the wrong number of words
to a 64bit host.
@@ -253,7 +278,6 @@
D_ASSERT(bits < ((MD_RESERVED_SIZE<<1)-MD_BM_OFFSET)<<12 );
if ( words == b->bm_words ) {
- int i;
/* optimize: capacity has changed,
* but only within one long word worth of bits.
* just update the bm_dev_capacity and bm_bits members.
@@ -261,13 +285,11 @@
spin_lock_irq(&b->bm_lock);
b->bm_bits = bits;
b->bm_dev_capacity = capacity;
- i = hweight_long(b->bm[words-1]);
- bm_clear_surplus(b);
- b->bm_set += hweight_long(b->bm[words-1]) - i;
+ b->bm_set -= bm_clear_surplus(b);
spin_unlock_irq(&b->bm_lock);
goto out;
} else {
- /* one extra long to catch off by one errors */
+ /* one extra long to catch off by one errors */
bytes = (words+1)*sizeof(long);
nbm = vmalloc(bytes);
if (!nbm) {
@@ -348,6 +370,7 @@
struct drbd_bitmap *b = mdev->bitmap;
unsigned long *bm;
unsigned long word, bits;
+ size_t n = number;
D_BUG_ON(!(b && b->bm));
D_BUG_ON(offset >= b->bm_words);
@@ -359,16 +382,14 @@
spin_lock_irq(&b->bm_lock);
// BM_PARANOIA_CHECK(); no.
bm = b->bm + offset;
- while(number--) {
+ while(n--) {
bits = hweight_long(*bm);
word = *bm | lel_to_cpu(*buffer++);
*bm++ = word;
b->bm_set += hweight_long(word) - bits;
}
if (offset+number == b->bm_words) {
- bits = hweight_long(b->bm[b->bm_words-1]);
- bm_clear_surplus(b);
- b->bm_set -= bits - hweight_long(b->bm[b->bm_words-1]);
+ b->bm_set -= bm_clear_surplus(b);
}
spin_unlock_irq(&b->bm_lock);
}
@@ -382,6 +403,7 @@
struct drbd_bitmap *b = mdev->bitmap;
unsigned long *bm;
unsigned long word, bits;
+ size_t n = number;
D_BUG_ON(!(b && b->bm));
D_BUG_ON(offset >= b->bm_words);
@@ -393,16 +415,14 @@
spin_lock_irq(&b->bm_lock);
// BM_PARANOIA_CHECK(); no.
bm = b->bm + offset;
- while(number--) {
+ while(n--) {
bits = hweight_long(*bm);
word = lel_to_cpu(*buffer++);
*bm++ = word;
b->bm_set += hweight_long(word) - bits;
}
if (offset+number == b->bm_words) {
- bits = hweight_long(b->bm[b->bm_words-1]);
- bm_clear_surplus(b);
- b->bm_set -= bits - hweight_long(b->bm[b->bm_words-1]);
+ b->bm_set -= bm_clear_surplus(b);
}
spin_unlock_irq(&b->bm_lock);
}
@@ -784,10 +804,8 @@
n = e-s;
memset(b->bm+s,-1,n*sizeof(long));
b->bm_set += n*BITS_PER_LONG - count;
- if (e == b->bm_words) {
- bm_clear_surplus(b);
- b->bm_set -= BITS_PER_LONG -
- (b->bm_bits & (BITS_PER_LONG-1));
+ if (e == b->bm_bits >> LN2_BPL) {
+ b->bm_set -= bm_clear_surplus(b);
}
} else {
D_ASSERT(0);