]> err.no Git - util-linux/commitdiff
blkid: add Linux RAID
authorKarel Zak <kzak@redhat.com>
Tue, 9 Sep 2008 10:16:14 +0000 (12:16 +0200)
committerKarel Zak <kzak@redhat.com>
Wed, 11 Feb 2009 22:21:44 +0000 (23:21 +0100)
Signed-off-by: Karel Zak <kzak@redhat.com>
libs/blkid/src/probe.c
libs/blkid/src/probers/Makefile.am
libs/blkid/src/probers/linux_raid.c [new file with mode: 0644]
libs/blkid/src/probers/probers.h

index 4fc3b83eaa2a5f5596fb00aa2bbd9e164b111188..8f1b8ffd2ae55b5ad70c966c71e954113a2e3b11 100644 (file)
@@ -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
index 5a5bf7e5ba28c759a7ff40ea3319cadd3c0e5401..9331636c325ad085ad5572341ff5d4ff67cbdaa1 100644 (file)
@@ -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 (file)
index 0000000..41be8b7
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdint.h>
+
+#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
+};
+
+
index e5313364d0245cbd51e9183db5ac9b40c2c9fa90..83012b934d0298a0033f8e5657efdde97f1f4dee 100644 (file)
@@ -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 */