intelfb: add vsync interrupt support
[safe/jmp/linux-2.6] / drivers / md / bitmap.c
index 275a2aa..f8ffaee 100644 (file)
@@ -21,7 +21,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/version.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/init.h>
@@ -90,16 +89,6 @@ int bitmap_active(struct bitmap *bitmap)
 }
 
 #define WRITE_POOL_SIZE 256
-/* mempool for queueing pending writes on the bitmap file */
-static void *write_pool_alloc(unsigned int gfp_flags, void *data)
-{
-       return kmalloc(sizeof(struct page_list), gfp_flags);
-}
-
-static void write_pool_free(void *ptr, void *data)
-{
-       kfree(ptr);
-}
 
 /*
  * just a placeholder - calls kmalloc for bitmap pages
@@ -108,7 +97,7 @@ static unsigned char *bitmap_alloc_page(struct bitmap *bitmap)
 {
        unsigned char *page;
 
-#if INJECT_FAULTS_1
+#ifdef INJECT_FAULTS_1
        page = NULL;
 #else
        page = kmalloc(PAGE_SIZE, GFP_NOIO);
@@ -116,7 +105,7 @@ static unsigned char *bitmap_alloc_page(struct bitmap *bitmap)
        if (!page)
                printk("%s: bitmap_alloc_page FAILED\n", bmname(bitmap));
        else
-               printk("%s: bitmap_alloc_page: allocated page at %p\n",
+               PRINTK("%s: bitmap_alloc_page: allocated page at %p\n",
                        bmname(bitmap), page);
        return page;
 }
@@ -201,7 +190,7 @@ out:
 /* if page is completely empty, put it back on the free list, or dealloc it */
 /* if page was hijacked, unmark the flag so it might get alloced next time */
 /* Note: lock should be held when calling this */
