Package: lvm2
Version: 2.02.95-4
Tags: patch wheezy sid
Severity: important

Currently, lvm automatically filters out mdraid devices. That is a
good thing, otherwise it could accidentally activate volume groups
on disks that are part of a mdraid array.

For quite some time now, the mdraid subsystem (mainly through mdadm)
supports more metadata formats than native mdraid only. These are
the 'imsm' (Intel Matrix Raid) and 'ddf' formats.

This patch makes sure that disks with signatures of one of these
metadata formats are also filtered out. To minimize the chance of
regressions, it only does this if md is actually running (i.e.
/proc/mdstat is present).

Background: I have added support for installation on Intel Matrix raid (imsm)
arrays using mdadm to d-i, and I'll be sending patches to the debian-boot
list soon. Please consider this patch for inclusion in wheezy.

Changelog entry:

  * lvm already filters disks that have a mdraid signature, now also filter
    DDF and IMSM formatted disks as well - but only if MD is actually running.

Mike.
Description: Also automatically filter DDF and IMSM formatted disks
Author: Miquel van Smoorenburg <miqu...@debian.org>

--- lvm2-2.02.95.orig/lib/device/dev-md.c
+++ lvm2-2.02.95/lib/device/dev-md.c
@@ -16,6 +16,7 @@
 #include "lib.h"
 #include "metadata.h"
 #include "xlate.h"
+#include "crc.h"
 #include "filter.h"
 
 #ifdef linux
@@ -29,6 +30,18 @@
 				- MD_RESERVED_SECTORS)
 #define MD_MAX_SYSFS_SIZE 64
 
+#define IMSM_SIGNATURE "Intel Raid ISM Cfg Sig. "
+#define IMSM_SIG_LEN (strlen(IMSM_SIGNATURE))
+
+#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_md_magic(struct device *dev, uint64_t sb_offset)
 {
 	uint32_t md_magic;
@@ -42,6 +55,34 @@ static int _dev_has_md_magic(struct devi
 	return 0;
 }
 
+static int _dev_has_imsm_superblock(struct device *dev, uint64_t dev_size)
+{
+	char imsm_signature[IMSM_SIG_LEN];
+
+	if (dev_read(dev, dev_size - 1024, IMSM_SIG_LEN, imsm_signature) &&
+	    memcmp(imsm_signature, IMSM_SIGNATURE, IMSM_SIG_LEN) == 0)
+		return 1;
+
+	return 0;
+}
+
+static int _dev_has_ddf_superblock(struct device *dev, uint64_t dev_size)
+{
+	struct ddf_header hdr;
+	uint32_t crc;
+
+	/* Also calculate CRC so we have at least 8 bytes to check */
+	if (dev_read(dev, dev_size - 512, 512, &hdr) &&
+	    (hdr.magic == xlate32(DDF_MAGIC))) {
+		crc = hdr.crc;
+		hdr.crc = 0xffffffff;
+		if (xlate32(calc_crc(0, (const uint8_t *)&hdr, 512)) == crc)
+			return 1;
+	}
+
+	return 0;
+}
+
 /*
  * Calculate the position of the superblock.
  * It is always aligned to a 4K boundary and
@@ -86,6 +127,7 @@ int dev_is_md(struct device *dev, uint64
 	int ret = 1;
 	md_minor_version_t minor;
 	uint64_t size, sb_offset;
+	struct stat st;
 
 	if (!dev_get_size(dev, &size)) {
 		stack;
@@ -114,6 +156,18 @@ int dev_is_md(struct device *dev, uint64
 			goto out;
 	} while (++minor <= MD_MINOR_VERSION_MAX);
 
+	/* Only check for ddf/imsm if md is actually running. */
+	if (stat("/proc/mdstat", &st) < 0)
+		goto out;
+
+	/* Check if it is a ddf container device */
+	if (_dev_has_ddf_superblock(dev, size))
+		goto out;
+
+	/* Check if it is an imsm container device */
+	if (_dev_has_imsm_superblock(dev, size))
+		goto out;
+
 	ret = 0;
 
 out:

Reply via email to