[PATCH] lvm2 support for detecting v1.x MD superblocks

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



lvm2's MD v1.0 superblock detection doesn't work at all (because it
doesn't use v1 sb offsets).

I've tested the attached patch to work on MDs with v0.90.0, v1.0,
v1.1, and v1.2 superblocks.

please advise, thanks.
Mike
Index: lib/device/dev-md.c
===================================================================
RCS file: /cvs/lvm2/LVM2/lib/device/dev-md.c,v
retrieving revision 1.5
diff -u -r1.5 dev-md.c
--- lib/device/dev-md.c	20 Aug 2007 20:55:25 -0000	1.5
+++ lib/device/dev-md.c	23 Oct 2007 15:17:57 -0000
@@ -25,6 +25,40 @@
 #define MD_NEW_SIZE_SECTORS(x) ((x & ~(MD_RESERVED_SECTORS - 1)) \
 				- MD_RESERVED_SECTORS)
 
+int dev_has_md_sb(struct device *dev, uint64_t sb_offset, uint64_t *sb)
+{
+	int ret = 0;	
+	uint32_t md_magic;
+	/* Version 1 is little endian; version 0.90.0 is machine endian */
+	if (dev_read(dev, sb_offset, sizeof(uint32_t), &md_magic) &&
+	    ((md_magic == xlate32(MD_SB_MAGIC)) ||
+	     (md_magic == MD_SB_MAGIC))) {
+		if (sb)
+			*sb = sb_offset;
+		ret = 1;
+	}
+	return ret;
+}
+
+uint64_t v1_sb_offset(uint64_t size, int minor_version) {
+	uint64_t sb_offset;
+	switch(minor_version) {
+	case 0:
+		sb_offset = size;
+		sb_offset -= 8*2;
+		sb_offset &= ~(4*2-1);
+		break;
+	case 1:
+		sb_offset = 0;
+		break;
+	case 2:
+		sb_offset = 4*2;
+		break;
+	}
+	sb_offset <<= SECTOR_SHIFT;
+	return sb_offset;
+}
+
 /*
  * Returns -1 on error
  */
@@ -35,7 +69,6 @@
 #ifdef linux
 
 	uint64_t size, sb_offset;
-	uint32_t md_magic;
 
 	if (!dev_get_size(dev, &size)) {
 		stack;
@@ -50,16 +83,20 @@
 		return -1;
 	}
 
-	sb_offset = MD_NEW_SIZE_SECTORS(size) << SECTOR_SHIFT;
-
 	/* Check if it is an md component device. */
-	/* Version 1 is little endian; version 0.90.0 is machine endian */
-	if (dev_read(dev, sb_offset, sizeof(uint32_t), &md_magic) &&
-	    ((md_magic == xlate32(MD_SB_MAGIC)) ||
-	     (md_magic == MD_SB_MAGIC))) {
-		if (sb)
-			*sb = sb_offset;
+	/* Version 0.90.0 */
+	sb_offset = MD_NEW_SIZE_SECTORS(size) << SECTOR_SHIFT;
+	if (dev_has_md_sb(dev, sb_offset, sb)) {
 		ret = 1;
+	} else {
+		/* Version 1, try v1.0 -> v1.2 */
+		int minor;
+		for (minor = 0; minor <= 2; minor++) {
+			if (dev_has_md_sb(dev, v1_sb_offset(size, minor), sb)) {
+				ret = 1;
+				break;
+			}
+		}
 	}
 
 	if (!dev_close(dev))

[Index of Archives]     [Linux RAID Wiki]     [ATA RAID]     [Linux SCSI Target Infrastructure]     [Linux Block]     [Linux IDE]     [Linux SCSI]     [Linux Hams]     [Device Mapper]     [Device Mapper Cryptographics]     [Kernel]     [Linux Admin]     [Linux Net]     [GFS]     [RPM]     [git]     [Yosemite Forum]


  Powered by Linux