-static inline void bitmap_checkfree(struct bitmap *bitmap, unsigned long page)
+static void bitmap_checkfree(struct bitmap *bitmap, unsigned long page)
 {
        char *ptr;
 
@@ -258,33 +247,98 @@ char *file_path(struct file *file, char *buf, int count)
  * basic page I/O operations
  */
 
+/* IO operations when bitmap is stored near all superblocks */
+static struct page *read_sb_page(mddev_t *mddev, long offset, unsigned long index)
+{
+       /* choose a good rdev and read the page from there */
+
+       mdk_rdev_t *rdev;
+       struct list_head *tmp;
+       struct page *page = alloc_page(GFP_KERNEL);
+       sector_t target;
+
+       if (!page)
+               return ERR_PTR(-ENOMEM);
+
+       ITERATE_RDEV(mddev, rdev, tmp) {
+               if (! test_bit(In_sync, &rdev->flags)
+                   || test_bit(Faulty, &rdev->flags))
+                       continue;
+
+               target = (rdev->sb_offset << 1) + offset + index * (PAGE_SIZE/512);
+
+               if (sync_page_io(rdev->bdev, target, PAGE_SIZE, page, READ)) {
+                       page->index = index;
+                       return page;
+               }
+       }
+       return ERR_PTR(-EIO);
+
+}
+
+static int write_sb_page(mddev_t *mddev, long offset, struct page *page, int wait)
+{
+       mdk_rdev_t *rdev;
+       struct list_head *tmp;
+
+       ITERATE_RDEV(mddev, rdev, tmp)
+               if (test_bit(In_sync, &rdev->flags)
+                   && !test_bit(Faulty, &rdev->flags))
+                       md_super_write(mddev, rdev,
+                                      (rdev->sb_offset<<1) + offset
+                                      + page->index * (PAGE_SIZE/512),
+                                      PAGE_SIZE,
+                                      page);
+
+       if (wait)
+               md_super_wait(mddev);
+       return 0;
+}
+
 /*
- * write out a page
+ * write out a page to a file
  */
-static int write_page(struct page *page, int wait)
+static int write_page(struct bitmap *bitmap, struct page *page, int wait)
 {
        int ret = -ENOMEM;
 
-       lock_page(page);
+       if (bitmap->file == NULL)
+               return write_sb_page(bitmap->mddev, bitmap->offset, page, wait);
 
-       if (page->mapping == NULL)
-               goto unlock_out;
-       else if (i_size_read(page->mapping->host) < page->index << PAGE_SHIFT) {
-               ret = -ENOENT;
-               goto unlock_out;
+       flush_dcache_page(page); /* make sure visible to anyone reading the file */
+
+       if (wait)
+               lock_page(page);
+       else {
+               if (TestSetPageLocked(page))
+                       return -EAGAIN; /* already locked */
+               if (PageWriteback(page)) {
+                       unlock_page(page);
+                       return -EAGAIN;
+               }
        }
 
-       ret = page->mapping->a_ops->prepare_write(NULL, page, 0, PAGE_SIZE);
+       ret = page->mapping->a_ops->prepare_write(bitmap->file, page, 0, PAGE_SIZE);
        if (!ret)
-               ret = page->mapping->a_ops->commit_write(NULL, page, 0,
+               ret = page->mapping->a_ops->commit_write(bitmap->file, page, 0,
                        PAGE_SIZE);
        if (ret) {
-unlock_out:
                unlock_page(page);
                return ret;
        }
 
        set_page_dirty(page); /* force it to be written out */
+
+       if (!wait) {
+               /* add to list to be waited for by daemon */
+               struct page_list *item = mempool_alloc(bitmap->write_pool, GFP_NOIO);
+               item->page = page;
+               get_page(page);
+               spin_lock(&bitmap->write_lock);
+               list_add(&item->list, &bitmap->complete_pages);
+               spin_unlock(&bitmap->write_lock);
+               md_wakeup_thread(bitmap->writeback_daemon);
+       }
        return write_one_page(page, wait);
 }
 
@@ -295,10 +349,10 @@ static struct page *read_page(struct file *file, unsigned long index,
        struct inode *inode = file->f_mapping->host;
        struct page *page = NULL;
        loff_t isize = i_size_read(inode);
-       unsigned long end_index = isize >> PAGE_CACHE_SHIFT;
+       unsigned long end_index = isize >> PAGE_SHIFT;
 
-       PRINTK("read bitmap file (%dB @ %Lu)\n", (int)PAGE_CACHE_SIZE,
-                       (unsigned long long)index << PAGE_CACHE_SHIFT);
+       PRINTK("read bitmap file (%dB @ %Lu)\n", (int)PAGE_SIZE,
+                       (unsigned long long)index << PAGE_SHIFT);
 
        page = read_cache_page(inode->i_mapping, index,
                        (filler_t *)inode->i_mapping->a_ops->readpage, file);
@@ -306,7 +360,7 @@ static struct page *read_page(struct file *file, unsigned long index,
                goto out;
        wait_on_page_locked(page);
        if (!PageUptodate(page) || PageError(page)) {
-               page_cache_release(page);
+               put_page(page);
                page = ERR_PTR(-EIO);
                goto out;
        }
@@ -314,14 +368,14 @@ static struct page *read_page(struct file *file, unsigned long index,
        if (index > end_index) /* we have read beyond EOF */
                *bytes_read = 0;
        else if (index == end_index) /* possible short read */
-               *bytes_read = isize & ~PAGE_CACHE_MASK;
+               *bytes_read = isize & ~PAGE_MASK;
        else
-               *bytes_read = PAGE_CACHE_SIZE; /* got a full page */
+               *bytes_read = PAGE_SIZE; /* got a full page */
 out:
        if (IS_ERR(page))
                printk(KERN_ALERT "md: bitmap read error: (%dB @ %Lu): %ld\n",
-                       (int)PAGE_CACHE_SIZE,
-                       (unsigned long long)index << PAGE_CACHE_SHIFT,
+                       (int)PAGE_SIZE,
+                       (unsigned long long)index << PAGE_SHIFT,
                        PTR_ERR(page));
        return page;
 }
@@ -343,15 +397,13 @@ int bitmap_update_sb(struct bitmap *bitmap)
                spin_unlock_irqrestore(&bitmap->lock, flags);
                return 0;
        }
-       page_cache_get(bitmap->sb_page);
        spin_unlock_irqrestore(&bitmap->lock, flags);
-       sb = (bitmap_super_t *)kmap(bitmap->sb_page);
+       sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0);
        sb->events = cpu_to_le64(bitmap->mddev->events);
        if (!bitmap->mddev->degraded)
                sb->events_cleared = cpu_to_le64(bitmap->mddev->events);
-       kunmap(bitmap->sb_page);
-       write_page(bitmap->sb_page, 0);
-       return 0;
+       kunmap_atomic(sb, KM_USER0);
+       return write_page(bitmap, bitmap->sb_page, 1);
 }
 
 /* print out the bitmap file superblock */
@@ -361,24 +413,26 @@ void bitmap_print_sb(struct bitmap *bitmap)
 
        if (!bitmap || !bitmap->sb_page)
                return;
-       sb = (bitmap_super_t *)kmap(bitmap->sb_page);
+       sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0);
        printk(KERN_DEBUG "%s: bitmap file superblock:\n", bmname(bitmap));
-       printk(KERN_DEBUG "       magic: %08x\n", le32_to_cpu(sb->magic));
-       printk(KERN_DEBUG "     version: %d\n", le32_to_cpu(sb->version));
-       printk(KERN_DEBUG "        uuid: %08x.%08x.%08x.%08x\n",
+       printk(KERN_DEBUG "         magic: %08x\n", le32_to_cpu(sb->magic));
+       printk(KERN_DEBUG "       version: %d\n", le32_to_cpu(sb->version));
+       printk(KERN_DEBUG "          uuid: %08x.%08x.%08x.%08x\n",
                                        *(__u32 *)(sb->uuid+0),
                                        *(__u32 *)(sb->uuid+4),
                                        *(__u32 *)(sb->uuid+8),
                                        *(__u32 *)(sb->uuid+12));
-       printk(KERN_DEBUG "      events: %llu\n",
+       printk(KERN_DEBUG "        events: %llu\n",
                        (unsigned long long) le64_to_cpu(sb->events));
-       printk(KERN_DEBUG "events_clred: %llu\n",
+       printk(KERN_DEBUG "events cleared: %llu\n",
                        (unsigned long long) le64_to_cpu(sb->events_cleared));
-       printk(KERN_DEBUG "       state: %08x\n", le32_to_cpu(sb->state));
-       printk(KERN_DEBUG "   chunksize: %d B\n", le32_to_cpu(sb->chunksize));
-       printk(KERN_DEBUG "daemon sleep: %ds\n", le32_to_cpu(sb->daemon_sleep));
-       printk(KERN_DEBUG "   sync size: %llu KB\n", le64_to_cpu(sb->sync_size));
-       kunmap(bitmap->sb_page);
+       printk(KERN_DEBUG "         state: %08x\n", le32_to_cpu(sb->state));
+       printk(KERN_DEBUG "     chunksize: %d B\n", le32_to_cpu(sb->chunksize));
+       printk(KERN_DEBUG "  daemon sleep: %ds\n", le32_to_cpu(sb->daemon_sleep));
+       printk(KERN_DEBUG "     sync size: %llu KB\n",
+                       (unsigned long long)le64_to_cpu(sb->sync_size)/2);
+       printk(KERN_DEBUG "max write behind: %d\n", le32_to_cpu(sb->write_behind));
+       kunmap_atomic(sb, KM_USER0);
 }
 
 /* read the superblock from the bitmap file and initialize some bitmap fields */
@@ -386,20 +440,25 @@ static int bitmap_read_sb(struct bitmap *bitmap)
 {
        char *reason = NULL;
        bitmap_super_t *sb;
-       unsigned long chunksize, daemon_sleep;
+       unsigned long chunksize, daemon_sleep, write_behind;
        unsigned long bytes_read;
        unsigned long long events;
        int err = -EINVAL;
 
        /* page 0 is the superblock, read it... */
-       bitmap->sb_page = read_page(bitmap->file, 0, &bytes_read);
+       if (bitmap->file)
+               bitmap->sb_page = read_page(bitmap->file, 0, &bytes_read);
+       else {
+               bitmap->sb_page = read_sb_page(bitmap->mddev, bitmap->offset, 0);
+               bytes_read = PAGE_SIZE;
+       }
        if (IS_ERR(bitmap->sb_page)) {
                err = PTR_ERR(bitmap->sb_page);
                bitmap->sb_page = NULL;
                return err;
        }
 
-       sb = (bitmap_super_t *)kmap(bitmap->sb_page);
+       sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0);
 
        if (bytes_read < sizeof(*sb)) { /* short read */
                printk(KERN_INFO "%s: bitmap file superblock truncated\n",
@@ -410,18 +469,22 @@ static int bitmap_read_sb(struct bitmap *bitmap)
 
        chunksize = le32_to_cpu(sb->chunksize);
        daemon_sleep = le32_to_cpu(sb->daemon_sleep);
+       write_behind = le32_to_cpu(sb->write_behind);
 
        /* verify that the bitmap-specific fields are valid */
        if (sb->magic != cpu_to_le32(BITMAP_MAGIC))
                reason = "bad magic";
-       else if (sb->version != cpu_to_le32(BITMAP_MAJOR))
+       else if (le32_to_cpu(sb->version) < BITMAP_MAJOR_LO ||
+                le32_to_cpu(sb->version) > BITMAP_MAJOR_HI)
                reason = "unrecognized superblock version";
-       else if (chunksize < 512 || chunksize > (1024 * 1024 * 4))
-               reason = "bitmap chunksize out of range (512B - 4MB)";
+       else if (chunksize < PAGE_SIZE)
+               reason = "bitmap chunksize too small";
        else if ((1 << ffz(~chunksize)) != chunksize)
                reason = "bitmap chunksize not a power of 2";
-       else if (daemon_sleep < 1 || daemon_sleep > 15)
+       else if (daemon_sleep < 1 || daemon_sleep > MAX_SCHEDULE_TIMEOUT / HZ)
                reason = "daemon sleep period out of range";
+       else if (write_behind > COUNTER_MAX)
+               reason = "write-behind limit out of range (0 - 16383)";
        if (reason) {
                printk(KERN_INFO "%s: invalid bitmap file superblock: %s\n",
                        bmname(bitmap), reason);
@@ -454,11 +517,17 @@ success:
        /* assign fields using values from superblock */
        bitmap->chunksize = chunksize;
        bitmap->daemon_sleep = daemon_sleep;
+       bitmap->daemon_lastrun = jiffies;
+       bitmap->max_write_behind = write_behind;
        bitmap->flags |= sb->state;
+       if (le32_to_cpu(sb->version) == BITMAP_MAJOR_HOSTENDIAN)
+               bitmap->flags |= BITMAP_HOSTENDIAN;
        bitmap->events_cleared = le64_to_cpu(sb->events_cleared);
+       if (sb->state & BITMAP_STALE)
+               bitmap->events_cleared = bitmap->mddev->events;
        err = 0;
 out:
-       kunmap(bitmap->sb_page);
+       kunmap_atomic(sb, KM_USER0);
        if (err)
                bitmap_print_sb(bitmap);
        return err;
@@ -477,13 +546,13 @@ static void bitmap_mask_state(struct bitmap *bitmap, enum bitmap_state bits,
        unsigned long flags;
 
        spin_lock_irqsave(&bitmap->lock, flags);
-       if (!bitmap || !bitmap->sb_page) { /* can't set the state */
+       if (!bitmap->sb_page) { /* can't set the state */
                spin_unlock_irqrestore(&bitmap->lock, flags);
                return;
        }
-       page_cache_get(bitmap->sb_page);
+       get_page(bitmap->sb_page);
        spin_unlock_irqrestore(&bitmap->lock, flags);
-       sb = (bitmap_super_t *)kmap(bitmap->sb_page);
+       sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0);
        switch (op) {
                case MASK_SET: sb->state |= bits;
                                break;
@@ -491,8 +560,8 @@ static void bitmap_mask_state(struct bitmap *bitmap, enum bitmap_state bits,
                                break;
                default: BUG();
        }
-       kunmap(bitmap->sb_page);
-       page_cache_release(bitmap->sb_page);
+       kunmap_atomic(sb, KM_USER0);
+       put_page(bitmap->sb_page);
 }
 
 /*
@@ -545,21 +614,20 @@ static void bitmap_file_unmap(struct bitmap *bitmap)
 
        while (pages--)
                if (map[pages]->index != 0) /* 0 is sb_page, release it below */
-                       page_cache_release(map[pages]);
+                       put_page(map[pages]);
        kfree(map);
        kfree(attr);
 
-       if (sb_page)
-               page_cache_release(sb_page);
+       safe_put_page(sb_page);
 }
 
-static void bitmap_stop_daemons(struct bitmap *bitmap);
+static void bitmap_stop_daemon(struct bitmap *bitmap);
 
 /* dequeue the next item in a page list -- don't call from irq context */
-static struct page_list *dequeue_page(struct bitmap *bitmap,
-                                       struct list_head *head)
+static struct page_list *dequeue_page(struct bitmap *bitmap)
 {
        struct page_list *item = NULL;
+       struct list_head *head = &bitmap->complete_pages;
 
        spin_lock(&bitmap->write_lock);
        if (list_empty(head))
@@ -573,23 +641,15 @@ out:
 
 static void drain_write_queues(struct bitmap *bitmap)
 {
-       struct list_head *queues[] = {  &bitmap->complete_pages, NULL };
-       struct list_head *head;
        struct page_list *item;
-       int i;
 
-       for (i = 0; queues[i]; i++) {
-               head = queues[i];
-               while ((item = dequeue_page(bitmap, head))) {
-                       page_cache_release(item->page);
-                       mempool_free(item, bitmap->write_pool);
-               }
+       while ((item = dequeue_page(bitmap))) {
+               /* don't bother to wait */
+               put_page(item->page);
+               mempool_free(item, bitmap->write_pool);
        }
 
-       spin_lock(&bitmap->write_lock);
-       bitmap->writes_pending = 0; /* make sure waiters continue */
        wake_up(&bitmap->write_wait);
-       spin_unlock(&bitmap->write_lock);
 }
 
 static void bitmap_file_put(struct bitmap *bitmap)
@@ -603,7 +663,7 @@ static void bitmap_file_put(struct bitmap *bitmap)
        bitmap->file = NULL;
        spin_unlock_irqrestore(&bitmap->lock, flags);
 
-       bitmap_stop_daemons(bitmap);
+       bitmap_stop_daemon(bitmap);
 
        drain_write_queues(bitmap);
 
@@ -631,14 +691,16 @@ static void bitmap_file_kick(struct bitmap *bitmap)
        bitmap_mask_state(bitmap, BITMAP_STALE, MASK_SET);
        bitmap_update_sb(bitmap);
 
-       path = kmalloc(PAGE_SIZE, GFP_KERNEL);
-       if (path)
-               ptr = file_path(bitmap->file, path, PAGE_SIZE);
+       if (bitmap->file) {
+               path = kmalloc(PAGE_SIZE, GFP_KERNEL);
+               if (path)
+                       ptr = file_path(bitmap->file, path, PAGE_SIZE);
 
-       printk(KERN_ALERT "%s: kicking failed bitmap file %s from array!\n",
-               bmname(bitmap), ptr ? ptr : "");
+               printk(KERN_ALERT "%s: kicking failed bitmap file %s from array!\n",
+                      bmname(bitmap), ptr ? ptr : "");
 
-       kfree(path);
+               kfree(path);
+       }
 
        bitmap_file_put(bitmap);
 
@@ -682,7 +744,7 @@ static void bitmap_file_set_bit(struct bitmap *bitmap, sector_t block)
        void *kaddr;
        unsigned long chunk = block >> CHUNK_BLOCK_SHIFT(bitmap);
 
-       if (!bitmap->file || !bitmap->filemap) {
+       if (!bitmap->filemap) {
                return;
        }
 
@@ -692,11 +754,14 @@ static void bitmap_file_set_bit(struct bitmap *bitmap, sector_t block)
 
        /* make sure the page stays cached until it gets written out */
        if (! (get_page_attr(bitmap, page) & BITMAP_PAGE_DIRTY))
-               page_cache_get(page);
+               get_page(page);
 
        /* set the bit */
        kaddr = kmap_atomic(page, KM_USER0);
-       set_bit(bit, kaddr);
+       if (bitmap->flags & BITMAP_HOSTENDIAN)
+               set_bit(bit, kaddr);
+       else
+               ext2_set_bit(bit, kaddr);
        kunmap_atomic(kaddr, KM_USER0);
        PRINTK("set file bit %lu page %lu\n", bit, page->index);
 
@@ -713,6 +778,7 @@ int bitmap_unplug(struct bitmap *bitmap)
        unsigned long i, attr, flags;
        struct page *page;
        int wait = 0;
+       int err;
 
        if (!bitmap)
                return 0;
@@ -721,7 +787,7 @@ int bitmap_unplug(struct bitmap *bitmap)
         * flushed out to disk */
        for (i = 0; i < bitmap->file_pages; i++) {
                spin_lock_irqsave(&bitmap->lock, flags);
-               if (!bitmap->file || !bitmap->filemap) {
+               if (!bitmap->filemap) {
                        spin_unlock_irqrestore(&bitmap->lock, flags);
                        return 0;
                }
@@ -733,21 +799,32 @@ int bitmap_unplug(struct bitmap *bitmap)
                        wait = 1;
                spin_unlock_irqrestore(&bitmap->lock, flags);
 
-               if (attr & (BITMAP_PAGE_DIRTY | BITMAP_PAGE_NEEDWRITE))
-                       write_page(page, 0);
+               if (attr & (BITMAP_PAGE_DIRTY | BITMAP_PAGE_NEEDWRITE)) {
+                       err = write_page(bitmap, page, 0);
+                       if (err == -EAGAIN) {
+                               if (attr & BITMAP_PAGE_DIRTY)
+                                       err = write_page(bitmap, page, 1);
+                               else
+                                       err = 0;
+                       }
+                       if (err)
+                               return 1;
+               }
        }
        if (wait) { /* if any writes were performed, we need to wait on them */
-               spin_lock_irq(&bitmap->write_lock);
-               wait_event_lock_irq(bitmap->write_wait,
-                       bitmap->writes_pending == 0, bitmap->write_lock,
-                       wake_up_process(bitmap->writeback_daemon->tsk));
-               spin_unlock_irq(&bitmap->write_lock);
+               if (bitmap->file) {
+                       spin_lock_irq(&bitmap->write_lock);
+                       wait_event_lock_irq(bitmap->write_wait,
+                                           list_empty(&bitmap->complete_pages), bitmap->write_lock,
+                                           wake_up_process(bitmap->writeback_daemon->tsk));
+                       spin_unlock_irq(&bitmap->write_lock);
+               } else
+                       md_super_wait(bitmap->mddev);
        }
        return 0;
 }
 
-static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset,
-       unsigned long sectors, int in_sync);
+static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed);
 /* * bitmap_init_from_disk -- called at bitmap_create time to initialize
  * the in-memory bitmap from the on-disk bitmap -- also, sets up the
  * memory mapping of the bitmap file
@@ -755,8 +832,11 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset,
  *   if there's no bitmap file, or if the bitmap file had been
  *   previously kicked from the array, we mark all the bits as
  *   1's in order to cause a full resync.
+ *
+ * We ignore all bits for sectors that end earlier than 'start'.
+ * This is used when reading an out-of-date bitmap...
  */
-static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync)
+static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
 {
        unsigned long i, chunks, index, oldindex, bit;
        struct page *page = NULL, *oldpage = NULL;
@@ -765,13 +845,14 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync)
        unsigned long bytes, offset, dummy;
        int outofdate;
        int ret = -ENOSPC;
+       void *paddr;
 
        chunks = bitmap->chunks;
        file = bitmap->file;
 
-       BUG_ON(!file);
+       BUG_ON(!file && !bitmap->offset);
 
-#if INJECT_FAULTS_3
+#ifdef INJECT_FAULTS_3
        outofdate = 1;
 #else
        outofdate = bitmap->flags & BITMAP_STALE;
@@ -784,7 +865,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync)
 
        num_pages = (bytes + sizeof(bitmap_super_t) + PAGE_SIZE - 1) / PAGE_SIZE;
 
-       if (i_size_read(file->f_mapping->host) < bytes + sizeof(bitmap_super_t)) {
+       if (file && i_size_read(file->f_mapping->host) < bytes + sizeof(bitmap_super_t)) {
                printk(KERN_INFO "%s: bitmap file too short %lu < %lu\n",
                        bmname(bitmap),
                        (unsigned long) i_size_read(file->f_mapping->host),
@@ -798,21 +879,18 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync)
        if (!bitmap->filemap)
                goto out;
 
-       bitmap->filemap_attr = kmalloc(sizeof(long) * num_pages, GFP_KERNEL);
+       bitmap->filemap_attr = kzalloc(sizeof(long) * num_pages, GFP_KERNEL);
        if (!bitmap->filemap_attr)
                goto out;
 
-       memset(bitmap->filemap_attr, 0, sizeof(long) * num_pages);
-
        oldindex = ~0L;
 
        for (i = 0; i < chunks; i++) {
+               int b;
                index = file_page_index(i);
                bit = file_page_offset(i);
                if (index != oldindex) { /* this is a new page, read it in */
                        /* unmap the old page, we're done with it */
-                       if (oldpage != NULL)
-                               kunmap(oldpage);
                        if (index == 0) {
                                /*
                                 * if we're here then the superblock page
@@ -821,41 +899,53 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync)
                                 */
                                page = bitmap->sb_page;
                                offset = sizeof(bitmap_super_t);
-                       } else {
+                       } else if (file) {
                                page = read_page(file, index, &dummy);
-                               if (IS_ERR(page)) { /* read error */
-                                       ret = PTR_ERR(page);
-                                       goto out;
-                               }
                                offset = 0;
+                       } else {
+                               page = read_sb_page(bitmap->mddev, bitmap->offset, index);
+                               offset = 0;
+                       }
+                       if (IS_ERR(page)) { /* read error */
+                               ret = PTR_ERR(page);
+                               goto out;
                        }
+
                        oldindex = index;
                        oldpage = page;
-                       kmap(page);
 
                        if (outofdate) {
                                /*
                                 * if bitmap is out of date, dirty the
                                 * whole page and write it out
                                 */
-                               memset(page_address(page) + offset, 0xff,
-                                       PAGE_SIZE - offset);
-                               ret = write_page(page, 1);
+                               paddr = kmap_atomic(page, KM_USER0);
+                               memset(paddr + offset, 0xff,
+                                      PAGE_SIZE - offset);
+                               kunmap_atomic(paddr, KM_USER0);
+                               ret = write_page(bitmap, page, 1);
                                if (ret) {
-                                       kunmap(page);
                                        /* release, page not in filemap yet */
-                                       page_cache_release(page);
+                                       put_page(page);
                                        goto out;
                                }
                        }
 
                        bitmap->filemap[bitmap->file_pages++] = page;
                }
-               if (test_bit(bit, page_address(page))) {
+               paddr = kmap_atomic(page, KM_USER0);
+               if (bitmap->flags & BITMAP_HOSTENDIAN)
+                       b = test_bit(bit, paddr);
+               else
+                       b = ext2_test_bit(bit, paddr);
+               kunmap_atomic(paddr, KM_USER0);
+               if (b) {
                        /* if the disk bit is set, set the memory bit */
-                       bitmap_set_memory_bits(bitmap,
-                                       i << CHUNK_BLOCK_SHIFT(bitmap), 1, in_sync);
+                       bitmap_set_memory_bits(bitmap, i << CHUNK_BLOCK_SHIFT(bitmap),
+                                              ((i+1) << (CHUNK_BLOCK_SHIFT(bitmap)) >= start)
+                               );
                        bit_cnt++;
+                       set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
                }
        }
 
@@ -863,9 +953,6 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync)
        ret = 0;
        bitmap_mask_state(bitmap, BITMAP_STALE, MASK_UNSET);
 
-       if (page) /* unmap the last page */
-               kunmap(page);
-
        if (bit_cnt) { /* Kick recovery if any bits were set */
                set_bit(MD_RECOVERY_NEEDED, &bitmap->mddev->recovery);
                md_wakeup_thread(bitmap->mddev->thread);
@@ -879,6 +966,19 @@ out:
        return ret;
 }
 
+void bitmap_write_all(struct bitmap *bitmap)
+{
+       /* We don't actually write all bitmap blocks here,
+        * just flag them as needing to be written
+        */
+
+       unsigned long chunks = bitmap->chunks;
+       unsigned long bytes = (chunks+7)/8 + sizeof(bitmap_super_t);
+       unsigned long num_pages = (bytes + PAGE_SIZE-1) / PAGE_SIZE;
+       while (num_pages--)
+               bitmap->filemap_attr[num_pages] |= BITMAP_PAGE_NEEDWRITE;
+}
+
 
 static void bitmap_count_page(struct bitmap *bitmap, sector_t offset, int inc)
 {
@@ -902,12 +1002,13 @@ static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap,
 
 int bitmap_daemon_work(struct bitmap *bitmap)
 {
-       unsigned long bit, j;
+       unsigned long j;
        unsigned long flags;
        struct page *page = NULL, *lastpage = NULL;
        int err = 0;
        int blocks;
        int attr;
+       void *paddr;
 
        if (bitmap == NULL)
                return 0;
@@ -918,50 +1019,58 @@ int bitmap_daemon_work(struct bitmap *bitmap)
        for (j = 0; j < bitmap->chunks; j++) {
                bitmap_counter_t *bmc;
                spin_lock_irqsave(&bitmap->lock, flags);
-               if (!bitmap->file || !bitmap->filemap) {
+               if (!bitmap->filemap) {
                        /* error or shutdown */
                        spin_unlock_irqrestore(&bitmap->lock, flags);
                        break;
                }
 
                page = filemap_get_page(bitmap, j);
-               /* skip this page unless it's marked as needing cleaning */
-               if (!((attr=get_page_attr(bitmap, page)) & BITMAP_PAGE_CLEAN)) {
-                       if (attr & BITMAP_PAGE_NEEDWRITE) {
-                               page_cache_get(page);
-                               clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE);
-                       }
-                       spin_unlock_irqrestore(&bitmap->lock, flags);
-                       if (attr & BITMAP_PAGE_NEEDWRITE) {
-                               if (write_page(page, 0))
-                                       bitmap_file_kick(bitmap);
-                               page_cache_release(page);
-                       }
-                       continue;
-               }
-
-               bit = file_page_offset(j);
 
                if (page != lastpage) {
+                       /* skip this page unless it's marked as needing cleaning */
+                       if (!((attr=get_page_attr(bitmap, page)) & BITMAP_PAGE_CLEAN)) {
+                               if (attr & BITMAP_PAGE_NEEDWRITE) {
+                                       get_page(page);
+                                       clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE);
+                               }
+                               spin_unlock_irqrestore(&bitmap->lock, flags);
+                               if (attr & BITMAP_PAGE_NEEDWRITE) {
+                                       switch (write_page(bitmap, page, 0)) {
+                                       case -EAGAIN:
+                                               set_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE);
+                                               break;
+                                       case 0:
+                                               break;
+                                       default:
+                                               bitmap_file_kick(bitmap);
+                                       }
+                                       put_page(page);
+                               }
+                               continue;
+                       }
+
                        /* grab the new page, sync and release the old */
-                       page_cache_get(page);
+                       get_page(page);
                        if (lastpage != NULL) {
                                if (get_page_attr(bitmap, lastpage) & BITMAP_PAGE_NEEDWRITE) {
                                        clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
                                        spin_unlock_irqrestore(&bitmap->lock, flags);
-                                       write_page(lastpage, 0);
+                                       err = write_page(bitmap, lastpage, 0);
+                                       if (err == -EAGAIN) {
+                                               err = 0;
+                                               set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+                                       }
                                } else {
                                        set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
                                        spin_unlock_irqrestore(&bitmap->lock, flags);
                                }
-                               kunmap(lastpage);
-                               page_cache_release(lastpage);
+                               put_page(lastpage);
                                if (err)
                                        bitmap_file_kick(bitmap);
                        } else
                                spin_unlock_irqrestore(&bitmap->lock, flags);
                        lastpage = page;
-                       kmap(page);
 /*
                        printk("bitmap clean at page %lu\n", j);
 */
@@ -984,7 +1093,12 @@ int bitmap_daemon_work(struct bitmap *bitmap)
                                                  -1);
 
                                /* clear the bit */
-                               clear_bit(bit, page_address(page));
+                               paddr = kmap_atomic(page, KM_USER0);
+                               if (bitmap->flags & BITMAP_HOSTENDIAN)
+                                       clear_bit(file_page_offset(j), paddr);
+                               else
+                                       ext2_clear_bit(file_page_offset(j), paddr);
+                               kunmap_atomic(paddr, KM_USER0);
                        }
                }
                spin_unlock_irqrestore(&bitmap->lock, flags);
@@ -992,18 +1106,21 @@ int bitmap_daemon_work(struct bitmap *bitmap)
 
        /* now sync the final page */
        if (lastpage != NULL) {
-               kunmap(lastpage);
                spin_lock_irqsave(&bitmap->lock, flags);
                if (get_page_attr(bitmap, lastpage) &BITMAP_PAGE_NEEDWRITE) {
                        clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
                        spin_unlock_irqrestore(&bitmap->lock, flags);
-                       write_page(lastpage, 0);
+                       err = write_page(bitmap, lastpage, 0);
+                       if (err == -EAGAIN) {
+                               set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+                               err = 0;
+                       }
                } else {
                        set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
                        spin_unlock_irqrestore(&bitmap->lock, flags);
                }
 
-               page_cache_release(lastpage);
+               put_page(lastpage);
        }
 
        return err;
@@ -1033,63 +1150,52 @@ static void bitmap_writeback_daemon(mddev_t *mddev)
        struct page_list *item;
        int err = 0;
 
-       while (1) {
-               PRINTK("%s: bitmap writeback daemon waiting...\n", bmname(bitmap));
-               down_interruptible(&bitmap->write_done);
-               if (signal_pending(current)) {
-                       printk(KERN_INFO
-                           "%s: bitmap writeback daemon got signal, exiting...\n",
-                           bmname(bitmap));
-                       break;
-               }
+       if (signal_pending(current)) {
+               printk(KERN_INFO
+                      "%s: bitmap writeback daemon got signal, exiting...\n",
+                      bmname(bitmap));
+               err = -EINTR;
+               goto out;
+       }
+       if (bitmap == NULL)
+               /* about to be stopped. */
+               return;
 
-               PRINTK("%s: bitmap writeback daemon woke up...\n", bmname(bitmap));
-               /* wait on bitmap page writebacks */
-               while ((item = dequeue_page(bitmap, &bitmap->complete_pages))) {
-                       page = item->page;
-                       mempool_free(item, bitmap->write_pool);
-                       PRINTK("wait on page writeback: %p %lu\n", page, bitmap->writes_pending);
-                       wait_on_page_writeback(page);
-                       PRINTK("finished page writeback: %p %lu\n", page, bitmap->writes_pending);
-                       spin_lock(&bitmap->write_lock);
-                       if (!--bitmap->writes_pending)
-                               wake_up(&bitmap->write_wait);
-                       spin_unlock(&bitmap->write_lock);
-                       err = PageError(page);
-                       page_cache_release(page);
-                       if (err) {
-                               printk(KERN_WARNING "%s: bitmap file writeback "
-                                       "failed (page %lu): %d\n",
-                                       bmname(bitmap), page->index, err);
-                               bitmap_file_kick(bitmap);
-                               goto out;
-                       }
+       PRINTK("%s: bitmap writeback daemon woke up...\n", bmname(bitmap));
+       /* wait on bitmap page writebacks */
+       while ((item = dequeue_page(bitmap))) {
+               page = item->page;
+               mempool_free(item, bitmap->write_pool);
+               PRINTK("wait on page writeback: %p\n", page);
+               wait_on_page_writeback(page);
+               PRINTK("finished page writeback: %p\n", page);
+
+               err = PageError(page);
+               put_page(page);
+               if (err) {
+                       printk(KERN_WARNING "%s: bitmap file writeback "
+                              "failed (page %lu): %d\n",
+                              bmname(bitmap), page->index, err);
+                       bitmap_file_kick(bitmap);
+                       goto out;
                }
        }
-out:
+ out:
+       wake_up(&bitmap->write_wait);
        if (err) {
                printk(KERN_INFO "%s: bitmap writeback daemon exiting (%d)\n",
-                       bmname(bitmap), err);
+                      bmname(bitmap), err);
                daemon_exit(bitmap, &bitmap->writeback_daemon);
        }
-       return;
 }
 
-static int bitmap_start_daemon(struct bitmap *bitmap, mdk_thread_t **ptr,
+static mdk_thread_t *bitmap_start_daemon(struct bitmap *bitmap,
                                void (*func)(mddev_t *), char *name)
 {
        mdk_thread_t *daemon;
-       unsigned long flags;
        char namebuf[32];
 
-       spin_lock_irqsave(&bitmap->lock, flags);
-       *ptr = NULL;
-       if (!bitmap->file) /* no need for daemon if there's no backing file */
-               goto out_unlock;
-
-       spin_unlock_irqrestore(&bitmap->lock, flags);
-
-#if INJECT_FATAL_FAULT_2
+#ifdef INJECT_FATAL_FAULT_2
        daemon = NULL;
 #else
        sprintf(namebuf, "%%s_%s", name);
@@ -1098,47 +1204,32 @@ static int bitmap_start_daemon(struct bitmap *bitmap, mdk_thread_t **ptr,
        if (!daemon) {
                printk(KERN_ERR "%s: failed to start bitmap daemon\n",
                        bmname(bitmap));
-               return -ECHILD;
+               return ERR_PTR(-ECHILD);
        }
 
-       spin_lock_irqsave(&bitmap->lock, flags);
-       *ptr = daemon;
-
        md_wakeup_thread(daemon); /* start it running */
 
        PRINTK("%s: %s daemon (pid %d) started...\n",
                bmname(bitmap), name, daemon->tsk->pid);
-out_unlock:
-       spin_unlock_irqrestore(&bitmap->lock, flags);
-       return 0;
-}
 
-static int bitmap_start_daemons(struct bitmap *bitmap)
-{
-       int err = bitmap_start_daemon(bitmap, &bitmap->writeback_daemon,
-                                       bitmap_writeback_daemon, "bitmap_wb");
-       return err;
+       return daemon;
 }
 
-static void bitmap_stop_daemon(struct bitmap *bitmap, mdk_thread_t **ptr)
+static void bitmap_stop_daemon(struct bitmap *bitmap)
 {
-       mdk_thread_t *daemon;
-       unsigned long flags;
-
-       spin_lock_irqsave(&bitmap->lock, flags);
-       daemon = *ptr;
-       *ptr = NULL;
-       spin_unlock_irqrestore(&bitmap->lock, flags);
-       if (daemon)
-               md_unregister_thread(daemon); /* destroy the thread */
-}
+       /* the daemon can't stop itself... it'll just exit instead... */
+       if (bitmap->writeback_daemon && ! IS_ERR(bitmap->writeback_daemon) &&
+           current->pid != bitmap->writeback_daemon->tsk->pid) {
+               mdk_thread_t *daemon;
+               unsigned long flags;
 
-static void bitmap_stop_daemons(struct bitmap *bitmap)
-{
-       /* the daemons can't stop themselves... they'll just exit instead... */
-       if (bitmap->writeback_daemon &&
-           current->pid != bitmap->writeback_daemon->tsk->pid)
-               bitmap_stop_daemon(bitmap, &bitmap->writeback_daemon);
+               spin_lock_irqsave(&bitmap->lock, flags);
+               daemon = bitmap->writeback_daemon;
+               bitmap->writeback_daemon = NULL;
+               spin_unlock_irqrestore(&bitmap->lock, flags);
+               if (daemon && ! IS_ERR(daemon))
+                       md_unregister_thread(daemon); /* destroy the thread */
+       }
 }
 
 static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap,
@@ -1178,9 +1269,16 @@ static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap,
        }
 }
 
-int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors)
+int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors, int behind)
 {
        if (!bitmap) return 0;
+
+       if (behind) {
+               atomic_inc(&bitmap->behind_writes);
+               PRINTK(KERN_DEBUG "inc write-behind count %d/%d\n",
+                 atomic_read(&bitmap->behind_writes), bitmap->max_write_behind);
+       }
+
        while (sectors) {
                int blocks;
                bitmap_counter_t *bmc;
@@ -1201,7 +1299,7 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect
                case 1:
                        *bmc = 2;
                }
-               if ((*bmc & COUNTER_MAX) == COUNTER_MAX) BUG();
+               BUG_ON((*bmc & COUNTER_MAX) == COUNTER_MAX);
                (*bmc)++;
 
                spin_unlock_irq(&bitmap->lock);
@@ -1215,9 +1313,15 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect
 }
 
 void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors,
-                    int success)
+                    int success, int behind)
 {
        if (!bitmap) return;
+       if (behind) {
+               atomic_dec(&bitmap->behind_writes);
+               PRINTK(KERN_DEBUG "dec write-behind count %d/%d\n",
+                 atomic_read(&bitmap->behind_writes), bitmap->max_write_behind);
+       }
+
        while (sectors) {
                int blocks;
                unsigned long flags;
@@ -1247,7 +1351,8 @@ void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long secto
        }
 }
 
-int bitmap_start_sync(struct bitmap *bitmap, sector_t offset, int *blocks)
+int bitmap_start_sync(struct bitmap *bitmap, sector_t offset, int *blocks,
+                       int degraded)
 {
        bitmap_counter_t *bmc;
        int rv;
@@ -1264,8 +1369,10 @@ int bitmap_start_sync(struct bitmap *bitmap, sector_t offset, int *blocks)
                        rv = 1;
                else if (NEEDED(*bmc)) {
                        rv = 1;
-                       *bmc |= RESYNC_MASK;
-                       *bmc &= ~NEEDED_MASK;
+                       if (!degraded) { /* don't set/clear bits if degraded */
+                               *bmc |= RESYNC_MASK;
+                               *bmc &= ~NEEDED_MASK;
+                       }
                }
        }
        spin_unlock_irq(&bitmap->lock);
@@ -1325,75 +1432,66 @@ void bitmap_close_sync(struct bitmap *bitmap)
        }
 }
 
