diff options
-rw-r--r-- | drivers/md/bitmap.c | 22 | ||||
-rw-r--r-- | drivers/md/md.c | 2 | ||||
-rw-r--r-- | include/linux/raid/bitmap.h | 11 | ||||
-rw-r--r-- | include/linux/raid/md.h | 4 |
4 files changed, 31 insertions, 8 deletions
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index c5fa4c2a5af1..220273e81ed6 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c | |||
@@ -482,7 +482,8 @@ static int bitmap_read_sb(struct bitmap *bitmap) | |||
482 | /* verify that the bitmap-specific fields are valid */ | 482 | /* verify that the bitmap-specific fields are valid */ |
483 | if (sb->magic != cpu_to_le32(BITMAP_MAGIC)) | 483 | if (sb->magic != cpu_to_le32(BITMAP_MAGIC)) |
484 | reason = "bad magic"; | 484 | reason = "bad magic"; |
485 | else if (sb->version != cpu_to_le32(BITMAP_MAJOR)) | 485 | else if (le32_to_cpu(sb->version) < BITMAP_MAJOR_LO || |
486 | le32_to_cpu(sb->version) > BITMAP_MAJOR_HI) | ||
486 | reason = "unrecognized superblock version"; | 487 | reason = "unrecognized superblock version"; |
487 | else if (chunksize < 512 || chunksize > (1024 * 1024 * 4)) | 488 | else if (chunksize < 512 || chunksize > (1024 * 1024 * 4)) |
488 | reason = "bitmap chunksize out of range (512B - 4MB)"; | 489 | reason = "bitmap chunksize out of range (512B - 4MB)"; |
@@ -527,6 +528,8 @@ success: | |||
527 | bitmap->daemon_lastrun = jiffies; | 528 | bitmap->daemon_lastrun = jiffies; |
528 | bitmap->max_write_behind = write_behind; | 529 | bitmap->max_write_behind = write_behind; |
529 | bitmap->flags |= sb->state; | 530 | bitmap->flags |= sb->state; |
531 | if (le32_to_cpu(sb->version) == BITMAP_MAJOR_HOSTENDIAN) | ||
532 | bitmap->flags |= BITMAP_HOSTENDIAN; | ||
530 | bitmap->events_cleared = le64_to_cpu(sb->events_cleared); | 533 | bitmap->events_cleared = le64_to_cpu(sb->events_cleared); |
531 | if (sb->state & BITMAP_STALE) | 534 | if (sb->state & BITMAP_STALE) |
532 | bitmap->events_cleared = bitmap->mddev->events; | 535 | bitmap->events_cleared = bitmap->mddev->events; |
@@ -764,7 +767,10 @@ static void bitmap_file_set_bit(struct bitmap *bitmap, sector_t block) | |||
764 | 767 | ||
765 | /* set the bit */ | 768 | /* set the bit */ |
766 | kaddr = kmap_atomic(page, KM_USER0); | 769 | kaddr = kmap_atomic(page, KM_USER0); |
767 | set_bit(bit, kaddr); | 770 | if (bitmap->flags & BITMAP_HOSTENDIAN) |
771 | set_bit(bit, kaddr); | ||
772 | else | ||
773 | ext2_set_bit(bit, kaddr); | ||
768 | kunmap_atomic(kaddr, KM_USER0); | 774 | kunmap_atomic(kaddr, KM_USER0); |
769 | PRINTK("set file bit %lu page %lu\n", bit, page->index); | 775 | PRINTK("set file bit %lu page %lu\n", bit, page->index); |
770 | 776 | ||
@@ -891,6 +897,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) | |||
891 | oldindex = ~0L; | 897 | oldindex = ~0L; |
892 | 898 | ||
893 | for (i = 0; i < chunks; i++) { | 899 | for (i = 0; i < chunks; i++) { |
900 | int b; | ||
894 | index = file_page_index(i); | 901 | index = file_page_index(i); |
895 | bit = file_page_offset(i); | 902 | bit = file_page_offset(i); |
896 | if (index != oldindex) { /* this is a new page, read it in */ | 903 | if (index != oldindex) { /* this is a new page, read it in */ |
@@ -939,7 +946,11 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) | |||
939 | 946 | ||
940 | bitmap->filemap[bitmap->file_pages++] = page; | 947 | bitmap->filemap[bitmap->file_pages++] = page; |
941 | } | 948 | } |
942 | if (test_bit(bit, page_address(page))) { | 949 | if (bitmap->flags & BITMAP_HOSTENDIAN) |
950 | b = test_bit(bit, page_address(page)); | ||
951 | else | ||
952 | b = ext2_test_bit(bit, page_address(page)); | ||
953 | if (b) { | ||
943 | /* if the disk bit is set, set the memory bit */ | 954 | /* if the disk bit is set, set the memory bit */ |
944 | bitmap_set_memory_bits(bitmap, i << CHUNK_BLOCK_SHIFT(bitmap), | 955 | bitmap_set_memory_bits(bitmap, i << CHUNK_BLOCK_SHIFT(bitmap), |
945 | ((i+1) << (CHUNK_BLOCK_SHIFT(bitmap)) >= start) | 956 | ((i+1) << (CHUNK_BLOCK_SHIFT(bitmap)) >= start) |
@@ -1097,7 +1108,10 @@ int bitmap_daemon_work(struct bitmap *bitmap) | |||
1097 | -1); | 1108 | -1); |
1098 | 1109 | ||
1099 | /* clear the bit */ | 1110 | /* clear the bit */ |
1100 | clear_bit(file_page_offset(j), page_address(page)); | 1111 | if (bitmap->flags & BITMAP_HOSTENDIAN) |
1112 | clear_bit(file_page_offset(j), page_address(page)); | ||
1113 | else | ||
1114 | ext2_clear_bit(file_page_offset(j), page_address(page)); | ||
1101 | } | 1115 | } |
1102 | } | 1116 | } |
1103 | spin_unlock_irqrestore(&bitmap->lock, flags); | 1117 | spin_unlock_irqrestore(&bitmap->lock, flags); |
diff --git a/drivers/md/md.c b/drivers/md/md.c index 9dfa063d1c6a..caa4add00c1b 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -4281,7 +4281,7 @@ static int __init md_init(void) | |||
4281 | " MD_SB_DISKS=%d\n", | 4281 | " MD_SB_DISKS=%d\n", |
4282 | MD_MAJOR_VERSION, MD_MINOR_VERSION, | 4282 | MD_MAJOR_VERSION, MD_MINOR_VERSION, |
4283 | MD_PATCHLEVEL_VERSION, MAX_MD_DEVS, MD_SB_DISKS); | 4283 | MD_PATCHLEVEL_VERSION, MAX_MD_DEVS, MD_SB_DISKS); |
4284 | printk(KERN_INFO "md: bitmap version %d.%d\n", BITMAP_MAJOR, | 4284 | printk(KERN_INFO "md: bitmap version %d.%d\n", BITMAP_MAJOR_HI, |
4285 | BITMAP_MINOR); | 4285 | BITMAP_MINOR); |
4286 | 4286 | ||
4287 | if (register_blkdev(MAJOR_NR, "md")) | 4287 | if (register_blkdev(MAJOR_NR, "md")) |
diff --git a/include/linux/raid/bitmap.h b/include/linux/raid/bitmap.h index 9de99198caf1..899437802aea 100644 --- a/include/linux/raid/bitmap.h +++ b/include/linux/raid/bitmap.h | |||
@@ -6,7 +6,13 @@ | |||
6 | #ifndef BITMAP_H | 6 | #ifndef BITMAP_H |
7 | #define BITMAP_H 1 | 7 | #define BITMAP_H 1 |
8 | 8 | ||
9 | #define BITMAP_MAJOR 3 | 9 | #define BITMAP_MAJOR_LO 3 |
10 | /* version 4 insists the bitmap is in little-endian order | ||
11 | * with version 3, it is host-endian which is non-portable | ||
12 | */ | ||
13 | #define BITMAP_MAJOR_HI 4 | ||
14 | #define BITMAP_MAJOR_HOSTENDIAN 3 | ||
15 | |||
10 | #define BITMAP_MINOR 39 | 16 | #define BITMAP_MINOR 39 |
11 | 17 | ||
12 | /* | 18 | /* |
@@ -133,7 +139,8 @@ typedef __u16 bitmap_counter_t; | |||
133 | /* use these for bitmap->flags and bitmap->sb->state bit-fields */ | 139 | /* use these for bitmap->flags and bitmap->sb->state bit-fields */ |
134 | enum bitmap_state { | 140 | enum bitmap_state { |
135 | BITMAP_ACTIVE = 0x001, /* the bitmap is in use */ | 141 | BITMAP_ACTIVE = 0x001, /* the bitmap is in use */ |
136 | BITMAP_STALE = 0x002 /* the bitmap file is out of date or had -EIO */ | 142 | BITMAP_STALE = 0x002, /* the bitmap file is out of date or had -EIO */ |
143 | BITMAP_HOSTENDIAN = 0x8000, | ||
137 | }; | 144 | }; |
138 | 145 | ||
139 | /* the superblock at the front of the bitmap file -- little endian */ | 146 | /* the superblock at the front of the bitmap file -- little endian */ |
diff --git a/include/linux/raid/md.h b/include/linux/raid/md.h index ffa316ce4dc8..91467a3c4a52 100644 --- a/include/linux/raid/md.h +++ b/include/linux/raid/md.h | |||
@@ -66,8 +66,10 @@ | |||
66 | * and major_version/minor_version accordingly | 66 | * and major_version/minor_version accordingly |
67 | * >=2 means that Internal bitmaps are supported by setting MD_SB_BITMAP_PRESENT | 67 | * >=2 means that Internal bitmaps are supported by setting MD_SB_BITMAP_PRESENT |
68 | * in the super status byte | 68 | * in the super status byte |
69 | * >=3 means that bitmap superblock version 4 is supported, which uses | ||
70 | * little-ending representation rather than host-endian | ||
69 | */ | 71 | */ |
70 | #define MD_PATCHLEVEL_VERSION 2 | 72 | #define MD_PATCHLEVEL_VERSION 3 |
71 | 73 | ||
72 | extern int register_md_personality (int p_num, mdk_personality_t *p); | 74 | extern int register_md_personality (int p_num, mdk_personality_t *p); |
73 | extern int unregister_md_personality (int p_num); | 75 | extern int unregister_md_personality (int p_num); |