1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
|
/*
* Copyright (C) 2008 Karel Zak <kzak@redhat.com>
*
* Inspired by libvolume_id by
* Kay Sievers <kay.sievers@vrfy.org>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.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,
sizeof(struct mdp0_super_block));
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,
sizeof(struct mdp1_super_block));
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;
if (pr->size > MD_RESERVED_BYTES) {
/* version 0 at the end of the device */
uint64_t 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";
}
if (!ver) {
/* version 1.1 at the start of the device */
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,
.magics = BLKID_NONE_MAGIC
};
|