[DRBD-cvs] drbd by phil; An excellent patch by LGE * A generic fi...

drbd-user@lists.linbit.com drbd-user@lists.linbit.com
Thu, 8 Jul 2004 10:04:54 +0200 (CEST)


DRBD CVS committal

Author  : phil
Module  : drbd

Dir     : drbd/drbd


Modified Files:
      Tag: rel-0_7-branch
	drbd_bitmap.c drbd_compat_types.h 


Log Message:
An excellent patch by LGE 
* A generic find_next_bit() for linux-2.4.x compatibility on exotic 
  architectures.
* Additional debugging code for drbd_bitmap.c (only enabled if DUMP_MD>3)
* An additional option to drbd_config.h to disable find_next_bit() on 
  Linux-2.4.x (probabely vendor kernels have it already...)

===================================================================
RCS file: /var/lib/cvs/drbd/drbd/drbd/Attic/drbd_bitmap.c,v
retrieving revision 1.1.2.15
retrieving revision 1.1.2.16
diff -u -3 -r1.1.2.15 -r1.1.2.16
--- drbd_bitmap.c	7 Jul 2004 14:54:09 -0000	1.1.2.15
+++ drbd_bitmap.c	8 Jul 2004 08:04:49 -0000	1.1.2.16
@@ -170,21 +170,25 @@
 #endif
 // }
 
-/* debugging aid 
-STATIC void bm_end_info(drbd_dev *mdev)
+#if DUMP_MD >= 3
+/* debugging aid */
+STATIC void bm_end_info(drbd_dev *mdev, const char* where)
 {
 	struct drbd_bitmap *b = mdev->bitmap;
-	size_t w = b->bm_bits >> LN2_BPL;
+	size_t w = (b->bm_bits-1) >> LN2_BPL;
 
-	INFO("bm_set=%lu\n",b->bm_set);
-	INFO("bm[%d]=0x%lX\n",w,b->bm[w]);
+	INFO("%s: bm_set=%lu\n", where, b->bm_set);
+	INFO("bm[%d]=0x%lX\n", w, b->bm[w]);
 	w++;
 
 	if ( w < b->bm_words ) {
+		D_ASSERT(w == b->bm_words -1);
 		INFO("bm[%d]=0x%lX\n",w,b->bm[w]);
 	}
 }
-*/
+#else
+#define bm_end_info(ignored...)	((void)(0))
+#endif
 
 /* long word offset of _bitmap_ sector */
 #define S2W(s)	((s)<<(BM_EXT_SIZE_B-BM_BLOCK_SIZE_B-LN2_BPL))
@@ -317,6 +321,7 @@
 			b->bm_bits    = bits;
 			b->bm_dev_capacity = capacity;
 			b->bm_set -= bm_clear_surplus(b);
+			bm_end_info(mdev, __FUNCTION__ );
 			spin_unlock_irq(&b->bm_lock);
 			goto out;
 		} else {
@@ -345,6 +350,7 @@
 		b->bm_words = words;
 		b->bm_dev_capacity = capacity;
 		bm_clear_surplus(b);
+		bm_end_info(mdev, __FUNCTION__ );
 		spin_unlock_irq(&b->bm_lock);
 		INFO("resync bitmap: bits=%lu words=%lu\n",bits,words);
 	}
@@ -426,6 +432,7 @@
 	 */
 	if (offset+number == b->bm_words) {
 		b->bm_set -= bm_clear_surplus(b);
+		bm_end_info(mdev, __FUNCTION__ );
 	}
 	spin_unlock_irq(&b->bm_lock);
 }
@@ -464,6 +471,7 @@
 	 */
 	if (offset+number == b->bm_words) {
 		b->bm_set -= bm_clear_surplus(b);
+		bm_end_info(mdev, __FUNCTION__ );
 	}
 	spin_unlock_irq(&b->bm_lock);
 }
@@ -533,7 +541,7 @@
 		offset    = S2W(enr);	// word offset into bitmap
 		num_words = min(S2W(1), bm_words - offset);
 #if DUMP_MD >= 3
