diff --git a/WHATS_NEW b/WHATS_NEW index 65d055de7..e2b064a59 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,6 @@ Version 2.02.29 - ================================== + Detect md superblocks version 1.0, 1.1 and 1.2. Add _alloc_pv() and _free_pv() from _pv_create() code and fix error paths. Add pv_dev_name() to access PV device name. Add const attributes to pv accessor functions. diff --git a/lib/device/dev-md.c b/lib/device/dev-md.c index 650823b8e..b4e9926ff 100644 --- a/lib/device/dev-md.c +++ b/lib/device/dev-md.c @@ -40,15 +40,35 @@ static int _dev_has_md_magic(struct device *dev, uint64_t sb_offset) return 0; } +/* FIXME Explain this algorithm */ +static uint64_t _v1_sb_offset(uint64_t size, int minor_version) +{ + uint64_t sb_offset; + + switch(minor_version) { + case 0: + sb_offset = (size - 8 * 2) & ~(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 */ int dev_is_md(struct device *dev, uint64_t *sb) { - int ret = 0; - + int ret = 1; + unsigned minor = 0; uint64_t size, sb_offset; - uint32_t md_magic; if (!dev_get_size(dev, &size)) { stack; @@ -63,24 +83,35 @@ int dev_is_md(struct device *dev, uint64_t *sb) return -1; } - sb_offset = MD_NEW_SIZE_SECTORS(size) << SECTOR_SHIFT; - /* Check if it is an md component device. */ - if (_dev_has_md_magic(dev, sb_offset)) { - if (sb) - *sb = sb_offset; - ret = 1; - } + /* Version 0.90.0 */ + sb_offset = MD_NEW_SIZE_SECTORS(size) << SECTOR_SHIFT; + if (_dev_has_md_magic(dev, sb_offset)) + goto out; + /* Version 1, try v1.0 -> v1.2 */ + do { + sb_offset = _v1_sb_offset(size, minor); + if (_dev_has_md_magic(dev, sb_offset)) + goto out; + } while (++minor <= 2); + + ret = 0; + +out: if (!dev_close(dev)) stack; + if (ret && sb) + *sb = sb_offset; + return ret; } #else -int dev_is_md(struct device *dev __attribute((unused)), uint64_t *sb __attribute((unused))) +int dev_is_md(struct device *dev __attribute((unused)), + uint64_t *sb __attribute((unused))) { return 0; }