Merge branch 'master'
[powerpc.git] / drivers / md / bitmap.c
index 2c84de2..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);
 }
@@ -270,19 +269,21 @@ static struct page *read_sb_page(mddev_t *mddev, long offset, unsigned long inde
 
        if (!page)
                return ERR_PTR(-ENOMEM);
-       do {
-               ITERATE_RDEV(mddev, rdev, tmp)
-                       if (rdev->in_sync && !rdev->faulty)
-                               goto found;
-               return ERR_PTR(-EIO);
 
-       found:
+       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);
 
-       } while (!sync_page_io(rdev->bdev, target, PAGE_SIZE, page, READ));
+               if (sync_page_io(rdev->bdev, target, PAGE_SIZE, page, READ)) {
+                       page->index = index;
+                       return page;
+               }
+       }
+       return ERR_PTR(-EIO);
 
-       page->index = index;
-       return page;
 }
 
 static int write_sb_page(mddev_t *mddev, long offset, struct page *page, int wait)
@@ -291,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),
@@ -299,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;
 }
 
@@ -480,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)";
@@ -522,8 +525,11 @@ 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;
@@ -624,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)
@@ -666,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);
 
@@ -761,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);
 
@@ -819,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;
 }
@@ -888,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 */
@@ -936,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)
@@ -1094,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);
@@ -1154,6 +1170,9 @@ static void bitmap_writeback_daemon(mddev_t *mddev)
                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 */
@@ -1183,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
@@ -1207,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,
@@ -1502,17 +1497,14 @@ void bitmap_flush(mddev_t *mddev)
 /*
  * 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);
 
@@ -1530,6 +1522,17 @@ 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 */
+
+       bitmap_free(bitmap);
+}
 
 /*
  * initialize the bitmap structure
@@ -1560,15 +1563,15 @@ int bitmap_create(mddev_t *mddev)
 
        spin_lock_init(&bitmap->lock);
        bitmap->mddev = mddev;
-       mddev->bitmap = bitmap;
 
        spin_lock_init(&bitmap->write_lock);
        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);
+       err = -ENOMEM;
        if (!bitmap->write_pool)
-               return -ENOMEM;
+               goto error;
 
        bitmap->file = file;
        bitmap->offset = mddev->bitmap_offset;
@@ -1576,7 +1579,7 @@ int bitmap_create(mddev_t *mddev)
        /* 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));
@@ -1600,8 +1603,9 @@ int bitmap_create(mddev_t *mddev)
 #else
        bitmap->bp = kmalloc(pages * sizeof(*bitmap->bp), GFP_KERNEL);
 #endif
+       err = -ENOMEM;
        if (!bitmap->bp)
-               return -ENOMEM;
+               goto error;
        memset(bitmap->bp, 0, pages * sizeof(*bitmap->bp));
 
        bitmap->flags |= BITMAP_ACTIVE;
@@ -1616,16 +1620,27 @@ int bitmap_create(mddev_t *mddev)
        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);
        return bitmap_update_sb(bitmap);
+
+ error:
+       bitmap_free(bitmap);
+       return err;
 }
 
 /* the bitmap API -- for raid personalities */