From 8ccb81be32fd33a3f711cb361ac35e833cf5949f Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Tue, 9 Sep 2008 12:16:14 +0200 Subject: [PATCH] blkid: add Linux RAID Signed-off-by: Karel Zak --- libs/blkid/src/probe.c | 3 +- libs/blkid/src/probers/Makefile.am | 3 +- libs/blkid/src/probers/linux_raid.c | 165 ++++++++++++++++++++++++++++ libs/blkid/src/probers/probers.h | 1 + 4 files changed, 170 insertions(+), 2 deletions(-) create mode 100644 libs/blkid/src/probers/linux_raid.c diff --git a/libs/blkid/src/probe.c b/libs/blkid/src/probe.c index 4fc3b83e..8f1b8ffd 100644 --- a/libs/blkid/src/probe.c +++ b/libs/blkid/src/probe.c @@ -46,7 +46,8 @@ static const struct blkid_idinfo *idinfos[] = &nvraid_idinfo, &pdcraid_idinfo, &silraid_idinfo, - &viaraid_idinfo + &viaraid_idinfo, + &linuxraid_idinfo }; #ifndef ARRAY_SIZE diff --git a/libs/blkid/src/probers/Makefile.am b/libs/blkid/src/probers/Makefile.am index 5a5bf7e5..9331636c 100644 --- a/libs/blkid/src/probers/Makefile.am +++ b/libs/blkid/src/probers/Makefile.am @@ -15,6 +15,7 @@ libprobers_a_SOURCES = probers.h \ nvidia_raid.c \ promise_raid.c \ silicon_raid.c \ - via_raid.c + via_raid.c \ + linux_raid.c all-local: $(lib_LIBRARIES) diff --git a/libs/blkid/src/probers/linux_raid.c b/libs/blkid/src/probers/linux_raid.c new file mode 100644 index 00000000..41be8b76 --- /dev/null +++ b/libs/blkid/src/probers/linux_raid.c @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2008 Karel Zak + * Copyright (C) 2004 Kay Sievers + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "blkidP.h" + +struct mdp0_super_block { + uint32_t md_magic; + uint32_t major_version; + uint32_t minor_version; + uint32_t patch_version; + uint32_t gvalid_words; + uint32_t set_uuid0; + uint32_t ctime; + uint32_t level; + uint32_t size; + uint32_t nr_disks; + uint32_t raid_disks; + uint32_t md_minor; + uint32_t not_persistent; + uint32_t set_uuid1; + uint32_t set_uuid2; + uint32_t set_uuid3; +}; + +struct mdp1_super_block { + uint32_t magic; + uint32_t major_version; + uint32_t feature_map; + uint32_t pad0; + uint8_t set_uuid[16]; + uint8_t set_name[32]; +}; + +#define MD_RESERVED_BYTES 0x10000 +#define MD_SB_MAGIC 0xa92b4efc + +static int probe_raid0(blkid_probe pr, off_t off) +{ + struct mdp0_super_block *mdp0; + union { + uint32_t ints[4]; + uint8_t bytes[16]; + } uuid; + + if (pr->size < 0x10000) + return -1; + mdp0 = (struct mdp0_super_block *) + blkid_probe_get_buffer(pr, off, 0x800); + if (!mdp0) + return -1; + + memset(uuid.ints, 0, sizeof(uuid.ints)); + + if (le32_to_cpu(mdp0->md_magic) == MD_SB_MAGIC) { + uuid.ints[0] = swab32(mdp0->set_uuid0); + if (le32_to_cpu(mdp0->minor_version >= 90)) { + uuid.ints[1] = swab32(mdp0->set_uuid1); + uuid.ints[2] = swab32(mdp0->set_uuid2); + uuid.ints[3] = swab32(mdp0->set_uuid3); + } + if (blkid_probe_sprintf_version(pr, "%u.%u.%u", + le32_to_cpu(mdp0->major_version), + le32_to_cpu(mdp0->minor_version), + le32_to_cpu(mdp0->patch_version)) != 0) + return -1; + + } else if (be32_to_cpu(mdp0->md_magic) == MD_SB_MAGIC) { + uuid.ints[0] = mdp0->set_uuid0; + if (be32_to_cpu(mdp0->minor_version >= 90)) { + uuid.ints[1] = mdp0->set_uuid1; + uuid.ints[2] = mdp0->set_uuid2; + uuid.ints[3] = mdp0->set_uuid3; + } + if (blkid_probe_sprintf_version(pr, "%u.%u.%u", + be32_to_cpu(mdp0->major_version), + be32_to_cpu(mdp0->minor_version), + be32_to_cpu(mdp0->patch_version)) != 0) + return -1; + } else + return -1; + + if (blkid_probe_set_uuid(pr, (unsigned char *) uuid.bytes) != 0) + return -1; + + return 0; +} + +static int probe_raid1(blkid_probe pr, off_t off) +{ + struct mdp1_super_block *mdp1; + + mdp1 = (struct mdp1_super_block *) + blkid_probe_get_buffer(pr, off, 0x800); + if (!mdp1) + return -1; + if (le32_to_cpu(mdp1->magic) != MD_SB_MAGIC) + return -1; + if (le32_to_cpu(mdp1->major_version) != 1) + return -1; + if (blkid_probe_set_uuid(pr, (unsigned char *) mdp1->set_uuid) != 0) + return -1; + if (blkid_probe_set_label(pr, mdp1->set_name, sizeof(mdp1->set_name)) != 0) + return -1; + + return 0; +} + +int probe_raid(blkid_probe pr, const struct blkid_idmag *mag) +{ + const char *ver = NULL; + uint64_t sboff; + + /* version 0 at the end of the device */ + sboff = (pr->size & ~(MD_RESERVED_BYTES - 1)) - MD_RESERVED_BYTES; + if (probe_raid0(pr, sboff) == 0) + return 0; + + /* version 1.0 at the end of the device */ + sboff = (pr->size & ~(0x1000 - 1)) - 0x2000; + if (probe_raid1(pr, sboff) == 0) + ver = "1.0"; + + /* version 1.1 at the start of the device */ + else if (probe_raid1(pr, 0) == 0) + ver = "1.1"; + + /* version 1.2 at 4k offset from the start */ + else if (probe_raid1(pr, 0x1000) == 0) + ver = "1.2"; + + if (ver) { + blkid_probe_set_version(pr, ver); + return 0; + } + return -1; +} + + +const struct blkid_idinfo linuxraid_idinfo = { + .name = "linux_raid_member", + .usage = BLKID_USAGE_RAID, + .probefunc = probe_raid +}; + + diff --git a/libs/blkid/src/probers/probers.h b/libs/blkid/src/probers/probers.h index e5313364..83012b93 100644 --- a/libs/blkid/src/probers/probers.h +++ b/libs/blkid/src/probers/probers.h @@ -27,5 +27,6 @@ extern const struct blkid_idinfo nvraid_idinfo; extern const struct blkid_idinfo pdcraid_idinfo; extern const struct blkid_idinfo silraid_idinfo; extern const struct blkid_idinfo viaraid_idinfo; +extern const struct blkid_idinfo linuxraid_idinfo; #endif /* _BLKID_PROBE_H */ -- 2.39.5