[DRBD-cvs] svn commit by lars - r2090 - in trunk/drbd: . linux - *
page->private is page->u.private since 2.6.15
drbd-cvs at lists.linbit.com
drbd-cvs at lists.linbit.com
Fri Mar 3 16:47:53 CET 2006
* drbd0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Author: lars
Date: 2006-03-03 16:47:52 +0100 (Fri, 03 Mar 2006)
New Revision: 2090
Modified:
trunk/drbd/drbd_bitmap.c
trunk/drbd/drbd_compat_wrappers.h
trunk/drbd/drbd_int.h
trunk/drbd/drbd_main.c
trunk/drbd/drbd_receiver.c
trunk/drbd/linux/drbd_config.h
Log:
* page->private is page->u.private since 2.6.15
* drbd07-plus async bitmap io code ==> drbd 8
untested!
Modified: trunk/drbd/drbd_bitmap.c
===================================================================
--- trunk/drbd/drbd_bitmap.c 2006-03-03 15:38:34 UTC (rev 2089)
+++ trunk/drbd/drbd_bitmap.c 2006-03-03 15:47:52 UTC (rev 2090)
@@ -29,6 +29,7 @@
#include <linux/bitops.h>
#include <linux/vmalloc.h>
#include <linux/string.h> // for memset
+#include <linux/swap.h> // for total_swapcache_pages
#include <linux/drbd.h>
#include "drbd_int.h"
@@ -57,12 +58,13 @@
/*
* NOTE
- * Access to the *bm is protected by bm_lock.
+ * Access to the *bm_pages is protected by bm_lock.
* It is safe to read the other members within the lock.
*
* drbd_bm_set_bit is called from bio_endio callbacks,
* so there we need a spin_lock_irqsave.
* Everywhere else we need a spin_lock_irq.
+ * And we need the kmap_atomic :-(
*
* FIXME
* Actually you need to serialize all resize operations.
@@ -78,17 +80,28 @@
* than have two resize operations interfere somewhen.
*/
struct drbd_bitmap {
- unsigned long *bm;
+ struct page **bm_pages;
spinlock_t bm_lock;
+ /* WARNING unsigned long bm_fo and friends:
+ * 32bit number of bit offset is just enough for 512 MB bitmap.
+ * it will blow up if we make the bitmap bigger...
+ * not that it makes much sense to have a bitmap that large,
+ * rather change the granularity to 16k or 64k or something.
+ */
unsigned long bm_fo; // next offset for drbd_bm_find_next
unsigned long bm_set; // nr of set bits; THINK maybe atomic_t ?
unsigned long bm_bits;
size_t bm_words;
+ size_t bm_number_of_pages;
sector_t bm_dev_capacity;
struct semaphore bm_change; // serializes resize operations
+ atomic_t bm_async_io;
+ wait_queue_head_t bm_io_wait;
+
+ unsigned long bm_flags;
+
// { REMOVE
- unsigned long bm_flags; // currently debugging aid only
unsigned long bm_line;
char *bm_file;
// }
@@ -96,7 +109,9 @@
// { REMOVE once we serialize all state changes properly
#define D_BUG_ON(x) ERR_IF(x) { dump_stack(); }
-#define BM_LOCKED 0
+#define BM_LOCKED 0
+#define BM_MD_IO_ERROR (BITS_PER_LONG-1) // 31? 63?
+
#if 0 // simply disabled for now...
#define MUST_NOT_BE_LOCKED() do { \
if (test_bit(BM_LOCKED,&b->bm_flags)) { \
@@ -158,7 +173,6 @@
// has been very helpful to indicate that rs_total and rs_left have been
// used in a non-smp safe way...
#define BM_PARANOIA_CHECK() do { \
- D_ASSERT(b->bm[b->bm_words] == DRBD_MAGIC); \
D_ASSERT(b->bm_dev_capacity == drbd_get_capacity(mdev->this_bdev)); \
if ( (b->bm_set != mdev->rs_total) && \
(b->bm_set != mdev->rs_left) ) { \
@@ -171,7 +185,6 @@
} while (0)
#else
#define BM_PARANOIA_CHECK() do { \
- D_ASSERT(b->bm[b->bm_words] == DRBD_MAGIC); \
if (b->bm_dev_capacity != drbd_get_capacity(mdev->this_bdev)) { \
ERR("%s:%d: bm_dev_capacity:%llu drbd_get_capacity:%llu\n", \
__FILE__, __LINE__, \
@@ -184,6 +197,7 @@
#if DUMP_MD >= 3
/* debugging aid */
+#error "FIXME"
STATIC void bm_end_info(drbd_dev *mdev, const char* where)
{
struct drbd_bitmap *b = mdev->bitmap;
@@ -202,9 +216,52 @@
#define bm_end_info(ignored...) ((void)(0))
#endif
+#if 0
+#define catch_oob_access_start() do { \
+ do { \
+ if ((bm-p_addr) >= PAGE_SIZE/sizeof(long)) { \
+ printk(KERN_ALERT "drbd_bitmap.c:%u %s: p_addr:%p bm:%p %d\n", \
+ __LINE__ , __func__ , p_addr, bm, (bm-p_addr)); \
+ break; \
+ }
+#define catch_oob_access_end() \
+ } while(0); } while (0)
+#else
+#define catch_oob_access_start() ((void)0)
+#define catch_oob_access_end() ((void)0)
+#endif
+
+/* word offset to long pointer */
+STATIC unsigned long * bm_map_paddr(struct drbd_bitmap* b, unsigned long offset)
+{
+ struct page * page;
+ unsigned long page_nr;
+
+ // page_nr = (word*sizeof(long)) >> PAGE_SHIFT;
+ page_nr = offset >> (PAGE_SHIFT - LN2_BPL + 3);
+ BUG_ON(page_nr >= b->bm_number_of_pages);
+ page = b->bm_pages[page_nr];
+
+ return (unsigned long*) kmap_atomic(page,KM_USER0);
+}
+
+STATIC void bm_unmap(unsigned long *p_addr) {
+ kunmap_atomic(p_addr, KM_USER0);
+};
+
/* long word offset of _bitmap_ sector */
#define S2W(s) ((s)<<(BM_EXT_SIZE_B-BM_BLOCK_SIZE_B-LN2_BPL))
+/* word offset from start of bitmap to word number _in_page_
+ * modulo longs per page
+#define MLPP(X) ((X) % (PAGE_SIZE/sizeof(long))
+ hm, well, Philipp thinks gcc might not optimze the % into & (... - 1)
+ so do it explicitly:
+ */
+#define MLPP(X) ((X) & ((PAGE_SIZE/sizeof(long))-1))
+/* Long words per page */
+#define LWPP (PAGE_SIZE/sizeof(long))
+
/*
* actually most functions herein should take a struct drbd_bitmap*, not a
* drbd_dev*, but for the debug macros I like to have the mdev around
@@ -217,7 +274,113 @@
* But it is NOT strictly ok.
*/
+STATIC void bm_free_pages(struct page ** pages, unsigned long number)
+{
+ unsigned long i;
+ if (!pages)
+ return;
+
+ for(i=0;i<number;i++) {
+ if (!pages[i]) {
+ printk(KERN_ALERT "drbd: bm_free_pages tried to free "
+ "a NULL pointer; i=%lu n=%lu\n",
+ i, number);
+ continue;
+ }
+ __free_page(pages[i]);
+ pages[i] = NULL;
+ }
+}
+
/*
+ * "have" and "want" are NUMBER OF PAGES.
+ */
+STATIC struct page ** bm_realloc_pages(struct page ** old_pages,
+ unsigned long have,
+ unsigned long want)
+{
+ struct page** new_pages, *page;
+ unsigned int i, bytes;
+
+ BUG_ON(have == 0 && old_pages != NULL);
+ BUG_ON(have != 0 && old_pages == NULL);
+
+ if (have == want)
+ return old_pages;
+
+ /* don't even try if it is likely to be too much */
+ if (want > have) {
+ unsigned long nfree, nleft;
+ nfree = nr_free_pages();
+ nleft = nfree + get_page_cache_size()-total_swapcache_pages;
+
+ if (nleft <= (want-have)) {
+ printk(KERN_ALERT "drbd: bm_realloc_pages: OOM!\n");
+ return NULL;
+ }
+
+ nleft -= (want-have);
+
+ /* protect me agains the infamous oom killer.
+ * FIXME sorry, now it does no longer work on embeded boxes with less than 16MB main ram :-)
+ */
+ if ( nleft < (10 << (20 - PAGE_SHIFT)) ) {
+ printk(KERN_ALERT "drbd: bm_realloc_pages would have left less than 10MB ram free; OOM!\n");
+ printk(KERN_ALERT "drbd: free:%lu buf+cache:%lu want:%lu have:%lu left:%lu\n"
+ , nfree
+ , get_page_cache_size()-total_swapcache_pages
+ , want, have, nleft
+ );
+ return NULL;
+ }
+ }
+
+ /* To use kmalloc here is ok, as long as we support 4TB at max...
+ * otherwise this might become bigger than 128KB, which is
+ * the maximum for kmalloc.
+ *
+ * no, it is not: on 64bit boxes, sizeof(void*) == 8,
+ * 128MB bitmap @ 4K pages -> 256K of page pointers.
+ * ==> use vmalloc for now again.
+ * then again, we could do something like
+ * if (nr_pages > watermark) vmalloc else kmalloc :*> ...
+ * or do cascading page arrays:
+ * one page for the page array of the page array,
+ * those pages for the real bitmap pages.
+ * there we could even add some optimization members,
+ * so we won't need to kmap_atomic in bm_find_next_bit just to see
+ * that the page has no bits set ...
+ */
+ bytes = sizeof(struct page*)*want;
+ new_pages = vmalloc(bytes);
+ if(!new_pages) return NULL;
+
+ memset(new_pages,0,bytes);
+ if( want >= have ) {
+ for(i=0;i<have;i++) {
+ new_pages[i] = old_pages[i];
+ }
+ for(;i<want;i++) {
+ if ( !(page = alloc_page(GFP_HIGHUSER)) ) {
+ bm_free_pages(new_pages + have, i - have);
+ vfree(new_pages);
+ return NULL;
+ }
+ new_pages[i] = page;
+ }
+ } else {
+ for(i=0;i<want;i++) {
+ new_pages[i] = old_pages[i];
+ }
+ /* NOT HERE, we are outside the spinlock!
+ bm_free_pages(old_pages + want, have - want);
+ */
+ }
+
+ return new_pages;
+}
+
+/*
* called on driver init only. TODO call when a device is created.
* allocates the drbd_bitmap, and stores it in mdev->bitmap.
*/
@@ -231,6 +394,7 @@
memset(b,0,sizeof(*b));
spin_lock_init(&b->bm_lock);
init_MUTEX(&b->bm_change);
+ init_waitqueue_head(&b->bm_io_wait);
mdev->bitmap = b;
return 0;
}
@@ -251,7 +415,8 @@
*
D_BUG_ON(mdev->bitmap->bm);
*/
- vfree(mdev->bitmap->bm);
+ bm_free_pages(mdev->bitmap->bm_pages,mdev->bitmap->bm_number_of_pages);
+ vfree(mdev->bitmap->bm_pages);
kfree(mdev->bitmap);
mdev->bitmap = NULL;
}
@@ -266,17 +431,25 @@
const unsigned long mask = (1UL << (b->bm_bits & (BITS_PER_LONG-1))) -1;
size_t w = b->bm_bits >> LN2_BPL;
int cleared=0;
+ unsigned long *p_addr, *bm;
+ p_addr = bm_map_paddr(b,w);
+ bm = p_addr + MLPP(w);
if ( w < b->bm_words ) {
- cleared = hweight_long(b->bm[w] & ~mask);
- b->bm[w++] &= mask;
+ catch_oob_access_start();
+ cleared = hweight_long(*bm & ~mask);
+ *bm &= mask;
+ catch_oob_access_end();
+ w++; bm++;
}
if ( w < b->bm_words ) {
- cleared += hweight_long(b->bm[w]);
- b->bm[w++]=0;
+ catch_oob_access_start();
+ cleared += hweight_long(*bm);
+ *bm=0;
+ catch_oob_access_end();
}
-
+ bm_unmap(p_addr);
return cleared;
}
@@ -284,31 +457,80 @@
{
const unsigned long mask = (1UL << (b->bm_bits & (BITS_PER_LONG-1))) -1;
size_t w = b->bm_bits >> LN2_BPL;
+ unsigned long *p_addr, *bm;
+ p_addr = bm_map_paddr(b,w);
+ bm = p_addr + MLPP(w);
if ( w < b->bm_words ) {
- b->bm[w++] |= ~mask;
+ catch_oob_access_start();
+ *bm |= ~mask;
+ bm++; w++;
+ catch_oob_access_end();
}
if ( w < b->bm_words ) {
- b->bm[w++] = ~(0UL);
+ catch_oob_access_start();
+ *bm = ~(0UL);
+ catch_oob_access_end();
}
+ bm_unmap(p_addr);
}
-STATIC unsigned long bm_count_bits(struct drbd_bitmap * b)
+STATIC unsigned long bm_count_bits(struct drbd_bitmap * b, int just_read)
{
- unsigned long *bm = b->bm;
- unsigned long *ep = b->bm + b->bm_words;
+ unsigned long *p_addr, *bm, offset = 0;
unsigned long bits = 0;
+ unsigned long i,do_now;
- while ( bm < ep ) {
- bits += hweight_long(*bm++);
+ while ( offset < b->bm_words ) {
+ i = do_now = min_t( size_t, b->bm_words-offset, LWPP );
+ p_addr = bm_map_paddr(b,offset);
+ bm = p_addr + MLPP(offset);
+ while(i--) {
+ catch_oob_access_start();
+ /* on little endian, this is *bm = *bm;
+ * and should be optimized away by the compiler */
+ if (just_read) *bm = lel_to_cpu(*bm);
+ bits += hweight_long(*bm++);
+ catch_oob_access_end();
+ }
+ bm_unmap(p_addr);
+ offset += do_now;
}
return bits;
}
-#define BM_SECTORS_PER_BIT (BM_BLOCK_SIZE/512)
+/* offset and len in long words.*/
+STATIC void bm_memset(struct drbd_bitmap * b, size_t offset, int c, size_t len)
+{
+ unsigned long *p_addr, *bm;
+ size_t do_now, end;
+ end = offset+len;
+
+ if( end > b->bm_words ) {
+ printk(KERN_ALERT "drbd: bm_memset end > bm_words\n");
+ return;
+ }
+
+ while (offset < end) {
+ do_now = min_t(size_t,ALIGN(offset+1,LWPP),end) - offset;
+ p_addr = bm_map_paddr(b,offset);
+ bm = p_addr + MLPP(offset);
+ catch_oob_access_start();
+ if ( bm+do_now > p_addr + LWPP ) {
+ printk(KERN_ALERT "drbd: BUG BUG BUG! p_addr:%p bm:%p do_now:%d\n",
+ p_addr, bm, do_now);
+ break;
+ }
+ memset(bm,c,do_now*sizeof(long));
+ catch_oob_access_end();
+ bm_unmap(p_addr);
+ offset += do_now;
+ }
+}
+
/*
* make sure the bitmap has enough room for the attached storage,
* if neccessary, resize.
@@ -320,7 +542,9 @@
int drbd_bm_resize(drbd_dev *mdev, sector_t capacity)
{
struct drbd_bitmap *b = mdev->bitmap;
- unsigned long bits, bytes, words, *nbm, *obm = 0;
+ unsigned long bits, words, owords, obits, *p_addr, *bm;
+ unsigned long want, have, onpages; // number of pages
+ struct page **npages, **opages = NULL;
int err = 0, growing;
ERR_IF(!b) return -ENOMEM;
@@ -337,79 +561,89 @@
if (capacity == 0) {
spin_lock_irq(&b->bm_lock);
- obm = b->bm;
- b->bm = NULL;
+ opages = b->bm_pages;
+ onpages = b->bm_number_of_pages;
+ owords = b->bm_words;
+ b->bm_pages = NULL;
+ b->bm_number_of_pages =
b->bm_fo =
b->bm_set =
b->bm_bits =
b->bm_words =
b->bm_dev_capacity = 0;
spin_unlock_irq(&b->bm_lock);
- goto free_obm;
+ bm_free_pages(opages, onpages);
+ vfree(opages);
+ goto out;
+ }
+ bits = BM_SECT_TO_BIT(ALIGN(capacity,BM_SECT_PER_BIT));
+
+ /* 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.
+ */
+ words = ALIGN(bits,64) >> LN2_BPL;
+
+ D_ASSERT((u64)bits <= (((u64)mdev->bc->md.md_size_sect-MD_BM_OFFSET) << 12));
+
+ /* one extra long to catch off by one errors */
+ want = ALIGN( (words+1)*sizeof(long) ,PAGE_SIZE) >> PAGE_SHIFT;
+ have = b->bm_number_of_pages;
+ if (want == have) {
+ D_ASSERT(b->bm_pages != NULL);
+ npages = b->bm_pages;
} else {
- bits = BM_SECT_TO_BIT(ALIGN(capacity,BM_SECTORS_PER_BIT));
- DUMPI(bits);
+ npages = bm_realloc_pages(b->bm_pages,have,want);
+ }
- /* 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.
- */
- words = ALIGN(bits,64) >> LN2_BPL;
+ if (!npages) {
+ err = -ENOMEM;
+ goto out;
+ }
- D_ASSERT((u64)bits <= (((u64)mdev->bc->md.md_size_sect-MD_BM_OFFSET) << 12));
+ spin_lock_irq(&b->bm_lock);
+ opages = b->bm_pages;
+ owords = b->bm_words;
+ obits = b->bm_bits;
- if ( words == b->bm_words ) {
- /* optimize: capacity has changed,
- * but only within one long word worth of bits.
- * just update the bm_dev_capacity and bm_bits members.
- */
- spin_lock_irq(&b->bm_lock);
- 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 {
- /* one extra long to catch off by one errors */
- bytes = (words+1)*sizeof(long);
- nbm = vmalloc(bytes);
- if (!nbm) {
- ERR("bitmap: failed to vmalloc %lu bytes\n",bytes);
- err = -ENOMEM;
- goto out;
- }
- }
- spin_lock_irq(&b->bm_lock);
- obm = b->bm;
- // brgs. move several MB within spinlock...
- // FIXME this should go into userspace!
- if (obm) {
- bm_set_surplus(b);
- D_ASSERT(b->bm[b->bm_words] == DRBD_MAGIC);
- memcpy(nbm,obm,min_t(size_t,b->bm_words,words)*sizeof(long));
- }
- growing = words > b->bm_words;
- if (growing) { // set all newly allocated bits
- // start at -1, just to be sure.
- memset( nbm + (b->bm_words?:1)-1 , 0xff,
- (words - ((b->bm_words?:1)-1)) * sizeof(long) );
- b->bm_set += bits - b->bm_bits;
- }
- nbm[words] = DRBD_MAGIC;
- b->bm = nbm;
- b->bm_bits = bits;
- b->bm_words = words;
- b->bm_dev_capacity = capacity;
- bm_clear_surplus(b);
- if( !growing ) b->bm_set = bm_count_bits(b);
- bm_end_info(mdev, __FUNCTION__ );
- spin_unlock_irq(&b->bm_lock);
- INFO("resync bitmap: bits=%lu words=%lu\n",bits,words);
+ growing = bits > obits;
+ if (opages) {
+ bm_set_surplus(b);
}
- free_obm:
- vfree(obm); // vfree(NULL) is noop
+
+ b->bm_pages = npages;
+ b->bm_number_of_pages = want;
+ b->bm_bits = bits;
+ b->bm_words = words;
+ b->bm_dev_capacity = capacity;
+
+ if( growing ) {
+ bm_memset(b,owords,0xff,words-owords);
+ b->bm_set += bits - obits;
+ }
+
+ if ( want < have ) {
+ /* implicit: (opages != NULL) && (opages != npages) */
+ bm_free_pages(opages + want, have - want);
+ }
+
+ p_addr = bm_map_paddr(b,words);
+ bm = p_addr + MLPP(words);
+ catch_oob_access_start();
+ *bm = DRBD_MAGIC;
+ catch_oob_access_end();
+ bm_unmap(p_addr);
+
+ (void)bm_clear_surplus(b);
+ if( !growing )
+ b->bm_set = bm_count_bits(b, 0 /* not just read */ );
+
+ bm_end_info(mdev, __FUNCTION__ );
+ spin_unlock_irq(&b->bm_lock);
+ if (opages != npages) vfree(opages);
+ INFO("resync bitmap: bits=%lu words=%lu\n",bits,words);
+
out:
up(&b->bm_change);
return err;
@@ -430,6 +664,7 @@
unsigned long flags;
ERR_IF(!b) return 0;
+ ERR_IF(!b->bm_pages) return 0;
// MUST_BE_LOCKED(); well. yes. but ...
spin_lock_irqsave(&b->bm_lock,flags);
@@ -443,6 +678,7 @@
{
struct drbd_bitmap *b = mdev->bitmap;
ERR_IF(!b) return 0;
+ ERR_IF(!b->bm_pages) return 0;
/* FIXME
* actually yes. really. otherwise it could just change its size ...
@@ -460,34 +696,42 @@
unsigned long* buffer )
{
struct drbd_bitmap *b = mdev->bitmap;
- unsigned long *bm;
+ unsigned long *p_addr, *bm;
unsigned long word, bits;
- size_t n = number;
+ size_t end, do_now;
- if (number == 0) return;
+ end = offset + number;
+
ERR_IF(!b) return;
- ERR_IF(!b->bm) return;
- D_BUG_ON(offset >= b->bm_words);
- D_BUG_ON(offset+number > b->bm_words);
- D_BUG_ON(number > PAGE_SIZE/sizeof(long));
+ ERR_IF(!b->bm_pages) return;
+ D_BUG_ON(offset >= b->bm_words);
+ D_BUG_ON(end > b->bm_words);
MUST_BE_LOCKED();
spin_lock_irq(&b->bm_lock);
// BM_PARANOIA_CHECK(); no.
- bm = b->bm + offset;
- while(n--) {
- bits = hweight_long(*bm);
- word = *bm | lel_to_cpu(*buffer++);
- *bm++ = word;
- b->bm_set += hweight_long(word) - bits;
+ while(offset < end) {
+ do_now = min_t(size_t,ALIGN(offset+1,LWPP),end) - offset;
+ p_addr = bm_map_paddr(b,offset);
+ bm = p_addr + MLPP(offset);
+ offset += do_now;
+ while(do_now--) {
+ catch_oob_access_start();
+ bits = hweight_long(*bm);
+ word = *bm | lel_to_cpu(*buffer++);
+ *bm++ = word;
+ b->bm_set += hweight_long(word) - bits;
+ catch_oob_access_end();
+ }
+ bm_unmap(p_addr);
}
/* with 32bit <-> 64bit cross-platform connect
* this is only correct for current usage,
* where we _know_ that we are 64 bit aligned,
* and know that this function is used in this way, too...
*/
- if (offset+number == b->bm_words) {
+ if (end == b->bm_words) {
b->bm_set -= bm_clear_surplus(b);
bm_end_info(mdev, __FUNCTION__ );
}
@@ -501,34 +745,42 @@
unsigned long* buffer )
{
struct drbd_bitmap *b = mdev->bitmap;
- unsigned long *bm;
+ unsigned long *p_addr, *bm;
unsigned long word, bits;
- size_t n = number;
+ size_t end, do_now;
- if (number == 0) return;
+ end = offset + number;
+
ERR_IF(!b) return;
- ERR_IF(!b->bm) return;
- D_BUG_ON(offset >= b->bm_words);
- D_BUG_ON(offset+number > b->bm_words);
- D_BUG_ON(number > PAGE_SIZE/sizeof(long));
+ ERR_IF(!b->bm_pages) return;
+ D_BUG_ON(offset >= b->bm_words);
+ D_BUG_ON(end > b->bm_words);
MUST_BE_LOCKED();
spin_lock_irq(&b->bm_lock);
// BM_PARANOIA_CHECK(); no.
- bm = b->bm + offset;
- while(n--) {
- bits = hweight_long(*bm);
- word = lel_to_cpu(*buffer++);
- *bm++ = word;
- b->bm_set += hweight_long(word) - bits;
+ while(offset < end) {
+ do_now = min_t(size_t,ALIGN(offset+1,LWPP),end) - offset;
+ p_addr = bm_map_paddr(b,offset);
+ bm = p_addr + MLPP(offset);
+ offset += do_now;
+ while(do_now--) {
+ catch_oob_access_start();
+ bits = hweight_long(*bm);
+ word = lel_to_cpu(*buffer++);
+ *bm++ = word;
+ b->bm_set += hweight_long(word) - bits;
+ catch_oob_access_end();
+ }
+ bm_unmap(p_addr);
}
/* with 32bit <-> 64bit cross-platform connect
* this is only correct for current usage,
* where we _know_ that we are 64 bit aligned,
* and know that this function is used in this way, too...
*/
- if (offset+number == b->bm_words) {
+ if (end == b->bm_words) {
b->bm_set -= bm_clear_surplus(b);
bm_end_info(mdev, __FUNCTION__ );
}
@@ -542,14 +794,16 @@
unsigned long* buffer )
{
struct drbd_bitmap *b = mdev->bitmap;
- unsigned long *bm;
+ unsigned long *p_addr, *bm;
+ size_t end, do_now;
- if (number == 0) return;
+ end = offset + number;
+
ERR_IF(!b) return;
- ERR_IF(!b->bm) return;
- if ( (offset >= b->bm_words) ||
- (offset+number > b->bm_words) ||
- (number > PAGE_SIZE/sizeof(long)) ||
+ ERR_IF(!b->bm_pages) return;
+
+ if ( (offset >= b->bm_words) ||
+ (end > b->bm_words) ||
(number <= 0) ) {
// yes, there is "%z", but that gives compiler warnings...
ERR("offset=%lu number=%lu bm_words=%lu\n",
@@ -563,8 +817,18 @@
spin_lock_irq(&b->bm_lock);
BM_PARANOIA_CHECK();
- bm = b->bm + offset;
- while(number--) *buffer++ = cpu_to_lel(*bm++);
+ while(offset < end) {
+ do_now = min_t(size_t,ALIGN(offset+1,LWPP),end) - offset;
+ p_addr = bm_map_paddr(b,offset);
+ bm = p_addr + MLPP(offset);
+ offset += do_now;
+ while(do_now--) {
+ catch_oob_access_start();
+ *buffer++ = cpu_to_lel(*bm++);
+ catch_oob_access_end();
+ }
+ bm_unmap(p_addr);
+ }
spin_unlock_irq(&b->bm_lock);
}
@@ -573,22 +837,62 @@
{
struct drbd_bitmap *b = mdev->bitmap;
ERR_IF(!b) return;
- ERR_IF(!b->bm) return;
+ ERR_IF(!b->bm_pages) return;
- D_BUG_ON(!b);
- if (b->bm_bits == 0) return;
- D_BUG_ON(!b->bm);
-
MUST_BE_LOCKED();
spin_lock_irq(&b->bm_lock);
- BM_PARANOIA_CHECK();
- memset(b->bm,0xff,b->bm_words*sizeof(long));
- bm_clear_surplus(b);
+ bm_memset(b,0,0xff,b->bm_words);
+ (void)bm_clear_surplus(b);
b->bm_set = b->bm_bits;
spin_unlock_irq(&b->bm_lock);
}
+int drbd_bm_async_io_complete(struct bio *bio, unsigned int bytes_done, int error)
+{
+ struct drbd_bitmap *b = bio->bi_private;
+
+ if (bio->bi_size)
+ return 1;
+
+ if (error) {
+ /* doh. what now?
+ * for now, set all bits, and flag MD_IO_ERROR
+ */
+ /* FIXME kmap_atomic memset etc. pp. */
+ __set_bit(BM_MD_IO_ERROR,&b->bm_flags);
+ }
+ if (atomic_dec_and_test(&b->bm_async_io))
+ wake_up(&b->bm_io_wait);
+
+ bio_put(bio);
+
+ return 0;
+}
+
+STATIC void drbd_bm_page_io_async(drbd_dev *mdev, struct drbd_bitmap *b, int page_nr, int rw)
+{
+ /* we are process context. we always get a bio */
+ struct bio *bio = bio_alloc(GFP_KERNEL, 1);
+ unsigned int len;
+ sector_t on_disk_sector = mdev->bc->md.md_offset + mdev->bc->md.bm_offset;
+ on_disk_sector += ((sector_t)page_nr) << (PAGE_SHIFT-9);
+
+ /* this might happen with very small flexible external meta data device */
+ len = min_t(unsigned int, PAGE_SIZE,
+ (drbd_md_last_sector(mdev->bc) - on_disk_sector + 1)<<9);
+
+ D_DUMPLU(on_disk_sector);
+ D_DUMPI(len);
+
+ bio->bi_bdev = mdev->bc->md_bdev;
+ bio->bi_sector = on_disk_sector;
+ bio_add_page(bio, b->bm_pages[page_nr], len, 0);
+ bio->bi_private = b;
+ bio->bi_end_io = drbd_bm_async_io_complete;
+ submit_bio(rw, bio);
+}
+
/* read one sector of the on disk bitmap into memory.
* on disk bitmap is little endian.
* @enr is _sector_ offset from start of on disk bitmap (aka bm-extent nr).
@@ -596,11 +900,13 @@
*/
int drbd_bm_read_sect(drbd_dev *mdev,unsigned long enr)
{
+ /* addition of sector_t/u64/s32... works anyways */
sector_t on_disk_sector = mdev->bc->md.md_offset + mdev->bc->md.bm_offset + enr;
int bm_words, num_words, offset, err = 0;
// MUST_BE_LOCKED(); not neccessarily global ...
+ D_DUMPLU(on_disk_sector);
down(&mdev->md_io_mutex);
if(drbd_md_sync_page_io(mdev,mdev->bc,on_disk_sector,READ)) {
bm_words = drbd_bm_words(mdev);
@@ -629,12 +935,50 @@
/**
* drbd_bm_read: Read the whole bitmap from its on disk location.
+ *
+ * currently only called from "drbd_ioctl_set_disk"
+ * FIXME need to be able to return an error!!
+ *
*/
-void drbd_bm_read(struct Drbd_Conf *mdev)
+# if defined(__LITTLE_ENDIAN)
+ /* nothing to do, on disk == in memory */
+# define bm_cpu_to_lel(x) ((void)0)
+# else
+void bm_cpu_to_lel(struct drbd_bitmap *b)
{
+ /* need to cpu_to_lel all the pages ...
+ * this may be optimized by using
+ * cpu_to_lel(-1) == -1 and cpu_to_lel(0) == 0;
+ * the following is still not optimal, but better than nothing */
+ if (b->bm_set == 0) {
+ /* no page at all; avoid swap if all is 0 */
+ i = b->bm_number_of_pages;
+ } else if (b->bm_set == b->bm_bits) {
+ /* only the last page */
+ i = b->bm_number_of_pages -1;
+ } else {
+ /* all pages */
+ i = 0;
+ }
+ for (; i < b->bm_number_of_pages; i++) {
+ unsigned long *bm;
+ p_addr = kmap_atomic(b->bm_pages[i],KM_USER0)
+ for (bm = p_addr; bm < p_addr+PAGE_SIZE/sizeof(long); bm++) {
+ *bm = cpu_to_lel(*bm);
+ }
+ kunmap_atomic(p_addr);
+ }
+}
+# endif
+/* lel_to_cpu == cpu_to_lel */
+# define bm_lel_to_cpu(x) bm_cpu_to_lel(x)
+
+STATIC void drbd_bm_rw(struct Drbd_Conf *mdev, int rw)
+{
struct drbd_bitmap *b = mdev->bitmap;
- sector_t sector;
- int bm_words, num_sectors;
+ /* sector_t sector; */
+ int bm_words, num_sectors, i;
+ unsigned long now;
char ppb[10];
MUST_BE_LOCKED();
@@ -642,15 +986,62 @@
bm_words = drbd_bm_words(mdev);
num_sectors = (bm_words*sizeof(long) + 511) >> 9;
- for (sector = 0; sector < num_sectors; sector++) {
- // FIXME do something on io error here?
- drbd_bm_read_sect(mdev,sector);
+ /* OK, I manipulate the bitmap low level,
+ * and I expect to be the exclusive user.
+ * If not, I am really in a bad mood...
+ * to catch such bugs early, make all people who want to access the
+ * bitmap while I read it dereference a NULL pointer :->
+ */
+ mdev->bitmap = NULL;
+
+ if(rw == WRITE) bm_cpu_to_lel(b);
+
+ now = jiffies;
+ atomic_set(&b->bm_async_io, b->bm_number_of_pages);
+ for (i = 0; i < b->bm_number_of_pages; i++) {
+ /* let the layers below us try to merge these bios... */
+ drbd_bm_page_io_async(mdev,b,i,rw);
}
+ blk_run_queue(bdev_get_queue(mdev->bc->md_bdev));
+ wait_event(b->bm_io_wait, atomic_read(&b->bm_async_io) == 0);
+ INFO("%s of bitmap took %lu jiffies\n",
+ rw == READ ? "reading" : "writing", jiffies - now);
+
+ if (test_bit(BM_MD_IO_ERROR,&b->bm_flags)) {
+ /* FIXME correct handling of this.
+ * detach?
+ */
+ ALERT("we had at least one MD IO ERROR during bitmap IO\n");
+ drbd_chk_io_error(mdev, 1);
+ drbd_io_error(mdev);
+ }
+
+ now = jiffies;
+ /* just read, if neccessary adjust endianness */
+ if(rw == WRITE) {
+ bm_lel_to_cpu(b);
+ } else /* rw == READ */ {
+ b->bm_set = bm_count_bits(b, 1);
+ INFO("recounting of set bits took additional %lu jiffies\n",
+ jiffies - now);
+ }
+
+ /* ok, done,
+ * now it is visible again
+ */
+
+ mdev->bitmap = b;
+
INFO("%s marked out-of-sync by on disk bit-map.\n",
ppsize(ppb,drbd_bm_total_weight(mdev) << (BM_BLOCK_SIZE_B-10)) );
}
+void drbd_bm_read(struct Drbd_Conf *mdev)
+{
+ drbd_bm_rw(mdev, READ);
+}
+
/**
* drbd_bm_write_sect: Writes a 512 byte piece of the bitmap to its
* on disk location. On disk bitmap is little endian.
@@ -678,6 +1069,7 @@
}
drbd_bm_get_lel( mdev, offset, num_words,
page_address(mdev->md_io_page) );
+ D_DUMPLU(on_disk_sector);
if (!drbd_md_sync_page_io(mdev,mdev->bc,on_disk_sector,WRITE)) {
int i;
err = -EIO;
@@ -696,25 +1088,27 @@
/**
* drbd_bm_write: Write the whole bitmap to its on disk location.
+ *
+ * called at various occasions:
+ *
+int drbd_determin_dev_size(struct Drbd_Conf* mdev)
+int drbd_ioctl_set_disk(struct Drbd_Conf *mdev,
+ struct ioctl_disk_config * arg)
+ case DRBD_IOCTL_INVALIDATE:
+ case DRBD_IOCTL_INVALIDATE_REM:
+ case DRBD_IOCTL_SET_DISK_SIZE:
+int _drbd_send_bitmap(drbd_dev *mdev)
+STATIC int drbd_sync_handshake(drbd_dev *mdev, Drbd_Parameter_Packet *p)
+STATIC int receive_BecomeSyncTarget(drbd_dev *mdev, Drbd_Header *h)
+STATIC int receive_BecomeSyncSource(drbd_dev *mdev, Drbd_Header *h)
+STATIC int receive_param(drbd_dev *mdev, Drbd_Header *h)
+ *
+ * FIXME need to be able to return an error!!
*/
+
void drbd_bm_write(struct Drbd_Conf *mdev)
{
- struct drbd_bitmap *b = mdev->bitmap;
- sector_t sector;
- int bm_words, num_sectors;
-
- MUST_BE_LOCKED();
-
- bm_words = drbd_bm_words(mdev);
- num_sectors = (bm_words*sizeof(long) + 511) >> 9;
-
- for (sector = 0; sector < num_sectors; sector++) {
- // FIXME do something on io error here?
- drbd_bm_write_sect(mdev,sector);
- }
-
- INFO("%lu KB now marked out-of-sync by on disk bit-map.\n",
- drbd_bm_total_weight(mdev) << (BM_BLOCK_SIZE_B-10) );
+ drbd_bm_rw(mdev, WRITE);
}
/* clear all bits in the bitmap */
@@ -723,13 +1117,12 @@
struct drbd_bitmap *b = mdev->bitmap;
ERR_IF(!b) return;
- ERR_IF(!b->bm) return;
+ ERR_IF(!b->bm_pages) return;
- MUST_BE_LOCKED(); \
+ MUST_BE_LOCKED();
spin_lock_irq(&b->bm_lock);
- BM_PARANOIA_CHECK();
- memset(b->bm,0,b->bm_words*sizeof(long));
+ bm_memset(b,0,0x00,b->bm_words);
b->bm_set = 0;
spin_unlock_irq(&b->bm_lock);
}
@@ -752,29 +1145,44 @@
/* NOTE
* find_first_bit returns int, we return unsigned long.
* should not make much difference anyways, but ...
+ *
* this returns a bit number, NOT a sector!
*/
+#define BPP_MASK ((1UL << (PAGE_SHIFT+3) ) - 1)
unsigned long drbd_bm_find_next(drbd_dev *mdev)
{
struct drbd_bitmap *b = mdev->bitmap;
unsigned long i = -1UL;
+ unsigned long *p_addr;
+ unsigned long bit_offset; //bit offset of the mapped page.
ERR_IF(!b) return i;
- ERR_IF(!b->bm) return i;
+ ERR_IF(!b->bm_pages) return i;
spin_lock_irq(&b->bm_lock);
BM_PARANOIA_CHECK();
- if (b->bm_fo < b->bm_bits) {
- i = find_next_bit(b->bm,b->bm_bits,b->bm_fo);
- } else if (b->bm_fo > b->bm_bits) {
+ if (b->bm_fo > b->bm_bits) {
ERR("bm_fo=%lu bm_bits=%lu\n",b->bm_fo, b->bm_bits);
- }
- if (i >= b->bm_bits) {
+ } else {
+ while (b->bm_fo < b->bm_bits) {
+ unsigned long offset;
+ bit_offset = b->bm_fo & ~BPP_MASK; // bit offset of the page
+ offset = bit_offset >> LN2_BPL; // word offset of the page
+ p_addr = bm_map_paddr(b,offset);
+ i = find_next_bit(p_addr,PAGE_SIZE*8,b->bm_fo&BPP_MASK);
+ bm_unmap(p_addr);
+ if (i < PAGE_SIZE*8) {
+ i = bit_offset + i;
+ if( i >= b->bm_bits ) break;
+ b->bm_fo = i+1;
+ goto found;
+ }
+ b->bm_fo = bit_offset + PAGE_SIZE*8;
+ }
i = -1UL;
b->bm_fo = 0;
- } else {
- b->bm_fo = i+1;
}
+ found:
spin_unlock_irq(&b->bm_lock);
return i;
}
@@ -795,7 +1203,6 @@
spin_unlock_irq(&b->bm_lock);
}
-
int drbd_bm_rs_done(drbd_dev *mdev)
{
return mdev->bitmap->bm_fo == 0;
@@ -809,9 +1216,11 @@
int drbd_bm_set_bit(drbd_dev *mdev, const unsigned long bitnr)
{
struct drbd_bitmap *b = mdev->bitmap;
+ unsigned long *p_addr;
int i;
+
ERR_IF(!b) return 1;
- ERR_IF(!b->bm) return 1;
+ ERR_IF(!b->bm_pages) return 1;
/*
* only called from drbd_set_out_of_sync.
@@ -831,7 +1240,10 @@
ERR("bitnr=%lu bm_bits=%lu\n",bitnr, b->bm_bits);
i = 0;
} else {
- i = (0 != __test_and_set_bit(bitnr, b->bm));
+ unsigned long offset = bitnr>>LN2_BPL;
+ p_addr = bm_map_paddr(b,offset);
+ i = (0 != __test_and_set_bit(bitnr & BPP_MASK, p_addr));
+ bm_unmap(p_addr);
b->bm_set += !i;
}
spin_unlock_irq(&b->bm_lock);
@@ -844,10 +1256,12 @@
int drbd_bm_clear_bit(drbd_dev *mdev, const unsigned long bitnr)
{
struct drbd_bitmap *b = mdev->bitmap;
+ unsigned long *p_addr;
unsigned long flags;
int i;
+
ERR_IF(!b) return 0;
- ERR_IF(!b->bm) return 0;
+ ERR_IF(!b->bm_pages) return 0;
spin_lock_irqsave(&b->bm_lock,flags);
BM_PARANOIA_CHECK();
@@ -856,7 +1270,10 @@
ERR("bitnr=%lu bm_bits=%lu\n",bitnr, b->bm_bits);
i = 0;
} else {
- i = (0 != __test_and_clear_bit(bitnr, b->bm));
+ unsigned long offset = bitnr>>LN2_BPL;
+ p_addr = bm_map_paddr(b,offset);
+ i = (0 != __test_and_clear_bit(bitnr & BPP_MASK, p_addr));
+ bm_unmap(p_addr);
b->bm_set -= i;
}
spin_unlock_irqrestore(&b->bm_lock,flags);
@@ -882,14 +1299,19 @@
int drbd_bm_test_bit(drbd_dev *mdev, const unsigned long bitnr)
{
struct drbd_bitmap *b = mdev->bitmap;
+ unsigned long *p_addr;
int i;
+
ERR_IF(!b) return 0;
- ERR_IF(!b->bm) return 0;
+ ERR_IF(!b->bm_pages) return 0;
spin_lock_irq(&b->bm_lock);
BM_PARANOIA_CHECK();
if (bitnr < b->bm_bits) {
- i = test_bit(bitnr, b->bm);
+ unsigned long offset = bitnr>>LN2_BPL;
+ p_addr = bm_map_paddr(b,offset);
+ i = test_bit(bitnr & BPP_MASK, p_addr);
+ bm_unmap(p_addr);
} else if (bitnr == b->bm_bits) {
i = -1;
} else /* (bitnr > b->bm_bits) */ {
@@ -920,9 +1342,11 @@
struct drbd_bitmap *b = mdev->bitmap;
int count, s, e;
unsigned long flags;
+ unsigned long *p_addr, *bm;
ERR_IF(!b) return 0;
- ERR_IF(!b->bm) return 0;
+ ERR_IF(!b->bm_pages) return 0;
+
spin_lock_irqsave(&b->bm_lock,flags);
BM_PARANOIA_CHECK();
@@ -930,9 +1354,15 @@
e = min((size_t)S2W(enr+1),b->bm_words);
count = 0;
if (s < b->bm_words) {
- const unsigned long* w = b->bm+s;
int n = e-s;
- while (n--) count += hweight_long(*w++);
+ p_addr = bm_map_paddr(b,s);
+ bm = p_addr + MLPP(s);
+ while (n--) {
+ catch_oob_access_start();
+ count += hweight_long(*bm++);
+ catch_oob_access_end();
+ }
+ bm_unmap(p_addr);
} else {
ERR("start offset (%d) too large in drbd_bm_e_weight\n", s);
}
@@ -947,10 +1377,11 @@
unsigned long drbd_bm_ALe_set_all(drbd_dev *mdev, unsigned long al_enr)
{
struct drbd_bitmap *b = mdev->bitmap;
+ unsigned long *p_addr, *bm;
unsigned long weight;
- int count, s, e;
+ int count, s, e, i, do_now;
ERR_IF(!b) return 0;
- ERR_IF(!b->bm) return 0;
+ ERR_IF(!b->bm_pages) return 0;
MUST_BE_LOCKED();
@@ -960,14 +1391,23 @@
s = al_enr * BM_WORDS_PER_AL_EXT;
e = min_t(size_t, s + BM_WORDS_PER_AL_EXT, b->bm_words);
+ /* assert that s and e are on the same page */
+ D_ASSERT( (e-1) >> (PAGE_SHIFT - LN2_BPL + 3)
+ == s >> (PAGE_SHIFT - LN2_BPL + 3) );
count = 0;
if (s < b->bm_words) {
- const unsigned long* w = b->bm+s;
- int n = e-s;
- while (n--) count += hweight_long(*w++);
- n = e-s;
- memset(b->bm+s,-1,n*sizeof(long));
- b->bm_set += n*BITS_PER_LONG - count;
+ i = do_now = e-s;
+ p_addr = bm_map_paddr(b,s);
+ bm = p_addr + MLPP(s);
+ while (i--) {
+ catch_oob_access_start();
+ count += hweight_long(*bm);
+ *bm = -1UL;
+ catch_oob_access_end();
+ bm++;
+ }
+ bm_unmap(p_addr);
+ b->bm_set += do_now*BITS_PER_LONG - count;
if (e == b->bm_words) {
b->bm_set -= bm_clear_surplus(b);
}
Modified: trunk/drbd/drbd_compat_wrappers.h
===================================================================
--- trunk/drbd/drbd_compat_wrappers.h 2006-03-03 15:38:34 UTC (rev 2089)
+++ trunk/drbd/drbd_compat_wrappers.h 2006-03-03 15:47:52 UTC (rev 2090)
@@ -7,6 +7,14 @@
# error "use a 2.6 kernel, please"
#endif
+
+/* struct page has a union since 2.6.15 ... */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
+#define U_PRIVATE private
+#else
+#define U_PRIVATE u.private
+#endif
+
#include <linux/buffer_head.h> // for fsync_bdev
/* see get_sb_bdev and bd_claim */
Modified: trunk/drbd/drbd_int.h
===================================================================
--- trunk/drbd/drbd_int.h 2006-03-03 15:38:34 UTC (rev 2089)
+++ trunk/drbd/drbd_int.h 2006-03-03 15:47:52 UTC (rev 2090)
@@ -116,6 +116,19 @@
#define DUMPST(A) DUMPLLU((unsigned long long)(A))
+#if 0
+#define D_DUMPP(A) DUMPP(A)
+#define D_DUMPLU(A) DUMPLU(A)
+#define D_DUMPLLU(A) DUMPLLU(A)
+#define D_DUMPLX(A) DUMPLX(A)
+#define D_DUMPI(A) DUMPI(A)
+#else
+#define D_DUMPP(A)
+#define D_DUMPLU(A)
+#define D_DUMPLLU(A)
+#define D_DUMPLX(A)
+#define D_DUMPI(A)
+#endif
// Info: do not remove the spaces around the "," before ##
// Otherwise this is not portable from gcc-2.95 to gcc-3.3
Modified: trunk/drbd/drbd_main.c
===================================================================
--- trunk/drbd/drbd_main.c 2006-03-03 15:38:34 UTC (rev 2089)
+++ trunk/drbd/drbd_main.c 2006-03-03 15:47:52 UTC (rev 2090)
@@ -1929,7 +1929,7 @@
while(drbd_pp_pool) {
page = drbd_pp_pool;
- drbd_pp_pool = (struct page*)page->private;
+ drbd_pp_pool = (struct page*)page->U_PRIVATE;
__free_page(page);
drbd_pp_vacant--;
}
@@ -1998,7 +1998,7 @@
for (i=0;i< number;i++) {
page = alloc_page(GFP_HIGHUSER);
if(!page) goto Enomem;
- page->private = (unsigned long)drbd_pp_pool;
+ page->U_PRIVATE = (unsigned long)drbd_pp_pool;
drbd_pp_pool = page;
}
drbd_pp_vacant = number;
Modified: trunk/drbd/drbd_receiver.c
===================================================================
--- trunk/drbd/drbd_receiver.c 2006-03-03 15:38:34 UTC (rev 2089)
+++ trunk/drbd/drbd_receiver.c 2006-03-03 15:47:52 UTC (rev 2090)
@@ -52,7 +52,7 @@
#include <linux/drbd.h>
#include "drbd_int.h"
-#ifdef __arch_um__
+#if defined(__arch_um__) && !defined(HAVE_UML_TO_VIRT)
void *to_virt(unsigned long phys)
{
return((void *) uml_physmem + phys);
@@ -136,7 +136,7 @@
/* first, use our pool. */
spin_lock(&drbd_pp_lock);
if ( (page = drbd_pp_pool) ) {
- drbd_pp_pool = (struct page*)page->private;
+ drbd_pp_pool = (struct page*)page->U_PRIVATE;
drbd_pp_vacant--;
}
spin_unlock(&drbd_pp_lock);
@@ -150,7 +150,7 @@
/* try the pool again, maybe the drbd_kick_log set some free */
spin_lock(&drbd_pp_lock);
if ( (page = drbd_pp_pool) ) {
- drbd_pp_pool = (struct page*)page->private;
+ drbd_pp_pool = (struct page*)page->U_PRIVATE;
drbd_pp_vacant--;
}
spin_unlock(&drbd_pp_lock);
@@ -192,7 +192,7 @@
if (drbd_pp_vacant > (DRBD_MAX_SEGMENT_SIZE/PAGE_SIZE)*minor_count) {
__free_page(page);
} else {
- page->private = (unsigned long)drbd_pp_pool;
+ page->U_PRIVATE = (unsigned long)drbd_pp_pool;
drbd_pp_pool = page;
drbd_pp_vacant++;
}
Modified: trunk/drbd/linux/drbd_config.h
===================================================================
--- trunk/drbd/linux/drbd_config.h 2006-03-03 15:38:34 UTC (rev 2089)
+++ trunk/drbd/linux/drbd_config.h 2006-03-03 15:47:52 UTC (rev 2090)
@@ -26,6 +26,9 @@
#define API_VERSION 80
#define PRO_VERSION 80
+// undef if you need the workaround in drbd_receiver
+#define HAVE_UML_TO_VIRT 1
+
//#define DBG_ALL_SYMBOLS // no static functs, improves quality of OOPS traces
//#define DBG_SPINLOCKS // enables MUST_HOLD macro (assertions for spinlocks)
More information about the drbd-cvs
mailing list