~ubuntu-branches/ubuntu/trusty/util-linux/trusty-proposed

« back to all changes in this revision

Viewing changes to libblkid/src/superblocks/linux_raid.c

  • Committer: Package Import Robot
  • Author(s): LaMont Jones
  • Date: 2011-11-03 15:38:23 UTC
  • mto: (4.5.5 sid) (1.6.4)
  • mto: This revision was merged to the branch mainline in revision 85.
  • Revision ID: package-import@ubuntu.com-20111103153823-10sx16jprzxlhkqf
ImportĀ upstreamĀ versionĀ 2.20.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 "superblocks.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
/*
 
38
 * Version-1, little-endian.
 
39
 */
 
40
struct mdp1_super_block {
 
41
        /* constant array information - 128 bytes */
 
42
        uint32_t        magic;          /* MD_SB_MAGIC: 0xa92b4efc - little endian */
 
43
        uint32_t        major_version;  /* 1 */
 
44
        uint32_t        feature_map;    /* 0 for now */
 
45
        uint32_t        pad0;           /* always set to 0 when writing */
 
46
 
 
47
        uint8_t         set_uuid[16];   /* user-space generated. */
 
48
        unsigned char   set_name[32];   /* set and interpreted by user-space */
 
49
 
 
50
        uint64_t        ctime;          /* lo 40 bits are seconds, top 24 are microseconds or 0*/
 
51
        uint32_t        level;          /* -4 (multipath), -1 (linear), 0,1,4,5 */
 
52
        uint32_t        layout;         /* only for raid5 currently */
 
53
        uint64_t        size;           /* used size of component devices, in 512byte sectors */
 
54
 
 
55
        uint32_t        chunksize;      /* in 512byte sectors */
 
56
        uint32_t        raid_disks;
 
57
        uint32_t        bitmap_offset;  /* sectors after start of superblock that bitmap starts
 
58
                                         * NOTE: signed, so bitmap can be before superblock
 
59
                                         * only meaningful of feature_map[0] is set.
 
60
                                         */
 
61
 
 
62
        /* These are only valid with feature bit '4' */
 
63
        uint32_t        new_level;      /* new level we are reshaping to                */
 
64
        uint64_t        reshape_position;       /* next address in array-space for reshape */
 
65
        uint32_t        delta_disks;    /* change in number of raid_disks               */
 
66
        uint32_t        new_layout;     /* new layout                                   */
 
67
        uint32_t        new_chunk;      /* new chunk size (bytes)                       */
 
68
        uint8_t         pad1[128-124];  /* set to 0 when written */
 
69
 
 
70
        /* constant this-device information - 64 bytes */
 
71
        uint64_t        data_offset;    /* sector start of data, often 0 */
 
72
        uint64_t        data_size;      /* sectors in this device that can be used for data */
 
73
        uint64_t        super_offset;   /* sector start of this superblock */
 
74
        uint64_t        recovery_offset;/* sectors before this offset (from data_offset) have been recovered */
 
75
        uint32_t        dev_number;     /* permanent identifier of this  device - not role in raid */
 
76
        uint32_t        cnt_corrected_read; /* number of read errors that were corrected by re-writing */
 
77
        uint8_t         device_uuid[16]; /* user-space setable, ignored by kernel */
 
78
        uint8_t         devflags;        /* per-device flags.  Only one defined...*/
 
79
        uint8_t         pad2[64-57];    /* set to 0 when writing */
 
80
 
 
81
        /* array state information - 64 bytes */
 
82
        uint64_t        utime;          /* 40 bits second, 24 btes microseconds */
 
83
        uint64_t        events;         /* incremented when superblock updated */
 
84
        uint64_t        resync_offset;  /* data before this offset (from data_offset) known to be in sync */
 
85
        uint32_t        sb_csum;        /* checksum upto dev_roles[max_dev] */
 
86
        uint32_t        max_dev;        /* size of dev_roles[] array to consider */
 
87
        uint8_t         pad3[64-32];    /* set to 0 when writing */
 
88
 
 
89
        /* device state information. Indexed by dev_number.
 
90
         * 2 bytes per device
 
91
         * Note there are no per-device state flags. State information is rolled
 
92
         * into the 'roles' value.  If a device is spare or faulty, then it doesn't
 
93
         * have a meaningful role.
 
94
         */
 
95
        uint16_t        dev_roles[0];   /* role in array, or 0xffff for a spare, or 0xfffe for faulty */
 
96
};
 