-static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset,
-                                  unsigned long sectors, int in_sync)
+static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed)
 {
        /* For each chunk covered by any of these sectors, set the
-        * counter to 1 and set resync_needed unless in_sync.  They should all
+        * counter to 1 and set resync_needed.  They should all
         * be 0 at this point
         */
-       while (sectors) {
-               int secs;
-               bitmap_counter_t *bmc;
-               spin_lock_irq(&bitmap->lock);
-               bmc = bitmap_get_counter(bitmap, offset, &secs, 1);
-               if (!bmc) {
-                       spin_unlock_irq(&bitmap->lock);
-                       return;
-               }
-               if (! *bmc) {
-                       struct page *page;
-                       *bmc = 1 | (in_sync? 0 : NEEDED_MASK);
-                       bitmap_count_page(bitmap, offset, 1);
-                       page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap));
-                       set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
-               }
+
+       int secs;
+       bitmap_counter_t *bmc;
+       spin_lock_irq(&bitmap->lock);
+       bmc = bitmap_get_counter(bitmap, offset, &secs, 1);
+       if (!bmc) {
                spin_unlock_irq(&bitmap->lock);
-               if (sectors > secs)
-                       sectors -= secs;
-               else
-                       sectors = 0;
+               return;
+       }
+       if (! *bmc) {
+               struct page *page;
+               *bmc = 1 | (needed?NEEDED_MASK:0);
+               bitmap_count_page(bitmap, offset, 1);
+               page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap));
+               set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
        }
