md/bitmap: separate bitmap file allocation to its own function.
authorNeilBrown <neilb@suse.de>
Tue, 22 May 2012 03:55:12 +0000 (13:55 +1000)
committerNeilBrown <neilb@suse.de>
Tue, 22 May 2012 03:55:12 +0000 (13:55 +1000)
This will allow allocation before swapping in a new bitmap.

Signed-off-by: NeilBrown <neilb@suse.de>
drivers/md/bitmap.c

index 7a3be0d..4ac60ed 100644 (file)
@@ -716,6 +716,58 @@ static inline struct page *filemap_get_page(struct bitmap_storage *store,
                              - file_page_index(store, 0)];
 }
 
+static int bitmap_storage_alloc(struct bitmap_storage *store,
+                               unsigned long chunks, int with_super)
+{
+       int pnum;
+       unsigned long num_pages;
+       unsigned long bytes;
+
+       bytes = DIV_ROUND_UP(chunks, 8);
+       if (with_super)
+               bytes += sizeof(bitmap_super_t);
+
+       num_pages = DIV_ROUND_UP(bytes, PAGE_SIZE);
+
+       store->filemap = kmalloc(sizeof(struct page *)
+                                * num_pages, GFP_KERNEL);
+       if (!store->filemap)
+               return -ENOMEM;
+
+       if (with_super && !store->sb_page) {
+               store->sb_page = alloc_page(GFP_KERNEL);
+               if (store->sb_page == NULL)
+                       return -ENOMEM;
+               store->sb_page->index = 0;
+       }
+       pnum = 0;
+       if (store->sb_page) {
+               store->filemap[0] = store->sb_page;
+               pnum = 1;
+       }
+       for ( ; pnum < num_pages; pnum++) {
+               store->filemap[pnum] = alloc_page(GFP_KERNEL);
+               if (!store->filemap[pnum]) {
+                       store->file_pages = pnum;
+                       return -ENOMEM;
+               }
+               store->filemap[pnum]->index = pnum;
+       }
+       store->file_pages = pnum;
+
+       /* We need 4 bits per page, rounded up to a multiple
+        * of sizeof(unsigned long) */
+       store->filemap_attr = kzalloc(
+               roundup(DIV_ROUND_UP(num_pages*4, 8), sizeof(unsigned long)),
+               GFP_KERNEL);
+       if (!store->filemap_attr)
+               return -ENOMEM;
+
+       store->bytes = bytes;
+
+       return 0;
+}
+
 static void bitmap_file_unmap(struct bitmap *bitmap)
 {
        struct page **map, *sb_page;
@@ -940,11 +992,10 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int n
 static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
 {
        unsigned long i, chunks, index, oldindex, bit;
-       int pnum;
        struct page *page = NULL;
-       unsigned long num_pages, bit_cnt = 0;
+       unsigned long bit_cnt = 0;
        struct file *file;
-       unsigned long bytes, offset;
+       unsigned long offset;
        int outofdate;
        int ret = -ENOSPC;
        void *paddr;
@@ -973,53 +1024,23 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
                printk(KERN_INFO "%s: bitmap file is out of date, doing full "
                        "recovery\n", bmname(bitmap));
 
-       bytes = DIV_ROUND_UP(bitmap->chunks, 8);
-       if (!bitmap->mddev->bitmap_info.external)
-               bytes += sizeof(bitmap_super_t);
-
-       store->bytes = bytes;
-
-       num_pages = DIV_ROUND_UP(bytes, PAGE_SIZE);
-
-       if (file && i_size_read(file->f_mapping->host) < bytes) {
+       if (file && i_size_read(file->f_mapping->host) < store->bytes) {
                printk(KERN_INFO "%s: bitmap file too short %lu < %lu\n",
-                       bmname(bitmap),
-                       (unsigned long) i_size_read(file->f_mapping->host),
-                       bytes);
+                      bmname(bitmap),
+                      (unsigned long) i_size_read(file->f_mapping->host),
+                      store->bytes);
                goto err;
        }
 
-       ret = -ENOMEM;
-
-       store->filemap = kmalloc(sizeof(struct page *)
-                                         * num_pages, GFP_KERNEL);
-       if (!store->filemap)
+       ret = bitmap_storage_alloc(&bitmap->storage, bitmap->chunks,
+                                  !bitmap->mddev->bitmap_info.external);
+       if (ret)
                goto err;
 
-       pnum = 0;
+       oldindex = ~0L;
        offset = 0;
-       if (store->sb_page) {
-               store->filemap[0] = store->sb_page;
-               pnum = 1;
+       if (!bitmap->mddev->bitmap_info.external)
                offset = sizeof(bitmap_super_t);
-       }
-       for ( ; pnum < num_pages; pnum++) {
-               store->filemap[pnum] = alloc_page(GFP_KERNEL);
-               if (!store->filemap[pnum]) {
-                       store->file_pages = pnum;
-                       goto err;
-               }
-       }
-       store->file_pages = pnum;
-
-       /* We need 4 bits per page, rounded up to a multiple of sizeof(unsigned long) */
-       store->filemap_attr = kzalloc(
-               roundup(DIV_ROUND_UP(num_pages*4, 8), sizeof(unsigned long)),
-               GFP_KERNEL);
-       if (!store->filemap_attr)
-               goto err;
-
-       oldindex = ~0L;
 
        for (i = 0; i < chunks; i++) {
                int b;
@@ -1028,8 +1049,8 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
                if (index != oldindex) { /* this is a new page, read it in */
                        int count;
                        /* unmap the old page, we're done with it */
-                       if (index == num_pages-1)
-                               count = bytes - index * PAGE_SIZE;
+                       if (index == store->file_pages-1)
+                               count = store->bytes - index * PAGE_SIZE;
                        else
                                count = PAGE_SIZE;
                        page = store->filemap[index];
@@ -1083,9 +1104,9 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
        }
 
        printk(KERN_INFO "%s: bitmap initialized from disk: "
-              "read %lu/%lu pages, set %lu of %lu bits\n",
+              "read %lu pages, set %lu of %lu bits\n",
               bmname(bitmap), store->file_pages,
-              num_pages, bit_cnt, chunks);
+              bit_cnt, chunks);
 
        return 0;