aboutsummaryrefslogtreecommitdiffstats
path: root/lib/blkid
diff options
context:
space:
mode:
authorEric Sandeen <sandeen@redhat.com>2008-01-30 17:25:03 -0600
committerTheodore Ts'o <tytso@mit.edu>2008-02-19 08:40:15 -0500
commita451d92f38188f7218a837a395b310354864b5a4 (patch)
tree93bbd00f547802614d26bf33820817b0cb07343e /lib/blkid
parent6b226c3de2aea0ae3a44a56d0322ba3a7f561886 (diff)
downloadandroid_external_e2fsprogs-a451d92f38188f7218a837a395b310354864b5a4.tar.gz
android_external_e2fsprogs-a451d92f38188f7218a837a395b310354864b5a4.tar.bz2
android_external_e2fsprogs-a451d92f38188f7218a837a395b310354864b5a4.zip
blkid: detect LVM2 physical volumes
Bits liberally stolen from lvm2 userspace. Addresses-Red-Hat-Bugzilla: #409321 Signed-off-by: Eric Sandeen <sandeen@redhat.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'lib/blkid')
-rw-r--r--lib/blkid/probe.c70
-rw-r--r--lib/blkid/probe.h14
2 files changed, 84 insertions, 0 deletions
diff --git a/lib/blkid/probe.c b/lib/blkid/probe.c
index 00cf8507..8f73355c 100644
--- a/lib/blkid/probe.c
+++ b/lib/blkid/probe.c
@@ -1020,6 +1020,72 @@ static int probe_hfsplus(struct blkid_probe *probe,
return 1;
}
+#define LVM2_LABEL_SIZE 512
+static int lvm2_calc_crc(const void *buf, uint size)
+{
+ static const uint crctab[] = {
+ 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
+ 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
+ 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
+ 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
+ };
+ uint i, crc = 0xf597a6cf;
+ const __u8 *data = (const __u8 *) buf;
+
+ for (i = 0; i < size; i++) {
+ crc ^= *data++;
+ crc = (crc >> 4) ^ crctab[crc & 0xf];
+ crc = (crc >> 4) ^ crctab[crc & 0xf];
+ }
+ return crc;
+}
+
+static int probe_lvm2(struct blkid_probe *probe,
+ struct blkid_magic *id __BLKID_ATTR((unused)),
+ unsigned char *buf)
+{
+ int sector = (id->bim_kboff) << 1;;
+ struct lvm2_pv_label_header *label;
+ label = (struct lvm2_pv_label_header *)buf;
+ char *p, *q, uuid[40];
+ unsigned int i, b;
+
+ /* buf is at 0k or 1k offset; find label inside */
+ if (memcmp(buf, "LABELONE", 8) == 0) {
+ label = (struct lvm2_pv_label_header *)buf;
+ } else if (memcmp(buf + 512, "LABELONE", 8) == 0) {
+ label = (struct lvm2_pv_label_header *)(buf + 512);
+ sector++;
+ } else {
+ return 1;
+ }
+
+ if (blkid_le64(label->sector_xl) != sector) {
+ DBG(DEBUG_PROBE,
+ printf("LVM2: label for sector %d found at sector %d\n",
+ blkid_le64(label->sector_xl), sector));
+ return 1;
+ }
+
+ if (lvm2_calc_crc(&label->offset_xl, LVM2_LABEL_SIZE -
+ ((void *)&label->offset_xl - (void *)label)) !=
+ blkid_le32(label->crc_xl)) {
+ DBG(DEBUG_PROBE,
+ printf("LVM2: label checksum incorrect at sector %d\n",
+ sector));
+ return 1;
+ }
+
+ for (i=0, b=1, p=uuid, q=label->pv_uuid; i <= 32; i++, b <<= 1) {
+ if (b & 0x4444440)
+ *p++ = '-';
+ *p++ = *q++;
+ }
+
+ blkid_set_tag(probe->dev, "UUID", uuid, LVM2_ID_LEN+6);
+
+ return 0;
+}
/*
* BLKID_BLK_OFFS is at least as large as the highest bim_kboff defined
* in the type_array table below + bim_kbalign.
@@ -1113,6 +1179,10 @@ static struct blkid_magic type_array[] = {
{ "crypt_LUKS", 0, 0, 6, "LUKS\xba\xbe", probe_luks },
{ "squashfs", 0, 0, 4, "sqsh", 0 },
{ "squashfs", 0, 0, 4, "hsqs", 0 },
+ { "lvm2pv", 0, 0x218, 8, "LVM2 001", probe_lvm2 },
+ { "lvm2pv", 0, 0x018, 8, "LVM2 001", probe_lvm2 },
+ { "lvm2pv", 1, 0x018, 8, "LVM2 001", probe_lvm2 },
+ { "lvm2pv", 1, 0x218, 8, "LVM2 001", probe_lvm2 },
{ NULL, 0, 0, 0, NULL, NULL }
};
diff --git a/lib/blkid/probe.h b/lib/blkid/probe.h
index acfe1195..b3cc26b9 100644
--- a/lib/blkid/probe.h
+++ b/lib/blkid/probe.h
@@ -531,6 +531,20 @@ struct hfs_mdb {
__u16 embed_blockcount;
} __attribute__((packed));
+/* this is lvm's label_header & pv_header combined. */
+
+#define LVM2_ID_LEN 32
+
+struct lvm2_pv_label_header {
+ /* label_header */
+ __u8 id[8]; /* LABELONE */
+ __u64 sector_xl; /* Sector number of this label */
+ __u32 crc_xl; /* From next field to end of sector */
+ __u32 offset_xl; /* Offset from start of struct to contents */
+ __u8 type[8]; /* LVM2 001 */
+ /* pv_header */
+ __u8 pv_uuid[LVM2_ID_LEN];
+} __attribute__ ((packed));
/*
* Byte swap functions