Merge branch 'master'
[powerpc.git] / drivers / md / bitmap.c
index 87145fa..5131530 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>
@@ -91,7 +90,7 @@ 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)
+static void *write_pool_alloc(gfp_t gfp_flags, void *data)
 {
        return kmalloc(sizeof(struct page_list), gfp_flags);
 }
@@ -272,7 +271,8 @@ static struct page *read_sb_page(mddev_t *mddev, long offset, unsigned long inde
                return ERR_PTR(-ENOMEM);
 
        ITERATE_RDEV(mddev, rdev, tmp) {
-               if (! rdev->in_sync || rdev->faulty)
+               if (! test_bit(In_sync, &rdev->flags)
+                   || test_bit(Faulty, &rdev->flags))
                        continue;
 
                target = (rdev->sb_offset << 1) + offset + index * (PAGE_SIZE/512);
@@ -292,7 +292,8 @@ static int write_sb_page(mddev_t *mddev, long offset, struct page *page, int wai
        struct list_head *tmp;
 
        ITERATE_RDEV(mddev, rdev, tmp)
-               if (rdev->in_sync && !rdev->faulty)
+               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),
@@ -300,7 +301,7 @@ static int write_sb_page(mddev_t *mddev, long offset, struct page *page, int wai
                                       page);
 
        if (wait)
-               wait_event(mddev->sb_wait, atomic_read(&mddev->pending_writes)==0);
+               md_super_wait(mddev);
        return 0;
 }
 
@@ -481,7 +482,8 @@ static int bitmap_read_sb(struct bitmap *bitmap)
        /* 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)";
@@ -526,6 +528,8 @@ success:
        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;
@@ -626,7 +630,7 @@ static void bitmap_file_unmap(struct bitmap *bitmap)
                page_cache_release(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)
@@ -668,7 +672,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);
 
@@ -763,7 +767,10 @@ static void bitmap_file_set_bit(struct bitmap *bitmap, sector_t block)
 
        /* 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);
 
@@ -821,8 +828,7 @@ int bitmap_unplug(struct bitmap *bitmap)
                                            wake_up_process(bitmap->writeback_daemon->tsk));
                        spin_unlock_irq(&bitmap->write_lock);
                } else
-                       wait_event(bitmap->mddev->sb_wait,
-                                  atomic_read(&bitmap->mddev->pending_writes)==0);
+                       md_super_wait(bitmap->mddev);
        }
        return 0;
 }
@@ -890,6 +896,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
        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 */
@@ -938,7 +945,11 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
 
                        bitmap->filemap[bitmap->file_pages++] = page;
                }
-               if (test_bit(bit, page_address(page))) {
+               if (bitmap->flags & BITMAP_HOSTENDIAN)
+                       b = test_bit(bit, page_address(page));
+               else
+                       b = ext2_test_bit(bit, page_address(page));
+               if (b) {
                        /* if the disk bit is set, set the memory bit */
                        bitmap_set_memory_bits(bitmap, i << CHUNK_BLOCK_SHIFT(bitmap),
                                               ((i+1) << (CHUNK_BLOCK_SHIFT(bitmap)) >= start)
@@ -1096,7 +1107,10 @@ int bitmap_daemon_work(struct bitmap *bitmap)
                                                  -1);
 
                                /* clear the bit */
-                               clear_bit(file_page_offset(j), page_address(page));
+                               if (bitmap->flags & BITMAP_HOSTENDIAN)
+                                       clear_bit(file_page_offset(j), page_address(page));
+                               else
+                                       ext2_clear_bit(file_page_offset(j), page_address(page));
                        }
                }
                spin_unlock_irqrestore(&bitmap->lock, flags);
@@ -1188,21 +1202,12 @@ static void bitmap_writeback_daemon(mddev_t *mddev)
        }
 }
 
-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);
-
 #ifdef INJECT_FATAL_FAULT_2
        daemon = NULL;
 #else
@@ -1212,47 +1217,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,
@@ -1637,10 +1627,15 @@ int bitmap_create(mddev_t *mddev)
 
        mddev->bitmap = bitmap;
 
-       /* kick off the bitmap daemons */
-       err = bitmap_start_daemons(bitmap);
-       if (err)
-               return err;
+       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);
        return bitmap_update_sb(bitmap);
 
  error: