summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2019-09-19 11:33:59 -0500
committerDavid Teigland <teigland@redhat.com>2020-07-09 10:48:21 -0500
commit23774f997ea077f2cbe8a32bd8bccdd7f4560cca (patch)
treeb115cc2d95c482a0c170667cc2f68835af266e21
parent286a793c12aac1fde17cb9768bacad660e1dfeb3 (diff)
downloadlvm2-23774f997ea077f2cbe8a32bd8bccdd7f4560cca.tar.gz
devices: detect md ddf and imsm superblocks
-rw-r--r--lib/device/dev-md.c105
1 files changed, 104 insertions, 1 deletions
diff --git a/lib/device/dev-md.c b/lib/device/dev-md.c
index 9d0a36363..13a3c168a 100644
--- a/lib/device/dev-md.c
+++ b/lib/device/dev-md.c
@@ -16,6 +16,7 @@
#include "lib/misc/lib.h"
#include "lib/device/dev-type.h"
#include "lib/mm/xlate.h"
+#include "lib/misc/crc.h"
#ifdef UDEV_SYNC_SUPPORT
#include <libudev.h> /* for MD detection using udev db records */
#include "lib/device/dev-ext-udev-constants.h"
@@ -48,6 +49,93 @@ static int _dev_has_md_magic(struct device *dev, uint64_t sb_offset)
return 0;
}
+#define IMSM_SIGNATURE "Intel Raid ISM Cfg Sig. "
+#define IMSM_SIG_LEN (strlen(IMSM_SIGNATURE))
+
+static int _dev_has_imsm_magic(struct device *dev, uint64_t devsize_sectors)
+{
+ char imsm_signature[IMSM_SIG_LEN];
+ uint64_t off = (devsize_sectors * 512) - 1024;
+
+ if (!dev_read_bytes(dev, off, IMSM_SIG_LEN, imsm_signature))
+ return_0;
+
+ if (!memcmp(imsm_signature, IMSM_SIGNATURE, IMSM_SIG_LEN))
+ return 1;
+
+ return 0;
+}
+
+#define DDF_MAGIC 0xDE11DE11
+struct ddf_header {
+ uint32_t magic;
+ uint32_t crc;
+ char guid[24];
+ char revision[8];
+ char padding[472];
+};
+
+static int _dev_has_ddf_magic(struct device *dev, uint64_t devsize_sectors)
+{
+ struct ddf_header hdr;
+ uint32_t crc, our_crc;
+ uint64_t off;
+ uint64_t devsize_bytes = devsize_sectors * 512;
+
+ if (devsize_bytes < 0x30000)
+ return 0;
+
+ /* 512 bytes before the end of device (from libblkid) */
+ off = ((devsize_bytes / 0x200) - 1) * 0x200;
+
+ if (!dev_read_bytes(dev, off, 512, &hdr))
+ return_0;
+
+ if ((hdr.magic == cpu_to_be32(DDF_MAGIC)) ||
+ (hdr.magic == cpu_to_le32(DDF_MAGIC))) {
+ crc = hdr.crc;
+ hdr.crc = 0xffffffff;
+ our_crc = calc_crc(0, (const uint8_t *)&hdr, 512);
+
+ if ((cpu_to_be32(our_crc) == crc) ||
+ (cpu_to_le32(our_crc) == crc)) {
+ log_debug_devs("Found md ddf magic at %llu crc %x %s",
+ (unsigned long long)off, crc, dev_name(dev));
+ return 1;
+ } else {
+ log_debug_devs("Found md ddf magic at %llu wrong crc %x disk %x %s",
+ (unsigned long long)off, our_crc, crc, dev_name(dev));
+ return 0;
+ }
+ }
+
+ /* 128KB before the end of device (from libblkid) */
+ off = ((devsize_bytes / 0x200) - 257) * 0x200;
+
+ if (!dev_read_bytes(dev, off, 512, &hdr))
+ return_0;
+
+ if ((hdr.magic == cpu_to_be32(DDF_MAGIC)) ||
+ (hdr.magic == cpu_to_le32(DDF_MAGIC))) {
+ crc = hdr.crc;
+ hdr.crc = 0xffffffff;
+ our_crc = calc_crc(0, (const uint8_t *)&hdr, 512);
+
+ if ((cpu_to_be32(our_crc) == crc) ||
+ (cpu_to_le32(our_crc) == crc)) {
+ log_debug_devs("Found md ddf magic at %llu crc %x %s",
+ (unsigned long long)off, crc, dev_name(dev));
+ return 1;
+ } else {
+ log_debug_devs("Found md ddf magic at %llu wrong crc %x disk %x %s",
+ (unsigned long long)off, our_crc, crc, dev_name(dev));
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
/*
* Calculate the position of the superblock.
* It is always aligned to a 4K boundary and
@@ -178,8 +266,8 @@ static int _native_dev_is_md_component(struct device *dev, uint64_t *offset_foun
goto out;
}
- /* Check if it is an md component device. */
/* Version 0.90.0 */
+ /* superblock at 64KB from end of device */
sb_offset = MD_NEW_SIZE_SECTORS(size) << SECTOR_SHIFT;
if (_dev_has_md_magic(dev, sb_offset)) {
ret = 1;
@@ -187,8 +275,11 @@ static int _native_dev_is_md_component(struct device *dev, uint64_t *offset_foun
}
minor = MD_MINOR_VERSION_MIN;
+
/* Version 1, try v1.0 -> v1.2 */
+
do {
+ /* superblock at start or 4K from start */
sb_offset = _v1_sb_offset(size, minor);
if (_dev_has_md_magic(dev, sb_offset)) {
ret = 1;
@@ -196,6 +287,18 @@ static int _native_dev_is_md_component(struct device *dev, uint64_t *offset_foun
}
} while (++minor <= MD_MINOR_VERSION_MAX);
+ /* superblock 1K from end of device */
+ if (_dev_has_imsm_magic(dev, size)) {
+ ret = 1;
+ goto out;
+ }
+
+ /* superblock 512 bytes from end, or 128KB from end */
+ if (_dev_has_ddf_magic(dev, size)) {
+ ret = 1;
+ goto out;
+ }
+
ret = 0;
out:
if (ret && offset_found)