+       spin_unlock_irq(&bitmap->lock);
+
 }
 
-/* dirty the entire bitmap */
-int bitmap_setallbits(struct bitmap *bitmap)
+/*
+ * flush out any pending updates
+ */
+void bitmap_flush(mddev_t *mddev)
 {
-       unsigned long flags;
-       unsigned long j;
-
-       /* dirty the in-memory bitmap */
-       bitmap_set_memory_bits(bitmap, 0, bitmap->chunks << CHUNK_BLOCK_SHIFT(bitmap), 1);
-
-       /* dirty the bitmap file */
-       for (j = 0; j < bitmap->file_pages; j++) {
-               struct page *page = bitmap->filemap[j];
+       struct bitmap *bitmap = mddev->bitmap;
+       int sleep;
 
-               spin_lock_irqsave(&bitmap->lock, flags);
-               page_cache_get(page);
-               spin_unlock_irqrestore(&bitmap->lock, flags);
-               memset(kmap(page), 0xff, PAGE_SIZE);
-               kunmap(page);
-               write_page(page, 0);
-       }
+       if (!bitmap) /* there was no bitmap */
+               return;
 
-       return 0;
+       /* run the daemon_work three time to ensure everything is flushed
+        * that can be
+        */
+       sleep = bitmap->daemon_sleep;
+       bitmap->daemon_sleep = 0;
+       bitmap_daemon_work(bitmap);
+       bitmap_daemon_work(bitmap);
+       bitmap_daemon_work(bitmap);
+       bitmap->daemon_sleep = sleep;
+       bitmap_update_sb(bitmap);
 }
 
 /*
  * free memory that was allocated
  */