97
 
 
98
 
 
99
#define MD_RESERVED_BYTES               0x10000
 
100
#define MD_SB_MAGIC                     0xa92b4efc
 
101
 
 
102
static int probe_raid0(blkid_probe pr, blkid_loff_t off)
 
103
{
 
104
        struct mdp0_super_block *mdp0;
 
105
        union {
 
106
                uint32_t ints[4];
 
107
                uint8_t bytes[16];
 
108
        } uuid;
 
109
        uint32_t ma, mi, pa;
 
110
        uint64_t size;
 
111
 
 
112
        if (pr->size < MD_RESERVED_BYTES)
 
113
                return -1;
 
114
        mdp0 = (struct mdp0_super_block *)
 
115
                        blkid_probe_get_buffer(pr,
 
116
                                off,
 
117
                                sizeof(struct mdp0_super_block));
 
118
        if (!mdp0)
 
119
                return -1;
 
120
 
 
121
        memset(uuid.ints, 0, sizeof(uuid.ints));
 
122
 
 
123
        if (le32_to_cpu(mdp0->md_magic) == MD_SB_MAGIC) {
 
124
                uuid.ints[0] = swab32(mdp0->set_uuid0);
 
125
                if (le32_to_cpu(mdp0->minor_version) >= 90) {
 
126
                        uuid.ints[1] = swab32(mdp0->set_uuid1);
 
127
                        uuid.ints[2] = swab32(mdp0->set_uuid2);
 
128
                        uuid.ints[3] = swab32(mdp0->set_uuid3);
 
129
                }
 
130
                ma = le32_to_cpu(mdp0->major_version);
 
131
                mi = le32_to_cpu(mdp0->minor_version);
 
132
                pa = le32_to_cpu(mdp0->patch_version);
 
133
                size = le32_to_cpu(mdp0->size);
 
134
 
 
135
        } else if (be32_to_cpu(mdp0->md_magic) == MD_SB_MAGIC) {
 
136
                uuid.ints[0] = mdp0->set_uuid0;
 
137
                if (be32_to_cpu(mdp0->minor_version) >= 90) {
 
138
                        uuid.ints[1] = mdp0->set_uuid1;
 
139
                        uuid.ints[2] = mdp0->set_uuid2;
 
140
                        uuid.ints[3] = mdp0->set_uuid3;
 
141
                }
 
142
                ma = be32_to_cpu(mdp0->major_version);
 
143
                mi = be32_to_cpu(mdp0->minor_version);
 
144
                pa = be32_to_cpu(mdp0->patch_version);
 
145
                size = be32_to_cpu(mdp0->size);
 
146
        } else
 
147
                return 1;
 
148
 
 
149
        size <<= 10;    /* convert KiB to bytes */
 
150
 
 
151
        if (pr->size < 0 || (uint64_t) pr->size < size + MD_RESERVED_BYTES)
 
152
                /* device is too small */
 
153
                return 1;
 
154
 
 
155
        if (off < 0 || (uint64_t) off < size)
 
156
                /* no space before superblock */
 
157
                return 1;
 
158
 
 
159
        /*
 
160
         * Check for collisions between RAID and partition table
 
161
         *
 
162
         * For example the superblock is at the end of the last partition, it's
 
163
         * the same possition as at the end of the disk...
 
164
         */
 
165
        if ((S_ISREG(pr->mode) || blkid_probe_is_wholedisk(pr)) &&
 
166
            blkid_probe_is_covered_by_pt(pr,
 
167
                        off - size,                             /* min. start  */
 
168
                        size + MD_RESERVED_BYTES)) {            /* min. length */
 
169
 
 
170
                /* ignore this superblock, it's within any partition and
 
171
                 * we are working with whole-disk now */
 
172
                return 1;
 
173
        }
 
174
 
 
175
        if (blkid_probe_sprintf_version(pr, "%u.%u.%u", ma, mi, pa) != 0)
 
176
                return -1;
 
177
        if (blkid_probe_set_uuid(pr, (unsigned char *) uuid.bytes) != 0)
 
178
                return -1;
 
179
        if (blkid_probe_set_magic(pr, off, sizeof(mdp0->md_magic),
 
180
                                (unsigned char *) &mdp0->md_magic))
 
181
                return -1;
 
182
        return 0;
 
183
}
 
