Upload Tizen:Base source
[framework/base/util-linux-ng.git] / shlibs / blkid / src / probers / linux_raid.c
1 /*
2  * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
3  *
4  * Inspired by libvolume_id by
5  *     Kay Sievers <kay.sievers@vrfy.org>
6  *
7  * This file may be redistributed under the terms of the
8  * GNU Lesser General Public License.
9  */
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <unistd.h>
13 #include <string.h>
14 #include <stdint.h>
15
16 #include "blkidP.h"
17
18 struct mdp0_super_block {
19         uint32_t        md_magic;
20         uint32_t        major_version;
21         uint32_t        minor_version;
22         uint32_t        patch_version;
23         uint32_t        gvalid_words;
24         uint32_t        set_uuid0;
25         uint32_t        ctime;
26         uint32_t        level;
27         uint32_t        size;
28         uint32_t        nr_disks;
29         uint32_t        raid_disks;
30         uint32_t        md_minor;
31         uint32_t        not_persistent;
32         uint32_t        set_uuid1;
33         uint32_t        set_uuid2;
34         uint32_t        set_uuid3;
35 };
36
37 struct mdp1_super_block {
38         uint32_t        magic;
39         uint32_t        major_version;
40         uint32_t        feature_map;
41         uint32_t        pad0;
42         uint8_t         set_uuid[16];
43         uint8_t         set_name[32];
44 };
45
46 #define MD_RESERVED_BYTES               0x10000
47 #define MD_SB_MAGIC                     0xa92b4efc
48
49 static int probe_raid0(blkid_probe pr, off_t off)
50 {
51         struct mdp0_super_block *mdp0;
52         union {
53                 uint32_t ints[4];
54                 uint8_t bytes[16];
55         } uuid;
56
57         if (pr->size < 0x10000)
58                 return -1;
59         mdp0 = (struct mdp0_super_block *)
60                         blkid_probe_get_buffer(pr,
61                                 off,
62                                 sizeof(struct mdp0_super_block));
63         if (!mdp0)
64                 return -1;
65
66         memset(uuid.ints, 0, sizeof(uuid.ints));
67
68         if (le32_to_cpu(mdp0->md_magic) == MD_SB_MAGIC) {
69                 uuid.ints[0] = swab32(mdp0->set_uuid0);
70                 if (le32_to_cpu(mdp0->minor_version >= 90)) {
71                         uuid.ints[1] = swab32(mdp0->set_uuid1);
72                         uuid.ints[2] = swab32(mdp0->set_uuid2);
73                         uuid.ints[3] = swab32(mdp0->set_uuid3);
74                 }
75                 if (blkid_probe_sprintf_version(pr, "%u.%u.%u",
76                                 le32_to_cpu(mdp0->major_version),
77                                 le32_to_cpu(mdp0->minor_version),
78                                 le32_to_cpu(mdp0->patch_version)) != 0)
79                         return -1;
80
81         } else if (be32_to_cpu(mdp0->md_magic) == MD_SB_MAGIC) {
82                 uuid.ints[0] = mdp0->set_uuid0;
83                 if (be32_to_cpu(mdp0->minor_version >= 90)) {
84                         uuid.ints[1] = mdp0->set_uuid1;
85                         uuid.ints[2] = mdp0->set_uuid2;
86                         uuid.ints[3] = mdp0->set_uuid3;
87                 }
88                 if (blkid_probe_sprintf_version(pr, "%u.%u.%u",
89                                 be32_to_cpu(mdp0->major_version),
90                                 be32_to_cpu(mdp0->minor_version),
91                                 be32_to_cpu(mdp0->patch_version)) != 0)
92                         return -1;
93         } else
94                 return -1;
95
96         if (blkid_probe_set_uuid(pr, (unsigned char *) uuid.bytes) != 0)
97                 return -1;
98
99         return 0;
100 }
101
102 static int probe_raid1(blkid_probe pr, off_t off)
103 {
104         struct mdp1_super_block *mdp1;
105
106         mdp1 = (struct mdp1_super_block *)
107                         blkid_probe_get_buffer(pr,
108                                 off,
109                                 sizeof(struct mdp1_super_block));
110         if (!mdp1)
111                 return -1;
112         if (le32_to_cpu(mdp1->magic) != MD_SB_MAGIC)
113                 return -1;
114         if (le32_to_cpu(mdp1->major_version) != 1)
115                 return -1;
116         if (blkid_probe_set_uuid(pr, (unsigned char *) mdp1->set_uuid) != 0)
117                 return -1;
118         if (blkid_probe_set_label(pr, mdp1->set_name,
119                                 sizeof(mdp1->set_name)) != 0)
120                 return -1;
121
122         return 0;
123 }
124
125 int probe_raid(blkid_probe pr, const struct blkid_idmag *mag)
126 {
127         const char *ver = NULL;
128
129         if (pr->size > MD_RESERVED_BYTES) {
130                 /* version 0 at the end of the device */
131                 uint64_t sboff = (pr->size & ~(MD_RESERVED_BYTES - 1))
132                                  - MD_RESERVED_BYTES;
133                 if (probe_raid0(pr, sboff) == 0)
134                         return 0;
135
136                 /* version 1.0 at the end of the device */
137                 sboff = (pr->size & ~(0x1000 - 1)) - 0x2000;
138                 if (probe_raid1(pr, sboff) == 0)
139                         ver = "1.0";
140         }
141
142         if (!ver) {
143                 /* version 1.1 at the start of the device */
144                 if (probe_raid1(pr, 0) == 0)
145                         ver = "1.1";
146
147                 /* version 1.2 at 4k offset from the start */
148                 else if (probe_raid1(pr, 0x1000) == 0)
149                         ver = "1.2";
150         }
151
152         if (ver) {
153                 blkid_probe_set_version(pr, ver);
154                 return 0;
155         }
156         return -1;
157 }
158
159
160 const struct blkid_idinfo linuxraid_idinfo = {
161         .name           = "linux_raid_member",
162         .usage          = BLKID_USAGE_RAID,
163         .probefunc      = probe_raid,
164         .magics         = BLKID_NONE_MAGIC
165 };
166
167