-void bitmap_destroy(mddev_t *mddev)
+static void bitmap_free(struct bitmap *bitmap)
 {
        unsigned long k, pages;
        struct bitmap_page *bp;
-       struct bitmap *bitmap = mddev->bitmap;
 
        if (!bitmap) /* there was no bitmap */
                return;
 
-       mddev->bitmap = NULL; /* disconnect from the md device */
-
        /* release the bitmap file and kill the daemon */
        bitmap_file_put(bitmap);
 
@@ -1411,6 +1509,19 @@ void bitmap_destroy(mddev_t *mddev)
        kfree(bp);
        kfree(bitmap);
 }
+void bitmap_destroy(mddev_t *mddev)
+{
+       struct bitmap *bitmap = mddev->bitmap;
+
+       if (!bitmap) /* there was no bitmap */
+               return;
+
+       mddev->bitmap = NULL; /* disconnect from the md device */
+       if (mddev->thread)
+               mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
+
+       bitmap_free(bitmap);
+}
 
 /*
  * initialize the bitmap structure
@@ -1424,37 +1535,38 @@ int bitmap_create(mddev_t *mddev)
        unsigned long pages;
        struct file *file = mddev->bitmap_file;
        int err;
+       sector_t start;
 
        BUG_ON(sizeof(bitmap_super_t) != 256);
 
-       if (!file) /* bitmap disabled, nothing to do */
+       if (!file && !mddev->bitmap_offset) /* bitmap disabled, nothing to do */
                return 0;
 
