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))