184
 
 
185
static int probe_raid1(blkid_probe pr, off_t off)
 
186
{
 
187
        struct mdp1_super_block *mdp1;
 
188
 
 
189
        mdp1 = (struct mdp1_super_block *)
 
190
                        blkid_probe_get_buffer(pr,
 
191
                                off,
 
192
                                sizeof(struct mdp1_super_block));
 
193
        if (!mdp1)
 
194
                return -1;
 
195
        if (le32_to_cpu(mdp1->magic) != MD_SB_MAGIC)
 
196
                return -1;
 
197
        if (le32_to_cpu(mdp1->major_version) != 1U)
 
198
                return -1;
 
199
        if (le64_to_cpu(mdp1->super_offset) != (uint64_t) off >> 9)
 
200
                return -1;
 
201
        if (blkid_probe_set_uuid(pr, (unsigned char *) mdp1->set_uuid) != 0)
 
202
                return -1;
 
203
        if (blkid_probe_set_uuid_as(pr,
 
204
                        (unsigned char *) mdp1->device_uuid, "UUID_SUB") != 0)
 
205
                return -1;
 
206
        if (blkid_probe_set_label(pr, mdp1->set_name,
 
207
                                sizeof(mdp1->set_name)) != 0)
 
208
                return -1;
 
209
        if (blkid_probe_set_magic(pr, off, sizeof(mdp1->magic),
 
210
                                (unsigned char *) &mdp1->magic))
 
211
                return -1;
 
212
        return 0;
 
213
}
 
214
 
 
215
int probe_raid(blkid_probe pr,
 
216
                const struct blkid_idmag *mag __attribute__((__unused__)))
 
217
{
 
218
        const char *ver = NULL;
 
219
 
 
220
        if (pr->size > MD_RESERVED_BYTES) {
 
221
                /* version 0 at the end of the device */
 
222
                uint64_t sboff = (pr->size & ~(MD_RESERVED_BYTES - 1))
 
223
                                 - MD_RESERVED_BYTES;
 
224
                if (probe_raid0(pr, sboff) == 0)
 
225
                        return 0;
 
226
 
 
227
                /* version 1.0 at the end of the device */
 
228
                sboff = (pr->size & ~(0x1000 - 1)) - 0x2000;
 
229
                if (probe_raid1(pr, sboff) == 0)
 
230
                        ver = "1.0";
 
231
        }
 
232
 
 
233
        if (!ver) {
 
234
                /* version 1.1 at the start of the device */
 
235
                if (probe_raid1(pr, 0) == 0)
 
236
                        ver = "1.1";
 
237
 
 
238
                /* version 1.2 at 4k offset from the start */
 
239
                else if (probe_raid1(pr, 0x1000) == 0)
 
240
                        ver = "1.2";
 
241
        }
 
242
 
 
243
        if (ver) {
 
244
                blkid_probe_set_version(pr, ver);
 
245
                return 0;
 
246
        }
 
247
        return -1;
 
248
}
 
249
 
 
250
 
 
251
const struct blkid_idinfo linuxraid_idinfo = {
 
252
        .name           = "linux_raid_member",
 
253
        .usage          = BLKID_USAGE_RAID,
 
254
        .probefunc      = probe_raid,
 
255
        .magics         = BLKID_NONE_MAGIC
 
256
};
 
257
 
 
258