-       bitmap = kmalloc(sizeof(*bitmap), GFP_KERNEL);
+       BUG_ON(file && mddev->bitmap_offset);
+
+       bitmap = kzalloc(sizeof(*bitmap), GFP_KERNEL);
        if (!bitmap)
                return -ENOMEM;
 
-       memset(bitmap, 0, sizeof(*bitmap));
-
        spin_lock_init(&bitmap->lock);
        bitmap->mddev = mddev;
-       mddev->bitmap = bitmap;
 
        spin_lock_init(&bitmap->write_lock);
-       init_MUTEX_LOCKED(&bitmap->write_done);
        INIT_LIST_HEAD(&bitmap->complete_pages);
        init_waitqueue_head(&bitmap->write_wait);
-       bitmap->write_pool = mempool_create(WRITE_POOL_SIZE, write_pool_alloc,
-                               write_pool_free, NULL);
+       bitmap->write_pool = mempool_create_kmalloc_pool(WRITE_POOL_SIZE,
+                                               sizeof(struct page_list));
+       err = -ENOMEM;
        if (!bitmap->write_pool)
-               return -ENOMEM;
+               goto error;
 
        bitmap->file = file;
-       get_file(file);
+       bitmap->offset = mddev->bitmap_offset;
+       if (file) get_file(file);
        /* read superblock from bitmap file (this sets bitmap->chunksize) */
        err = bitmap_read_sb(bitmap);
        if (err)
