aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/bitmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md/bitmap.c')
-rw-r--r--drivers/md/bitmap.c113
1 files changed, 67 insertions, 46 deletions
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 7a3be0d4103e..4ac60ed66c49 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -716,6 +716,58 @@ static inline struct page *filemap_get_page(struct bitmap_storage *store,
716 - file_page_index(store, 0)]; 716 - file_page_index(store, 0)];
717} 717}
718 718
719static int bitmap_storage_alloc(struct bitmap_storage *store,
720 unsigned long chunks, int with_super)
721{
722 int pnum;
723 unsigned long num_pages;
724 unsigned long bytes;
725
726 bytes = DIV_ROUND_UP(chunks, 8);
727 if (with_super)
728 bytes += sizeof(bitmap_super_t);
729
730 num_pages = DIV_ROUND_UP(bytes, PAGE_SIZE);
731
732 store->filemap = kmalloc(sizeof(struct page *)
733 * num_pages, GFP_KERNEL);
734 if (!store->filemap)
735 return -ENOMEM;
736
737 if (with_super && !store->sb_page) {
738 store->sb_page = alloc_page(GFP_KERNEL);
739 if (store->sb_page == NULL)
740 return -ENOMEM;
741 store->sb_page->index = 0;
742 }
743 pnum = 0;
744 if (store->sb_page) {
745 store->filemap[0] = store->sb_page;
746 pnum = 1;
747 }
748 for ( ; pnum < num_pages; pnum++) {
749 store->filemap[pnum] = alloc_page(GFP_KERNEL);
750 if (!store->filemap[pnum]) {
751 store->file_pages = pnum;
752 return -ENOMEM;
753 }
754 store->filemap[pnum]->index = pnum;
755 }
756 store->file_pages = pnum;
757
758 /* We need 4 bits per page, rounded up to a multiple
759 * of sizeof(unsigned long) */
760 store->filemap_attr = kzalloc(
761 roundup(DIV_ROUND_UP(num_pages*4, 8), sizeof(unsigned long)),
762 GFP_KERNEL);
763 if (!store->filemap_attr)
764 return -ENOMEM;
765
766 store->bytes = bytes;
767
768 return 0;
769}
770
719static void bitmap_file_unmap(struct bitmap *bitmap) 771static void bitmap_file_unmap(struct bitmap *bitmap)
720{ 772{
721 struct page **map, *sb_page; 773 struct page **map, *sb_page;
@@ -940,11 +992,10 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int n
940static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) 992static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
941{ 993{
942 unsigned long i, chunks, index, oldindex, bit; 994 unsigned long i, chunks, index, oldindex, bit;
943 int pnum;
944 struct page *page = NULL; 995 struct page *page = NULL;
945 unsigned long num_pages, bit_cnt = 0; 996 unsigned long bit_cnt = 0;
946 struct file *file; 997 struct file *file;
947 unsigned long bytes, offset; 998 unsigned long offset;
948 int outofdate; 999 int outofdate;
949 int ret = -ENOSPC; 1000 int ret = -ENOSPC;
950 void *paddr; 1001 void *paddr;
@@ -973,53 +1024,23 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
973 printk(KERN_INFO "%s: bitmap file is out of date, doing full " 1024 printk(KERN_INFO "%s: bitmap file is out of date, doing full "
974 "recovery\n", bmname(bitmap)); 1025 "recovery\n", bmname(bitmap));
975 1026
976 bytes = DIV_ROUND_UP(bitmap->chunks, 8); 1027 if (file && i_size_read(file->f_mapping->host) < store->bytes) {
977 if (!bitmap->mddev->bitmap_info.external)
978 bytes += sizeof(bitmap_super_t);
979
980 store->bytes = bytes;
981
982 num_pages = DIV_ROUND_UP(bytes, PAGE_SIZE);
983
984 if (file && i_size_read(file->f_mapping->host) < bytes) {
985 printk(KERN_INFO "%s: bitmap file too short %lu < %lu\n", 1028 printk(KERN_INFO "%s: bitmap file too short %lu < %lu\n",
986 bmname(bitmap), 1029 bmname(bitmap),
987 (unsigned long) i_size_read(file->f_mapping->host), 1030 (unsigned long) i_size_read(file->f_mapping->host),
988 bytes); 1031 store->bytes);
989 goto err; 1032 goto err;
990 } 1033 }
991 1034
992 ret = -ENOMEM; 1035 ret = bitmap_storage_alloc(&bitmap->storage, bitmap->chunks,
993 1036 !bitmap->mddev->bitmap_info.external);
994 store->filemap = kmalloc(sizeof(struct page *) 1037 if (ret)
995 * num_pages, GFP_KERNEL);
996 if (!store->filemap)
997 goto err; 1038 goto err;
998 1039
999 pnum = 0; 1040 oldindex = ~0L;
1000 offset = 0; 1041 offset = 0;
1001 if (store->sb_page) { 1042 if (!bitmap->mddev->bitmap_info.external)
1002 store->filemap[0] = store->sb_page;
1003 pnum = 1;
1004 offset = sizeof(bitmap_super_t); 1043 offset = sizeof(bitmap_super_t);
1005 }
1006 for ( ; pnum < num_pages; pnum++) {
1007 store->filemap[pnum] = alloc_page(GFP_KERNEL);
1008 if (!store->filemap[pnum]) {
1009 store->file_pages = pnum;
1010 goto err;
1011 }
1012 }
1013 store->file_pages = pnum;
1014
1015 /* We need 4 bits per page, rounded up to a multiple of sizeof(unsigned long) */
1016 store->filemap_attr = kzalloc(
1017 roundup(DIV_ROUND_UP(num_pages*4, 8), sizeof(unsigned long)),
1018 GFP_KERNEL);
1019 if (!store->filemap_attr)
1020 goto err;
1021
1022 oldindex = ~0L;
1023 1044
1024 for (i = 0; i < chunks; i++) { 1045 for (i = 0; i < chunks; i++) {
1025 int b; 1046 int b;
@@ -1028,8 +1049,8 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
1028 if (index != oldindex) { /* this is a new page, read it in */ 1049 if (index != oldindex) { /* this is a new page, read it in */
1029 int count; 1050 int count;
1030 /* unmap the old page, we're done with it */ 1051 /* unmap the old page, we're done with it */
1031 if (index == num_pages-1) 1052 if (index == store->file_pages-1)
1032 count = bytes - index * PAGE_SIZE; 1053 count = store->bytes - index * PAGE_SIZE;
1033 else 1054 else
1034 count = PAGE_SIZE; 1055 count = PAGE_SIZE;
1035 page = store->filemap[index]; 1056 page = store->filemap[index];
@@ -1083,9 +1104,9 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
1083 } 1104 }
1084 1105
1085 printk(KERN_INFO "%s: bitmap initialized from disk: " 1106 printk(KERN_INFO "%s: bitmap initialized from disk: "
1086 "read %lu/%lu pages, set %lu of %lu bits\n", 1107 "read %lu pages, set %lu of %lu bits\n",
1087 bmname(bitmap), store->file_pages, 1108 bmname(bitmap), store->file_pages,
1088 num_pages, bit_cnt, chunks); 1109 bit_cnt, chunks);
1089 1110
1090 return 0; 1111 return 0;
1091 1112