-	INFO("write_sect: sector=%lu offset=%u num_words=%u\n",
+	INFO("read_sect: sector=%lu offset=%u num_words=%u\n",
 			enr, offset, num_words);
 #endif
 		drbd_bm_set_lel( mdev, offset, num_words,
@@ -598,6 +606,9 @@
 	INFO("write_sect: sector=%lu offset=%u num_words=%u\n",
 			enr, offset, num_words);
 #endif
+	if (num_words < S2W(1)) {
+		memset(page_address(mdev->md_io_page),0,MD_HARDSECT);
+	}
 	drbd_bm_get_lel( mdev, offset, num_words,
 			 page_address(mdev->md_io_page) );
 	if (!drbd_md_sync_page_io(mdev,on_disk_sector,WRITE)) {
===================================================================
RCS file: /var/lib/cvs/drbd/drbd/drbd/Attic/drbd_compat_types.h,v
retrieving revision 1.1.2.9
retrieving revision 1.1.2.10
diff -u -3 -r1.1.2.9 -r1.1.2.10
--- drbd_compat_types.h	3 Jul 2004 11:38:11 -0000	1.1.2.9
+++ drbd_compat_types.h	8 Jul 2004 08:04:49 -0000	1.1.2.10
@@ -42,6 +42,13 @@
 #include <linux/completion.h>
 #endif
 
+/* note that if you use some verndor kernels like SuSE,
+ * their 2.4.X variant probably already contain equivalent definitions.
+ * you then have to disable this compat again...
+ */
+
+#ifndef HAVE_FIND_NEXT_BIT /* { */
+
 #if defined(__i386__) || defined(__arch_um__)
 /**
  * find_first_bit - find the first set bit in a memory region
@@ -171,9 +178,70 @@
  found_middle:
 	return result + __ffs(tmp);
 }
+#elif defined(USE_GENERIC_FIND_NEXT_BIT)
+
+#if BITS_PER_LONG == 32
+#define  _xFFFF 31ul
+#define _x10000 32
+#define _xSHIFT  5
+#elif BITS_PER_LONG == 64
+#define  _xFFFF 63ul
+#define _x10000 64
+#define _xSHIFT  6
+#else
+#error "Unexpected BITS_PER_LONG"
+#endif
+
+/* slightly large to be inlined, but anyways... */
+static inline unsigned long
+find_next_bit(void * addr, unsigned long size, unsigned long offset)
+{
+	unsigned long * p = ((unsigned long *) addr) + (offset >> _xSHIFT);
+	unsigned long result = offset & ~_xFFFF;
+	unsigned long tmp;
+
+	if (offset >= size)
+		return size;
+	size -= result;
+	offset &= _xFFFF;
+	if (offset) {
+		tmp = *(p++);
+		tmp &= ~0UL << offset;
+		if (size < _x10000)
+			goto found_first;
+		if (tmp)
+			goto found_middle;
+		size -= _x10000;
+		result += _x10000;
+	}
+	while (size & ~_xFFFF) {
+		if ((tmp = *(p++)))
+			goto found_middle;
+		result += _x10000;
+		size -= _x10000;
+	}
+	if (!size)
+		return result;
+	tmp = *p;
+ found_first:
+	tmp &= ~0UL >> (_x10000 - size);
+	if (!tmp)
+		return result + size;
+ found_middle: /* if this is reached, we know that (tmp != 0) */
+	return result + generic_ffs(tmp)-1;
+}
+
+#undef _xFFFF
+#undef _x10000
+#undef _xSHIFT
+
 #else
 #warning "You probabely need to copy find_next_bit() from a 2.6.x kernel."
+#warning "Or enable low performance generic C-code"
+#warning "(USE_GENERIC_FIND_NEXT_BIT in drbd_config.h)"
 #endif
+
+#endif /* HAVE_FIND_NEXT_BIT } */
 
 #ifndef ALIGN
 #define ALIGN(x,a) ( ((x) + (a)-1) &~ ((a)-1) )