From: Eric Sandeen Date: Wed, 30 Jan 2008 23:25:03 +0000 (-0600) Subject: blkid: detect LVM2 physical volumes X-Git-Tag: v1.40.7~31 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=a451d92f38188f7218a837a395b310354864b5a4;p=tools%2Fe2fsprogs.git blkid: detect LVM2 physical volumes Bits liberally stolen from lvm2 userspace. Addresses-Red-Hat-Bugzilla: #409321 Signed-off-by: Eric Sandeen Signed-off-by: Theodore Ts'o --- diff --git a/lib/blkid/probe.c b/lib/blkid/probe.c index 00cf850..8f73355 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 acfe119..b3cc26b 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