-               return err;
+               goto error;
 
        bitmap->chunkshift = find_first_bit(&bitmap->chunksize,
                                        sizeof(bitmap->chunksize));
@@ -1473,31 +1585,50 @@ int bitmap_create(mddev_t *mddev)
 
        bitmap->syncchunk = ~0UL;
 
-#if INJECT_FATAL_FAULT_1
+#ifdef INJECT_FATAL_FAULT_1
        bitmap->bp = NULL;
 #else
-       bitmap->bp = kmalloc(pages * sizeof(*bitmap->bp), GFP_KERNEL);
+       bitmap->bp = kzalloc(pages * sizeof(*bitmap->bp), GFP_KERNEL);
 #endif
+       err = -ENOMEM;
        if (!bitmap->bp)
-               return -ENOMEM;
-       memset(bitmap->bp, 0, pages * sizeof(*bitmap->bp));
+               goto error;
 
        bitmap->flags |= BITMAP_ACTIVE;
 
        /* now that we have some pages available, initialize the in-memory
         * bitmap from the on-disk bitmap */
-       err = bitmap_init_from_disk(bitmap, mddev->recovery_cp == MaxSector);
+       start = 0;
+       if (mddev->degraded == 0
+           || bitmap->events_cleared == mddev->events)
+               /* no need to keep dirty bits to optimise a re-add of a missing device */
+               start = mddev->recovery_cp;
+       err = bitmap_init_from_disk(bitmap, start);
+
        if (err)
-               return err;
+               goto error;
 
        printk(KERN_INFO "created bitmap (%lu pages) for device %s\n",
                pages, bmname(bitmap));
 
-       /* kick off the bitmap daemons */
-       err = bitmap_start_daemons(bitmap);
-       if (err)
-               return err;
+       mddev->bitmap = bitmap;
+
+       if (file)
+               /* kick off the bitmap writeback daemon */
+               bitmap->writeback_daemon =
+                       bitmap_start_daemon(bitmap,
+                                           bitmap_writeback_daemon,
+                                           "bitmap_wb");
+
+       if (IS_ERR(bitmap->writeback_daemon))
+               return PTR_ERR(bitmap->writeback_daemon);
+       mddev->thread->timeout = bitmap->daemon_sleep * HZ;
+
        return bitmap_update_sb(bitmap);
+
+ error:
+       bitmap_free(bitmap);
+       return err;
 }
 
 /* the bitmap API -- for raid personalities */