Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bd926c63 authored by NeilBrown's avatar NeilBrown Committed by Linus Torvalds
Browse files

[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: default avatarNeil Brown <neilb@suse.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent b2d444d7
Loading
Loading
Loading
Loading
+18 −4
Original line number Diff line number Diff line
@@ -482,7 +482,8 @@ static int bitmap_read_sb(struct bitmap *bitmap)
	/* verify that the bitmap-specific fields are valid */
	if (sb->magic != cpu_to_le32(BITMAP_MAGIC))
		reason = "bad magic";
	else if (sb->version != cpu_to_le32(BITMAP_MAJOR))
	else if (le32_to_cpu(sb->version) < BITMAP_MAJOR_LO ||
		 le32_to_cpu(sb->version) > BITMAP_MAJOR_HI)
		reason = "unrecognized superblock version";
	else if (chunksize < 512 || chunksize > (1024 * 1024 * 4))
		reason = "bitmap chunksize out of range (512B - 4MB)";
@@ -527,6 +528,8 @@ static int bitmap_read_sb(struct bitmap *bitmap)
	bitmap->daemon_lastrun = jiffies;
	bitmap->max_write_behind = write_behind;
	bitmap->flags |= sb->state;
	if (le32_to_cpu(sb->version) == BITMAP_MAJOR_HOSTENDIAN)
		bitmap->flags |= BITMAP_HOSTENDIAN;
	bitmap->events_cleared = le64_to_cpu(sb->events_cleared);
	if (sb->state & BITMAP_STALE)
		bitmap->events_cleared = bitmap->mddev->events;
@@ -764,7 +767,10 @@ static void bitmap_file_set_bit(struct bitmap *bitmap, sector_t block)

 	/* set the bit */
	kaddr = kmap_atomic(page, KM_USER0);
	if (bitmap->flags & BITMAP_HOSTENDIAN)
		set_bit(bit, kaddr);
	else
		ext2_set_bit(bit, kaddr);
	kunmap_atomic(kaddr, KM_USER0);
	PRINTK("set file bit %lu page %lu\n", bit, page->index);

@@ -891,6 +897,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
	oldindex = ~0L;

	for (i = 0; i < chunks; i++) {
		int b;
		index = file_page_index(i);
		bit = file_page_offset(i);
		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)

			bitmap->filemap[bitmap->file_pages++] = page;
		}
		if (test_bit(bit, page_address(page))) {
		if (bitmap->flags & BITMAP_HOSTENDIAN)
			b = test_bit(bit, page_address(page));
		else
			b = ext2_test_bit(bit, page_address(page));
		if (b) {
			/* if the disk bit is set, set the memory bit */
			bitmap_set_memory_bits(bitmap, i << CHUNK_BLOCK_SHIFT(bitmap),
					       ((i+1) << (CHUNK_BLOCK_SHIFT(bitmap)) >= start)
@@ -1097,7 +1108,10 @@ int bitmap_daemon_work(struct bitmap *bitmap)
						  -1);

				/* clear the bit */
				if (bitmap->flags & BITMAP_HOSTENDIAN)
					clear_bit(file_page_offset(j), page_address(page));
				else
					ext2_clear_bit(file_page_offset(j), page_address(page));
			}
		}
		spin_unlock_irqrestore(&bitmap->lock, flags);
+1 −1
Original line number Diff line number Diff line
@@ -4281,7 +4281,7 @@ static int __init md_init(void)
			" MD_SB_DISKS=%d\n",
			MD_MAJOR_VERSION, MD_MINOR_VERSION,
			MD_PATCHLEVEL_VERSION, MAX_MD_DEVS, MD_SB_DISKS);
	printk(KERN_INFO "md: bitmap version %d.%d\n", BITMAP_MAJOR,
	printk(KERN_INFO "md: bitmap version %d.%d\n", BITMAP_MAJOR_HI,
			BITMAP_MINOR);

	if (register_blkdev(MAJOR_NR, "md"))
+9 −2
Original line number Diff line number Diff line
@@ -6,7 +6,13 @@
#ifndef BITMAP_H
#define BITMAP_H 1

#define BITMAP_MAJOR 3
#define BITMAP_MAJOR_LO 3
/* version 4 insists the bitmap is in little-endian order
 * with version 3, it is host-endian which is non-portable
 */
#define BITMAP_MAJOR_HI 4
#define	BITMAP_MAJOR_HOSTENDIAN 3

#define BITMAP_MINOR 39

/*
@@ -133,7 +139,8 @@ typedef __u16 bitmap_counter_t;
/* use these for bitmap->flags and bitmap->sb->state bit-fields */
enum bitmap_state {
	BITMAP_ACTIVE = 0x001, /* the bitmap is in use */
	BITMAP_STALE  = 0x002  /* the bitmap file is out of date or had -EIO */
	BITMAP_STALE  = 0x002,  /* the bitmap file is out of date or had -EIO */
	BITMAP_HOSTENDIAN = 0x8000,
};

/* the superblock at the front of the bitmap file -- little endian */
+3 −1
Original line number Diff line number Diff line
@@ -66,8 +66,10 @@
 *     and major_version/minor_version accordingly
 * >=2 means that Internal bitmaps are supported by setting MD_SB_BITMAP_PRESENT
 *     in the super status byte
 * >=3 means that bitmap superblock version 4 is supported, which uses
 *     little-ending representation rather than host-endian
 */
#define MD_PATCHLEVEL_VERSION           2
#define MD_PATCHLEVEL_VERSION           3

extern int register_md_personality (int p_num, mdk_personality_t *p);
extern int unregister_md_personality (int p_num);