]> err.no Git - linux-2.6/blobdiff - drivers/md/bitmap.c
[PATCH] Clean up struct flock64 definitions
[linux-2.6] / drivers / md / bitmap.c
index 030d6861051ad3ce2a861a23859563692f8742aa..41df4cda66e2f27b668a98988aaf80121fb16236 100644 (file)
@@ -108,7 +108,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);
@@ -313,7 +313,16 @@ static int write_page(struct bitmap *bitmap, struct page *page, int wait)
        if (bitmap->file == NULL)
                return write_sb_page(bitmap->mddev, bitmap->offset, page, wait);
 
-       lock_page(page);
+       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);
        if (!ret)
@@ -400,7 +409,7 @@ int bitmap_update_sb(struct bitmap *bitmap)
        if (!bitmap->mddev->degraded)
                sb->events_cleared = cpu_to_le64(bitmap->mddev->events);
        kunmap(bitmap->sb_page);
-       return write_page(bitmap, bitmap->sb_page, 0);
+       return write_page(bitmap, bitmap->sb_page, 1);
 }
 
 /* print out the bitmap file superblock */
@@ -762,6 +771,7 @@ int bitmap_unplug(struct bitmap *bitmap)
        unsigned long i, attr, flags;
        struct page *page;
        int wait = 0;
+       int err;
 
        if (!bitmap)
                return 0;
@@ -782,9 +792,17 @@ int bitmap_unplug(struct bitmap *bitmap)
                        wait = 1;
                spin_unlock_irqrestore(&bitmap->lock, flags);
 
-               if (attr & (BITMAP_PAGE_DIRTY | BITMAP_PAGE_NEEDWRITE))
-                       if (write_page(bitmap, 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 */
                if (bitmap->file) {
@@ -800,8 +818,7 @@ int bitmap_unplug(struct bitmap *bitmap)
        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);
 /* * 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
@@ -810,7 +827,7 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset,
  *   previously kicked from the array, we mark all the bits as
  *   1's in order to cause a full resync.
  */
-static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync)
+static int bitmap_init_from_disk(struct bitmap *bitmap)
 {
        unsigned long i, chunks, index, oldindex, bit;
        struct page *page = NULL, *oldpage = NULL;
@@ -825,7 +842,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync)
 
        BUG_ON(!file && !bitmap->offset);
 
-#if INJECT_FAULTS_3
+#ifdef INJECT_FAULTS_3
        outofdate = 1;
 #else
        outofdate = bitmap->flags & BITMAP_STALE;
@@ -911,8 +928,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync)
                }
                if (test_bit(bit, page_address(page))) {
                        /* 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));
                        bit_cnt++;
                }
        }
@@ -1006,8 +1022,15 @@ int bitmap_daemon_work(struct bitmap *bitmap)
                                }
                                spin_unlock_irqrestore(&bitmap->lock, flags);
                                if (attr & BITMAP_PAGE_NEEDWRITE) {
-                                       if (write_page(bitmap, page, 0))
+                                       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);
+                                       }
                                        page_cache_release(page);
                                }
                                continue;
@@ -1020,6 +1043,10 @@ int bitmap_daemon_work(struct bitmap *bitmap)
                                        clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
                                        spin_unlock_irqrestore(&bitmap->lock, flags);
                                        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);
@@ -1068,6 +1095,10 @@ int bitmap_daemon_work(struct bitmap *bitmap)
                        clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
                        spin_unlock_irqrestore(&bitmap->lock, flags);
                        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);
@@ -1154,7 +1185,7 @@ static int bitmap_start_daemon(struct bitmap *bitmap, mdk_thread_t **ptr,
 
        spin_unlock_irqrestore(&bitmap->lock, flags);
 
-#if INJECT_FATAL_FAULT_2
+#ifdef INJECT_FATAL_FAULT_2
        daemon = NULL;
 #else
        sprintf(namebuf, "%%s_%s", name);
@@ -1312,7 +1343,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;
@@ -1329,8 +1361,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);
@@ -1390,60 +1424,53 @@ 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)
 {
        /* 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_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);
+       }
+       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);
-               if (write_page(bitmap, page, 0))
-                       return 1;
-       }
+       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);
 }
 
 /*
@@ -1541,7 +1568,7 @@ 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);
@@ -1554,7 +1581,8 @@ int bitmap_create(mddev_t *mddev)
 
        /* 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);
+       err = bitmap_init_from_disk(bitmap);
+
        if (err)
                return err;