aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2005-11-09 00:39:32 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-11-09 10:56:38 -0500
commitbd926c63b7a6843d3ce2728396c0891e54fce5c4 (patch)
tree38f7083a733e9b31efe69616c5fa3448c74c1320
parentb2d444d7ad975d555bb919601bcdc0e58975a40e (diff)
[PATCH] md: make md on-disk bitmaps not host-endian
Current bitmaps use set_bit et.al and so are host-endian, which means not-portable. Oops. Define a new version number (4) for which bitmaps are little-endian. Signed-off-by: Neil Brown <neilb@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--drivers/md/bitmap.c22
-rw-r--r--drivers/md/md.c2
-rw-r--r--include/linux/raid/bitmap.h11
-rw-r--r--include/linux/raid/md.h4
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 */
134enum bitmap_state { 140enum 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
72extern int register_md_personality (int p_num, mdk_personality_t *p); 74extern int register_md_personality (int p_num, mdk_personality_t *p);
73extern int unregister_md_personality (int p_num); 75extern int unregister_md_personality (int p_num);