diff options
author | NeilBrown <neilb@suse.de> | 2012-05-21 23:55:12 -0400 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2012-05-21 23:55:12 -0400 |
commit | d1244cb062750bdb2298ca2565239d3d8cbd91a8 (patch) | |
tree | 85d68d961e0f2c03acf0550d66252a9346495cab /drivers/md | |
parent | 9b1215c102d4b12f6c815d7fdd35d0628db35b28 (diff) |
md/bitmap: separate bitmap file allocation to its own function.
This will allow allocation before swapping in a new bitmap.
Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/bitmap.c | 113 |
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 | ||
719 | static 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 | |||
719 | static void bitmap_file_unmap(struct bitmap *bitmap) | 771 | static 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 | |||
940 | static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) | 992 | static 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 | ||