--- linux-2.6.11.6/drivers/md/bitmap.h.orig Sun Jun 12 00:11:44 2005 +++ linux-2.6.11.6/drivers/md/bitmap.h Sun Jun 12 00:11:44 2005 @@ -0,0 +1,62 @@ +#ifndef BITMAP_H +#define BITMAP_H 1 + +struct bitmap_page { + /* + * If a page is missing then we use a per + * page pending write count instead. pages is the number of + * 4k pages in the map. + */ + char * map; + /* + * more precise count per zone (1/16 page), for emergencies. + */ + short *zoneinfo; + /* + * count of dirty bits on the page + */ + unsigned short count; +}; + +struct bitmap { + struct bitmap_page * bp; // array of size pages + unsigned long pages; // maximum #pages, mapping 32k blocks each + + int (*start) (struct bitmap * bitmap, __u64 events); + void (*stop) (struct bitmap * bitmap); + int (*testbits) (struct bitmap * bitmap, sector_t shift, unsigned long bits); + int (*setbits) (struct bitmap * bitmap, sector_t shift, unsigned long bits); + int (*clearbits) (struct bitmap * bitmap, sector_t shift, unsigned long bits); + int (*active) (struct bitmap * bitmap); + + /* bitmap spinlock */ + rwlock_t lock; + +#define BITMAP_ACTIVE 0x01 + unsigned long flags; + + /* + * events count at startup of the bitmap + */ + __u64 events; + + /* + * number of missing zoneinfo sections + */ + unsigned long missing_zones; + unsigned long missing_pages; + + /* + * pages currently in the map + */ + unsigned long current_pages; + unsigned long alloced_pages; + + void (*print_stats) (struct bitmap * bitmap); +}; + + +int bitmap_init(struct bitmap * bitmap, unsigned long long bits); +void bitmap_destr(struct bitmap * bitmap); + +#endif --- linux-2.6.11.6/drivers/md/bitmap.c.orig Sun Jun 12 00:11:44 2005 +++ linux-2.6.11.6/drivers/md/bitmap.c Sun Jun 12 00:11:44 2005 @@ -0,0 +1,887 @@ +/* + * bitmap.c two-level bitmap (C) Peter T. Breuer (ptb@ot.uc3m.es) 2003 + * + * bitmap_init - sets nr blks + * bitmap->start - then calls the setup part for the 1st + * level in the bitmap, which uses memory (kmalloc) so + * can fail. You should examine the return value. 0 is + * OK. -ve is FAIL. + * + * bitmap->stop - inverse to bitmap->start. kfrees the memory claimed in + * bitmap_init. + * + * bitmap_detr - inverse to init. Detroys pages, etc. + */ + +#include +#include +#include +#include // PTB for kmalloc! How? +#include // PTB for vmalloc +#include +#include + +# define DEBUG 1 + +#include "bitmap.h" + +/* use 16 bits of the address as extra bitmap */ +#define ZONESHIFT 4 +/* top 16 bits are nonzero */ +#define IS_ADDRESS(x) \ + ((( ((unsigned long)(x)) >> ((sizeof(char*)<<3) - (1< 0 +# define PRINTK(x...) printk(x) +# else +# define PRINTK(x...) +# endif +#endif + +/* cache of ready to go pages */ +static kmem_cache_t * bitmap_page_cache; + +/* + * replaces kfree on bitmap pages. + */ +static void +bitmap_free_page(struct bitmap * bitmap, unsigned char * page) { + + if (!page) + return; + + kmem_cache_free(bitmap_page_cache, (void *)page); + bitmap->alloced_pages--; +} + +static void +bitmap_print_stats(struct bitmap * bitmap) { + printk(KERN_INFO "bitmap: %lu pages in use\n", + bitmap->current_pages); + printk(KERN_INFO "bitmap: %lu pages allocated\n", + bitmap->alloced_pages); + printk(KERN_INFO "bitmap: %lu pages pre-allocated \n", + bitmap->alloced_pages - bitmap->current_pages); +} + +/* + * mark bitmap inactive and maybe prune the page cache + */ +static void +bitmap_stop(struct bitmap * bitmap) { + + write_lock(&bitmap->lock); + bitmap->flags &= ~BITMAP_ACTIVE; + write_unlock(&bitmap->lock); +} + +/* + * frees mamory kmalloced in bitmap_init + */ +void +bitmap_destr(struct bitmap *bitmap) { + + unsigned long k; + struct bitmap_page * bp; + unsigned long pages; + + printk(KERN_DEBUG "destroying bitmap %p\n", bitmap); + + bitmap_stop(bitmap); + bitmap_print_stats(bitmap); + + write_lock(&bitmap->lock); + bitmap->flags &= ~BITMAP_ACTIVE; + bp = bitmap->bp; + pages = bitmap->pages; + bitmap->bp = NULL; + bitmap->missing_pages = pages; + bitmap->current_pages = 0; + bitmap->alloced_pages = 0; + bitmap->missing_zones = pages; + write_unlock(&bitmap->lock); + + if (bp) { + for (k = 0; k < pages; k++) { + if (IS_ADDRESS(bp[k].map)) { + bitmap_free_page (bitmap, bp[k].map); + bp[k].map = NULL; + } + if (IS_ADDRESS(bp[k].zoneinfo)) { + kfree (bp[k].zoneinfo); + bp[k].zoneinfo = NULL; + } + } + vfree (bp); + } + + bitmap_stop(bitmap); + + MOD_DEC_USE_COUNT; + THIS_MODULE->unsafe = 0; +} + +/* + * tests if the bitmap is marked active (has been started) + * Returns the events count on the bitmap. + */ +static int +bitmap_active(struct bitmap * bitmap) { + int res = 0; + if (!bitmap) + return res; + read_lock(&bitmap->lock); + if (bitmap->flags & BITMAP_ACTIVE) { + res = (unsigned int)bitmap->events; + if (res <= 0) + res = 1; + } else { + res = 0; + } + read_unlock(&bitmap->lock); + return res; +} + +/* + * replaces kmalloc for bitmap pages. + */ +static unsigned char * +bitmap_alloc_page(struct bitmap *bitmap) { + unsigned char *page; + + page = kmem_cache_alloc(bitmap_page_cache, GFP_KERNEL); + /* PTB zeroing is done by the constructor and only + * clean pages are returned to the cache + */ + if (page) + bitmap->alloced_pages++; + return page; +} + + + +/* + * marks the bitmap active and primes the free page cache. + */ +static int +bitmap_start(struct bitmap * bitmap, u64 events) { + + struct bitmap_page * bp; + unsigned long pages; + + /* take lock to read data */ + write_lock(&bitmap->lock); + pages = bitmap->pages; + bp = bitmap->bp; + write_unlock(&bitmap->lock); + + if (!bp) { + + int k; + + bp = vmalloc (pages * sizeof(*bp)); + if (!bp) { + printk(KERN_WARNING "bitmap: cannot get %luB of memory!\n", + pages * sizeof(*bp)); + return -ENOMEM; + } + memset (bp, 0, pages * sizeof(*bp)); + + for (k = 0; k < pages; k++) { + if (bp[k].zoneinfo) + continue; + bp[k].zoneinfo = + kmalloc (sizeof(*bp[k].zoneinfo)<missing_zones--; + } + if (bitmap->missing_zones > 0) { + printk(KERN_WARNING "bitmap: warning! cannot get %ld*%uB memory!\n", + bitmap->missing_zones, + sizeof(*bp->zoneinfo) << ZONESHIFT); + } + } + + /* + * this is 16 shorts or 32 bytes + 4 bytes extra per page of 4096 + * bytes, which is a reserve of less that 0.1%. But each page + * bitmaps 32MB of disk, so a 1GB disk takes 32 pages or 128KB, and + * a 1TB disk takes 128MB of pages. In those circumstances, + * adding a capital cost of about 108KB doesn't seem bad. + */ + + + write_lock(&bitmap->lock); + bitmap->bp = bp; + + bitmap->flags |= BITMAP_ACTIVE; + bitmap->events = events; + write_unlock(&bitmap->lock); + + /* seed the page cache */ + bitmap_free_page(bitmap, bitmap_alloc_page(bitmap)); + + return 0; +} + +/* + * Test if the page is in the map, and bring it in if not. + * + * Return 0 for success. + */ +static int +bitmap_checkpage (struct bitmap *bitmap, unsigned long page) +{ + unsigned char * mappage; + + read_lock(&bitmap->lock); + if (page < 0 || page >= bitmap->pages) { + read_unlock(&bitmap->lock); + return -EINVAL; + } + + if (bitmap->bp == NULL) { + read_unlock(&bitmap->lock); + return -ENODEV; + } + + + if (IS_ADDRESS(bitmap->bp[page].map)) { + read_unlock(&bitmap->lock); + return 0; + } + read_unlock(&bitmap->lock); + + /* the page address was NULL */ + + if ((mappage = bitmap_alloc_page(bitmap)) == NULL) { + /* failed - check to see if we have backup counters */ + void * tmp; + int need_new_zoneinfo = 0; + + write_lock(&bitmap->lock); + if (!IS_ADDRESS(bitmap->bp[page].zoneinfo)) + need_new_zoneinfo = 1; + write_unlock(&bitmap->lock); + + if (need_new_zoneinfo) { + /* rarely, we might make an extra backup counter */ + tmp = kmalloc(sizeof(*bitmap->bp->zoneinfo)<lock); + if (IS_ADDRESS(bitmap->bp[page].zoneinfo)) { + /* somebody else made it first, backout */ + need_new_zoneinfo = 0; + } else { + bitmap->bp[page].zoneinfo = tmp; + bitmap->missing_zones--; + } + write_unlock(&bitmap->lock); + + if (!need_new_zoneinfo) + kfree(tmp); + } + } + return -ENOMEM; + } + + /* got a page */ + + write_lock(&bitmap->lock); + + /* recheck the page */ + + if (IS_ADDRESS(bitmap->bp[page].map)) { + /* somebody beat us to getting the page */ + write_unlock(&bitmap->lock); + bitmap_free_page(bitmap, mappage); + return 0; + } + + /* no page in place and we have one, so maybe install it */ + + if (bitmap->bp[page].count != 0) { + /* inpage bitmap - can't replace until no pending writes */ + write_unlock(&bitmap->lock); + bitmap_free_page(bitmap, mappage); + return -EINVAL; + } + + /* good case - we get to make a new page */ + memset(mappage, 0, PAGE_SIZE); + bitmap->bp[page].map = mappage; + if (IS_ADDRESS(bitmap->bp[page].zoneinfo)) { + memset(bitmap->bp[page].zoneinfo, 0, + sizeof(*bitmap->bp->zoneinfo) << ZONESHIFT); + } + bitmap->missing_pages--; + bitmap->current_pages++; + write_unlock(&bitmap->lock); + return 0; + +} + +/* + * offset8 is the BYTE offset, not the bit offset + * We call this routine under lock. + */ +static int +bitmap_clear_mask8 (struct bitmap *bitmap, sector_t offset8, + unsigned char mask, unsigned char **this_page) +{ + + unsigned long page ; + unsigned long pageoff; + + unsigned char oldmask; + unsigned char newmask; + unsigned char diffmask; + + page = offset8 >> PAGE_SHIFT; + + if (!IS_ADDRESS(bitmap->bp[page].map)) { + int bits = hweight8(mask); + bitmap->bp[page].count -= bits; + if (IS_ADDRESS(bitmap->bp[page].zoneinfo)) { + int zoneoffset = (offset8 >> (PAGE_SHIFT - ZONESHIFT)); + int zone = zoneoffset & ((1<bp[page].zoneinfo[zone] -= bits; + } + return -EINVAL; + } + + pageoff = offset8 & ~PAGE_MASK; + + oldmask = bitmap->bp[page].map[pageoff]; + newmask = oldmask & ~mask; + diffmask = newmask ^ oldmask; + + if (diffmask) { + unsigned bits = hweight8 (diffmask); + int newcount = (bitmap->bp[page].count -= bits); + + bitmap->bp[page].map[pageoff] = newmask; + + /* most frequent case is a +ve result and return */ + if (newcount > 0) + return 0; + /* negative count is a major misaccounting */ + if (newcount < 0) { + printk(KERN_WARNING "bitmap: dirty count %d on page %lu\n", + newcount, page); + return 0; + } + /* newcount == 0 is when we want to detach the page */ + *this_page = bitmap->bp[page].map; + bitmap->bp[page].map = NULL; + bitmap->missing_pages++; + bitmap->current_pages--; + return 0; + } + return 0; +} + +/* + * offset is the bit count, i.e. the block number. + */ +static int +bitmap_clear_mask (struct bitmap *bitmap, sector_t offset, unsigned char mask) +{ + + unsigned long blkgrp; + unsigned char blkoff; + unsigned long page ; + unsigned long pageoff; + int errs = 0; + unsigned char * free_page0 = NULL, *free_page1 = NULL; + + blkgrp = offset >> 3; + page = blkgrp >> PAGE_SHIFT; + + blkoff = offset & 7; + pageoff= blkgrp & ~PAGE_MASK; + + write_lock(&bitmap->lock); + + if (blkoff) { + unsigned char maskdiv = 0xff & (mask << blkoff); + unsigned char maskrem = 0xff & (mask >> (8 - blkoff)); + + if (maskdiv) { + if (bitmap_clear_mask8 (bitmap, blkgrp, maskdiv, &free_page0) < 0) + errs++; + } + if (!maskrem) { + goto out; + } + if (pageoff + 1 < PAGE_SIZE) { + + if (bitmap_clear_mask8 (bitmap, blkgrp + 1, maskrem, &free_page1) < 0) + errs++; + goto out; + } + + if (bitmap_clear_mask8 (bitmap, blkgrp + 1, maskrem, &free_page1) < 0) + errs++; + goto out; + } + + // normal situation. Offset is multiple of 8 + + if (bitmap_clear_mask8 (bitmap, blkgrp, mask, &free_page0) < 0) + errs++; +out: + write_unlock(&bitmap->lock); + if (free_page0) + bitmap_free_page(bitmap, free_page0); + if (free_page1) + bitmap_free_page(bitmap, free_page1); + return errs > 0 ? -EINVAL : 0; +} + + +/* + * offset8 is the BYTE offset, not the bit offset. + * We call this routine under lock. + */ +static int +bitmap_set_mask8 (struct bitmap *bitmap, sector_t offset8, + unsigned char mask) +{ + + unsigned long page ; + unsigned long pageoff; + + unsigned char oldmask; + unsigned char newmask; + unsigned char diffmask; + + page = offset8 >> PAGE_SHIFT; + pageoff = offset8 & ~PAGE_MASK; + + if (!IS_ADDRESS(bitmap->bp[page].map)) { + int bits = hweight8(mask); + bitmap->bp[page].count += bits; + /* mark the zone instead - we have 16 low bits markable */ + if (IS_ADDRESS(bitmap->bp[page].zoneinfo)) { + int zoneoffset = (offset8 >> (PAGE_SHIFT - ZONESHIFT)); + int zone = zoneoffset & ((1 << ZONESHIFT) - 1); + bitmap->bp[page].zoneinfo[zone] += bits; + } + return -EINVAL; + } + + oldmask = bitmap->bp[page].map[pageoff]; + newmask = oldmask | mask; + diffmask = newmask ^ oldmask; + + if (diffmask) { + unsigned int bits = hweight8 (diffmask); + bitmap->bp[page].map[pageoff] = newmask; + bitmap->bp[page].count += bits; + } + return 0; +} + +/* + * offset8 is the BYTE offset, not the bit offset. + * We call this routine under lock. + */ +static int +bitmap_test_mask8 (struct bitmap *bitmap, sector_t offset8, + unsigned char mask) +{ + + unsigned long page ; + unsigned long pageoff; + + if (!mask) + return 0; + + page = offset8 >> PAGE_SHIFT; + pageoff = offset8 & ~PAGE_MASK; + + if (!IS_ADDRESS(bitmap->bp[page].map)) { + /* look at zone instead - we have 16 low bits markable */ + if (IS_ADDRESS(bitmap->bp[page].zoneinfo)) { + int zoneoffset = (offset8 >> (PAGE_SHIFT - ZONESHIFT)); + int zone = zoneoffset & ((1 << ZONESHIFT) - 1); + if (bitmap->bp[page].zoneinfo[zone] > 0) + return 1; + return 0; + } + /* try the count */ + if (bitmap->bp[page].count > 0) + return 1; + return 0; + } + + return (bitmap->bp[page].map[pageoff] & mask) != 0; +} + +/* + * here offset is the BIT offset + */ +static int +bitmap_set_mask (struct bitmap *bitmap, sector_t offset, unsigned char mask) +{ + + unsigned long blkgrp; + unsigned char blkoff; + unsigned long page ; + unsigned long pageoff; + int errs = 0; + + blkgrp = offset >> 3; + page = blkgrp >> PAGE_SHIFT; + + if (bitmap_checkpage(bitmap, page) < 0) + errs++; + + /* the page may or may not have been made */ + + write_lock(&bitmap->lock); + blkoff = offset & 7; + pageoff= blkgrp & ~PAGE_MASK; + + if (blkoff) { + unsigned char maskdiv = 0xff & (mask << blkoff); + unsigned char maskrem = 0xff & (mask >> (8 - blkoff)); + + if (maskdiv) { + if (bitmap_set_mask8(bitmap, blkgrp, maskdiv) < 0) + errs++; + } + + if (!maskrem) { + write_unlock(&bitmap->lock); + return errs > 0 ? -EINVAL : 0 ; + } + + if (pageoff + 1 < PAGE_SIZE) { + + if (bitmap_set_mask8(bitmap, blkgrp + 1, maskrem) < 0) + errs++; + write_unlock(&bitmap->lock); + return errs > 0 ? -EINVAL : 0 ; + } + write_unlock(&bitmap->lock); + if (bitmap_checkpage(bitmap, page+1) < 0) + errs++; + + write_lock(&bitmap->lock); + + if (bitmap_set_mask8(bitmap, blkgrp + 1, maskrem) < 0) + errs++; + + write_unlock(&bitmap->lock); + return errs > 0 ? -EINVAL : 0 ; + } + + // normal situation. Offset is multiple of 8 + + if (bitmap_set_mask8(bitmap, blkgrp, mask) < 0) + errs++; + + write_unlock(&bitmap->lock); + return errs > 0 ? -EINVAL : 0; +} + +/* + * here offset is the BIT offset + */ +static int +bitmap_test_mask (struct bitmap *bitmap, sector_t offset, unsigned char mask) +{ + + unsigned long blkgrp; + unsigned char blkoff; + unsigned long page ; + unsigned long pageoff; + int err; + + blkgrp = offset >> 3; + page = blkgrp >> PAGE_SHIFT; + + if (bitmap_checkpage(bitmap, page) < 0) + ; // ignore. We'll react below + + /* the page may or may not have been made */ + + write_lock(&bitmap->lock); + blkoff = offset & 7; + pageoff= blkgrp & ~PAGE_MASK; + + if (blkoff) { + unsigned char maskdiv = 0xff & (mask << blkoff); + unsigned char maskrem = 0xff & (mask >> (8 - blkoff)); + + if (maskdiv) { + if (err = bitmap_test_mask8(bitmap, blkgrp, maskdiv), err) { + write_unlock(&bitmap->lock); + return err; + } + } + + if (!maskrem) { + write_unlock(&bitmap->lock); + return 0 ; + } + + if (pageoff + 1 < PAGE_SIZE) { + + if (err = bitmap_test_mask8(bitmap, blkgrp + 1, maskrem), err) { + write_unlock(&bitmap->lock); + return err; + } + write_unlock(&bitmap->lock); + return 0 ; + } + write_unlock(&bitmap->lock); + if (err = bitmap_checkpage(bitmap, page+1), err < 0) + ; // ignore errors + + write_lock(&bitmap->lock); + + if (err = bitmap_test_mask8(bitmap, blkgrp + 1, maskrem), err) { + write_unlock(&bitmap->lock); + return err; + } + + write_unlock(&bitmap->lock); + return 0 ; + } + + // normal situation. Offset is multiple of 8 + + if (err = bitmap_test_mask8(bitmap, blkgrp, mask), err) { + write_unlock(&bitmap->lock); + return err ; + } + + write_unlock(&bitmap->lock); + return 0; +} + +static int +bitmap_clear_bits (struct bitmap *bitmap, sector_t offset, unsigned long bits) +{ + + unsigned char mask; + int errs = 0; + + while (offset + bits >= (offset | 7) + 1) { + int more = (offset | 7) + 1 - offset; + mask = (1 << more) - 1; + /* ignore errors and do what we can */ + if (bitmap_clear_mask(bitmap, offset, mask) < 0) { + errs++; + } + bits -= more; + offset |= 7; + offset++; + } + + if (bits > 0) { + mask = (1 << bits) - 1; + /* ignore errors and do what we can */ + if (bitmap_clear_mask(bitmap, offset, mask) < 0) { + errs++; + } + bits = 0; + offset += bits; + } + + return (errs > 0) ? -EINVAL : 0; +} + +static int +bitmap_set_bits (struct bitmap *bitmap, sector_t offset, unsigned long bits) +{ + + unsigned char mask; + int errs = 0; + + while (offset + bits >= (offset | 7) + 1) { + int more = (offset | 7) + 1 - offset; + mask = (1 << more) - 1; + /* ignore errors and do what we can */ + if (bitmap_set_mask(bitmap, offset, mask) < 0) { + errs++; + } + bits -= more; + offset |= 7; + offset++; + } + + if (bits > 0) { + mask = (1 << bits) - 1; + /* ignore errors and do what we can */ + if (bitmap_set_mask(bitmap, offset, mask) < 0) { + errs++; + } + bits = 0; + offset += bits; + } + + return (errs > 0) ? -EINVAL : 0; +} + +static int +bitmap_test_bits (struct bitmap *bitmap, sector_t offset, unsigned long bits) +{ + unsigned char mask; + int err; + + while (offset + bits >= (offset | 7) + 1) { + int more = (offset | 7) + 1 - offset; + mask = (1 << more) - 1; + /* ignore errors and do what we can */ + if (err = bitmap_test_mask(bitmap, offset, mask), err) { + return err; + } + bits -= more; + offset |= 7; + offset++; + } + + if (bits > 0) { + mask = (1 << bits) - 1; + /* ignore errors and do what we can */ + if (err = bitmap_test_mask(bitmap, offset, mask), err) { + return err; + } + bits = 0; + offset += bits; + } + + return 0; +} + +/* +static int +bitmap_test_bit (struct bitmap *bitmap, unsigned long block) +{ + unsigned long blkgrp; + unsigned char blkoff; + unsigned long page ; + unsigned long pageoff; + int res; + + blkgrp = block >> 3; + page = blkgrp >> PAGE_SHIFT; + + read_lock(&bitmap->lock); + // high bits zero means no page address + if (!IS_ADDRESS(bitmap->bp[page].map)) { + int zoneoffset = (blkgrp >> (PAGE_SHIFT - ZONESHIFT)); + int zone = zoneoffset & ((1 << ZONESHIFT) - 1); + // use the counter instead - this is zoned + res = (bitmap->bp[page].count > 0); + if (res && IS_ADDRESS(bitmap->bp[page].zoneinfo)) + res = (bitmap->bp[page].zoneinfo[zone] > 0); + read_unlock(&bitmap->lock); + return res; + } + + blkoff = block & 7; + pageoff= blkgrp & ~PAGE_MASK; + + res = test_bit ((pageoff << 3) + blkoff, bitmap->bp[page].map) != 0; + read_unlock(&bitmap->lock); + return res; +} +*/ + +int +bitmap_init(struct bitmap * bitmap, unsigned long long blocks) { + + unsigned long pages = (blocks + (PAGE_SIZE * 8 - 1)) / (PAGE_SIZE * 8); + + memset(bitmap, 0, sizeof(*bitmap)); + rwlock_init (&bitmap->lock); + write_lock(&bitmap->lock); + + bitmap->start = bitmap_start; + bitmap->stop = bitmap_stop; + bitmap->testbits = bitmap_test_bits; + bitmap->setbits = bitmap_set_bits; + bitmap->clearbits = bitmap_clear_bits; + bitmap->active = bitmap_active; + bitmap->print_stats = bitmap_print_stats; + + /* now do 1st level init stuff */ + if (pages < 0) { + write_unlock(&bitmap->lock); + printk(KERN_WARNING "bitmap: initialised for -ve number of pages (%ld)!\n", + pages); + return -EINVAL; + } + bitmap->pages = pages; + bitmap->missing_zones = pages; + bitmap->missing_pages = pages; + bitmap->current_pages = 0; + bitmap->alloced_pages = 0; + + // we are all using the same page cache. + MOD_INC_USE_COUNT; + THIS_MODULE->unsafe = 0; + + write_unlock(&bitmap->lock); + return 0; +} + +static void +bitmap_clear_page(void *data, kmem_cache_t *cache, unsigned long flags) { + + if (! (flags & SLAB_CTOR_CONSTRUCTOR)) + return; + if (!data) + return; + memset(data, 0, PAGE_SIZE); +} + +int +bitmap_init_page_cache(void) { + bitmap_page_cache = + kmem_cache_create("bitmap_page", PAGE_SIZE, 0, 0, bitmap_clear_page, NULL); + if (!bitmap_page_cache) + return -ENOMEM; + return 0; +} + +#ifdef MODULE +void cleanup_module(void) +{ + if (!bitmap_page_cache) + return; + kmem_cache_destroy(bitmap_page_cache); + bitmap_page_cache = NULL; +} + +int init_module(void) +{ + return bitmap_init_page_cache(); +} + + MODULE_AUTHOR ("Peter T. Breuer"); + MODULE_DESCRIPTION ("Bitmap support"); + MODULE_LICENSE("GPL"); + int linux_version_code = LINUX_VERSION_CODE; +#else /* MODULE */ +__initcall(bitmap_init_page_cache); +#endif /* MODULE */ + +EXPORT_SYMBOL(bitmap_destr); +EXPORT_SYMBOL(bitmap_init); + +/* Compile line: + * + * gcc -O2 -D__KERNEL__ -DMODULE -c bitmap.c -o bitmap.o + * + */ + --- linux-2.6.11.6/include/linux/raid/raid1.h.orig Sat Mar 26 04:28:22 2005 +++ linux-2.6.11.6/include/linux/raid/raid1.h Sun Jun 12 00:11:44 2005 @@ -50,6 +50,17 @@ mempool_t *r1bio_pool; mempool_t *r1buf_pool; + +#ifdef CONFIG_MD_FR1 + long last_clean_sector; /* helps debugging */ + long last_dirty_sector; + int sync_mode; /* clean/dirty pass? */ + void *bitmap; /* the array bitmap */ + int bitmap_dirty; /* flag */ + int latency[MD_SB_DISKS]; + int last_source; /* disk read from */ +#endif /* CONFIG_MD_FR1 */ + }; typedef struct r1_private_data_s conf_t; @@ -85,6 +96,12 @@ int read_disk; struct list_head retry_list; + +#ifdef CONFIG_MD_FR1 + int nonoperational; /* no of bad mirrors */ + unsigned long start_jiffies; /* when i/o started */ +#endif /* CONFIG_MD_FR1 */ + /* * if the IO is in WRITE direction, then multiple bios are used. * We choose the number when they are allocated. @@ -95,4 +112,12 @@ /* bits for r1bio.state */ #define R1BIO_Uptodate 0 #define R1BIO_IsSync 1 +#ifdef CONFIG_MD_FR1 + #define R1BIO_AsyncPhase 4 + #define R1BIO_AsyncIO 5 +#endif /* CONFIG_MD_FR1 */ +#ifdef DO_ADD_READ_WRITE_CORRECT +#define R1BIO_ReadRetry 6 +#endif /* DO_ADD_READ_WRITE_CORRECT */ + #endif --- linux-2.6.11.6/include/linux/raid/md_p.h.orig Sat Mar 26 04:28:16 2005 +++ linux-2.6.11.6/include/linux/raid/md_p.h Sun Jun 12 09:11:53 2005 @@ -140,7 +140,20 @@ __u32 cp_events_hi; /* 10 high-order of checkpoint update count */ #endif __u32 recovery_cp; /* 11 recovery checkpoint sector count */ - __u32 gstate_sreserved[MD_SB_GENERIC_STATE_WORDS - 12]; +#ifdef __BIG_ENDIAN + __u32 bitmap_events_hi; /* 12 high-order bits of bitmap events count */ + __u32 bitmap_events_lo; /* 13 low-order bits of bitmap events count */ +#else + __u32 bitmap_events_lo; /* 12 low-order bits of bitmap events count */ + __u32 bitmap_events_hi; /* 13 high-order bits of bitmap events count */ +#endif + /* Begin macros to use 2 ints to support fast raid */ +#define MD_SB_BITMAP_EVENTS_LO(sb) (sb)->bitmap_events_lo +#define MD_SB_BITMAP_EVENTS_HI(sb) (sb)->bitmap_events_hi +#define MD_SB_BITMAP_EVENTS(sb) \ + (((u64)MD_SB_BITMAP_EVENTS_HI(sb) << 32)|((u64)MD_SB_BITMAP_EVENTS_LO(sb))) + /* End macros to use 2 ints to support fast raid */ + __u32 gstate_sreserved[MD_SB_GENERIC_STATE_WORDS - 14]; /* * Personality information @@ -215,7 +228,15 @@ __u64 resync_offset; /* data before this offset (from data_offset) known to be in sync */ __u32 sb_csum; /* checksum upto devs[max_dev] */ __u32 max_dev; /* size of devs[] array to consider */ - __u8 pad3[64-32]; /* set to 0 when writing */ + __u32 bitmap_events_lo; /* low-order bits of bitmap events count */ + __u32 bitmap_events_hi; /* high-order bits of bitmap events count */ + /* Begin macros to use 2 ints to support fast raid */ +#define MD_SB_BITMAP_EVENTS_LO_1(sb) (sb)->bitmap_events_lo +#define MD_SB_BITMAP_EVENTS_HI_1(sb) (sb)->bitmap_events_hi +#define MD_SB_BITMAP_EVENTS_1(sb) \ + (((u64)MD_SB_BITMAP_EVENTS_HI_1(sb) << 32)|((u64)MD_SB_BITMAP_EVENTS_LO_1(sb))) + /* End macros to use 2 ints to support fast raid */ + __u8 pad3[64-40]; /* set to 0 when writing */ /* device state information. Indexed by dev_number. * 2 bytes per device --- linux-2.6.11.6/include/linux/raid/md_k.h.orig Sat Mar 26 04:28:14 2005 +++ linux-2.6.11.6/include/linux/raid/md_k.h Sun Jun 12 00:11:44 2005 @@ -238,6 +238,9 @@ #define MD_RECOVERY_INTR 3 #define MD_RECOVERY_DONE 4 #define MD_RECOVERY_NEEDED 5 + /* begin bits added to support fast raid */ +#define MD_BITMAP_REPAIR 8 + /* end bits added to support fast raid */ unsigned long recovery; int in_sync; /* know to not need resync */ @@ -261,6 +264,9 @@ request_queue_t *queue; /* for plugging ... */ struct list_head all_mddevs; +/* added for bitmap */ + __u64 bitmap_events; /* last bitmap stamp */ +/* end of additions for bitmap */ };