diff options
| author | Eric Sandeen <sandeen@redhat.com> | 2008-01-30 17:25:03 -0600 |
|---|---|---|
| committer | Theodore Ts'o <tytso@mit.edu> | 2008-02-19 08:40:15 -0500 |
| commit | a451d92f38188f7218a837a395b310354864b5a4 (patch) | |
| tree | 93bbd00f547802614d26bf33820817b0cb07343e /lib/blkid | |
| parent | 6b226c3de2aea0ae3a44a56d0322ba3a7f561886 (diff) | |
| download | android_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.c | 70 | ||||
| -rw-r--r-- | lib/blkid/probe.h | 14 |
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 |
