~psusi/ubuntu/precise/dmraid/fix-gpt

« back to all changes in this revision

Viewing changes to 1.0.0.rc16/lib/format/ataraid/jm.c

  • Committer: Bazaar Package Importer
  • Author(s): Artur Rona
  • Date: 2010-02-04 21:34:22 UTC
  • mfrom: (1.1.4 upstream) (2.4.3 sid)
  • Revision ID: james.westby@ubuntu.com-20100204213422-tdag8lcxpr7ahmg4
Tags: 1.0.0.rc16-3ubuntu1
* Merge from debian testing. (LP: #503136)  Remaining changes:
  - debian/dmraid-activate: Remove the special-casing of the root
    device which breaks in many situations and leaves the raw devices
    exposed. This was introduced in Debian to accommodate some broken
    configurations which wanted to access "partitions" on the raid
    raw devices. In Ubuntu, broken configurations has not been supported.
  - debian/dmraid.postinst: Comment out "udevadm trigger" call in postinst
    for now as it has severeconsequences when mountall is installed
    (clears /tmp).  If dmraid is installed, then presumably the important
    system devices are up and one canbe bothered with a reboot to take 
    the change into account. Let update-initramfs flag the system
    as needing a reboot.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * JMicron metadata format handler.
 
3
 *
 
4
 * Copyright (C) 2006-2008  Heinz Mauelshagen, Red Hat GmbH.
 
5
 *                          All rights reserved.
 
6
 *
 
7
 * See file LICENSE at the top of this source tree for license information.
 
8
 */
 
9
 
 
10
#define HANDLER "jmicron"
 
11
 
 
12
#include "internal.h"
 
13
#define FORMAT_HANDLER
 
14
#include "jm.h"
 
15
 
 
16
#if     BYTE_ORDER != LITTLE_ENDIAN
 
17
#  define       DM_BYTEORDER_SWAB
 
18
#  include      <datastruct/byteorder.h>
 
19
#endif
 
20
 
 
21
static const char *handler = HANDLER;
 
22
 
 
23
/* RAID set name */
 
24
static int member(struct jm *jm);
 
25
static char *
 
26
name(struct lib_context *lc, struct raid_dev *rd, unsigned int subset)
 
27
{
 
28
        size_t i, len;
 
29
        struct jm *jm = META(rd, jm);
 
30
        char *ret, *name = (char *) jm->name;
 
31
        char buf[JM_NAME_LEN + 1] = { '\0' };
 
32
 
 
33
        /* Sanitize name, make sure it's null terminated */
 
34
        strncpy(buf, name, JM_NAME_LEN);
 
35
        while (i && isspace(buf[i])) {
 
36
                name[i]='\0';
 
37
                buf[i]='\0';
 
38
                --i;
 
39
        }
 
40
 
 
41
        len = strlen(buf) + sizeof(HANDLER) + (jm->mode == JM_T_RAID01 ? 3 : 2);
 
42
        if ((ret = dbg_malloc(len))) {
 
43
                if (jm->mode == JM_T_RAID01 && subset)
 
44
                        sprintf(buf, "-%u", member(jm) / 2);
 
45
                else
 
46
                        *buf = 0;
 
47
 
 
48
                sprintf(ret, "%s_%s%s", handler, name, buf);
 
49
        }
 
50
 
 
51
        return ret;
 
52
}
 
53
 
 
54
/*
 
55
 * Retrieve status of device.
 
56
 * FIXME: is this sufficient to cover all state ?
 
57
 */
 
58
static enum status
 
59
status(struct jm *jm)
 
60
{
 
61
        return jm->attribute & ~(JM_MOUNT | JM_BOOTABLE | JM_BADSEC | JM_ACTIVE
 
62
                                 | JM_UNSYNC | JM_NEWEST) ? s_broken : s_ok;
 
63
}
 
64
 
 
65
/* Neutralize disk type */
 
66
static enum type
 
67
type(struct jm *jm)
 
68
{
 
69
        /* Mapping of JM types to generic types */
 
70
        static struct types types[] = {
 
71
                { JM_T_JBOD, t_linear },
 
72
                { JM_T_RAID0, t_raid0 },
 
73
                { JM_T_RAID01, t_raid1 },
 
74
                { JM_T_RAID1, t_raid1 },
 
75
                { 0, t_undef },
 
76
        };
 
77
 
 
78
        return rd_type(types, (unsigned int) jm->mode);
 
79
}
 
80
 
 
81
/* Calculate checksum on metadata */
 
82
static int
 
83
checksum(struct jm *jm)
 
84
{
 
85
        int count = 64;
 
86
        uint16_t *p = (uint16_t *) jm, sum = 0;
 
87
 
 
88
        while (count--)
 
89
                sum += *p++;
 
90
 
 
91
        /* FIXME: shouldn't this be one value only ? */
 
92
        return !sum || sum == 1;
 
93
}
 
94
 
 
95
static inline unsigned int
 
96
segment(uint32_t m)
 
97
{
 
98
        return (unsigned int) (m & JM_SEG_MASK);
 
99
}
 
100
 
 
101
static inline unsigned int
 
102
disk(unsigned int m)
 
103
{
 
104
        return (unsigned int) (m & JM_HDD_MASK);
 
105
}
 
106
 
 
107
static int
 
108
member(struct jm *jm)
 
109
{
 
110
        unsigned int i = JM_MEMBERS;
 
111
 
 
112
        while (i--) {
 
113
                if (disk(jm->member[i]) == disk(jm->identity))
 
114
                        return i;
 
115
        }
 
116
 
 
117
        return -1;
 
118
}
 
119
 
 
120
/* Decide about ordering sequence of RAID device. */
 
121
static int
 
122
dev_sort(struct list_head *pos, struct list_head *new)
 
123
{
 
124
        return member(META(RD(new), jm)) < member(META(RD(pos), jm));
 
125
}
 
126
 
 
127
/* Decide about ordering sequence of RAID subset. */
 
128
static int
 
129
set_sort(struct list_head *pos, struct list_head *new)
 
130
{
 
131
        return member(META(RD_RS(RS(pos)), jm)) > 1;
 
132
}
 
133
 
 
134
static unsigned int
 
135
stride(unsigned int shift)
 
136
{
 
137
        return 1 << (shift + 1);
 
138
}
 
139
 
 
140
static void
 
141
super_created(struct raid_set *super, void *private)
 
142
{
 
143
        super->type = t_raid0;
 
144
        super->stride = stride(META((private), jm)->block);
 
145
}
 
146
 
 
147
/*
 
148
 * Group the RAID disk into a JM set.
 
149
 *
 
150
 * Check device hierarchy and create super set appropriately.
 
151
 */
 
152
static int
 
153
group_rd(struct lib_context *lc, struct raid_set *rs,
 
154
         struct raid_set **ss, struct raid_dev *rd)
 
155
{
 
156
        struct jm *jm = META(rd, jm);
 
157
 
 
158
        if (!init_raid_set(lc, rs, rd, stride(jm->block), jm->mode, handler))
 
159
                return 0;
 
160
 
 
161
        list_add_sorted(lc, &rs->devs, &rd->devs, dev_sort);
 
162
 
 
163
        switch (jm->mode) {
 
164
        case JM_T_JBOD:
 
165
        case JM_T_RAID0:
 
166
        case JM_T_RAID1:
 
167
                if (!find_set(lc, NULL, rs->name, FIND_TOP))
 
168
                        list_add_tail(&rs->list, LC_RS(lc));
 
169
                break;
 
170
 
 
171
        case JM_T_RAID01:
 
172
                if (!(*ss = join_superset(lc, name, super_created,
 
173
                                          set_sort, rs, rd)))
 
174
                        return 0;
 
175
        }
 
176
 
 
177
        return 1;
 
178
}
 
179
 
 
180
/*
 
181
 * Add a JMicron RAID device to a set.
 
182
 */
 
183
static struct raid_set *
 
184
jm_group(struct lib_context *lc, struct raid_dev *rd)
 
185
{
 
186
        struct raid_set *rs, *ss = NULL;
 
187
 
 
188
        if (T_SPARE(rd))
 
189
                return NULL;
 
190
 
 
191
        if ((rs = find_or_alloc_raid_set(lc, rd->name, FIND_ALL, rd,
 
192
                                         NO_LIST, NO_CREATE, NO_CREATE_ARG)))
 
193
                return group_rd(lc, rs, &ss, rd) ? (ss ? ss : rs) : NULL;
 
194
 
 
195
        return NULL;
 
196
}
 
197
 
 
198
/*
 
199
 * Read a JMicron RAID device.
 
200
 */
 
201
/* Endianess conversion. */
 
202
#if     BYTE_ORDER == LITTLE_ENDIAN
 
203
#  define       to_cpu  NULL
 
204
#else
 
205
static void
 
206
to_cpu(void *meta)
 
207
{
 
208
        unsigned int i;
 
209
        struct jm *jm = meta;
 
210
 
 
211
        CVT16(jm->version);
 
212
        CVT16(jm->checksum);
 
213
        CVT32(jm->identity);
 
214
 
 
215
        CVT32(jm->segment.base);
 
216
        CVT32(jm->segment.range);
 
217
        CVT16(jm->segment.range2);
 
218
 
 
219
        CVT16(jm->attribute);
 
220
 
 
221
        for (i = 0; i < JM_SPARES; i++)
 
222
                CVT32(jm->spare[i]);
 
223
 
 
224
        for (i = 0; i < JM_MEMBERS; i++)
 
225
                CVT32(jm->member[i]);
 
226
}
 
227
#endif
 
228
 
 
229
/* Magic check. */
 
230
static int
 
231
is_jm(struct lib_context *lc, struct dev_info *di, void *meta)
 
232
{
 
233
        struct jm *jm = meta;
 
234
 
 
235
        return !strncmp((const char *) jm->signature,
 
236
                        JM_SIGNATURE, JM_SIGNATURE_LEN) &&
 
237
               checksum(jm);
 
238
}
 
239
 
 
240
static int setup_rd(struct lib_context *lc, struct raid_dev *rd,
 
241
                    struct dev_info *di, void *meta, union read_info *info);
 
242
static struct raid_dev *
 
243
jm_read(struct lib_context *lc, struct dev_info *di)
 
244
{
 
245
        return read_raid_dev(lc, di, NULL,
 
246
                             sizeof(struct jm), JM_CONFIGOFFSET,
 
247
                             to_cpu, is_jm, NULL, setup_rd, handler);
 
248
}
 
249
 
 
250
/*
 
251
 * Write a JMicron RAID device.
 
252
 */
 
253
static int
 
254
jm_write(struct lib_context *lc, struct raid_dev *rd, int erase)
 
255
{
 
256
        int ret;
 
257
#if     BYTE_ORDER != LITTLE_ENDIAN
 
258
        struct jm *jm = META(rd, jm);
 
259
 
 
260
        to_disk(jm);
 
261
#endif
 
262
        ret = write_metadata(lc, handler, rd, -1, erase);
 
263
#if     BYTE_ORDER != LITTLE_ENDIAN
 
264
        to_cpu(jm);
 
265
#endif
 
266
        return ret;
 
267
}
 
268
 
 
269
/*
 
270
 * Check a JMicron RAID set.
 
271
 *
 
272
 * FIXME: more sanity checks.
 
273
 */
 
274
static unsigned int
 
275
devices(struct raid_dev *rd, void *context)
 
276
{
 
277
        unsigned int r = JM_MEMBERS;
 
278
        struct jm *jm = META(rd, jm);
 
279
 
 
280
        while (r-- && !jm->member[r]);
 
281
        return ++r;
 
282
}
 
283
 
 
284
static int
 
285
jm_check(struct lib_context *lc, struct raid_set *rs)
 
286
{
 
287
        return check_raid_set(lc, rs, devices, NULL,
 
288
                              NO_CHECK_RD, NULL, handler);
 
289
}
 
290
 
 
291
/*
 
292
 * IO error event handler.
 
293
 */
 
294
static int
 
295
event_io(struct lib_context *lc, struct event_io *e_io)
 
296
{
 
297
        struct raid_dev *rd = e_io->rd;
 
298
        struct jm *jm = META(rd, jm);
 
299
 
 
300
        /* Avoid write trashing. */
 
301
        if (S_BROKEN(status(jm)))
 
302
                return 0;
 
303
 
 
304
        jm->checksum = 1;       /* FIXME: how to flag a JMicron disk bad? */
 
305
        return 1;
 
306
}
 
307
 
 
308
static struct event_handlers jm_event_handlers = {
 
309
        .io = event_io,
 
310
        .rd = NULL,             /* FIXME: no device add/remove event handler yet. */
 
311
};
 
312
 
 
313
#ifdef DMRAID_NATIVE_LOG
 
314
/*
 
315
 * Log native information about an JM RAID device.
 
316
 */
 
317
static void
 
318
jm_log(struct lib_context *lc, struct raid_dev *rd)
 
319
{
 
320
        unsigned int i;
 
321
        struct jm *jm = META(rd, jm);
 
322
 
 
323
        log_print(lc, "%s (%s):", rd->di->path, handler);
 
324
        P("signature: %c%c", jm, jm->signature,
 
325
          jm->signature[0], jm->signature[1]);
 
326
        P("version: %u%u", jm, jm->version,
 
327
          JM_MAJOR_VERSION(jm), JM_MINOR_VERSION(jm));
 
328
        DP("checksum: %u", jm, jm->checksum);
 
329
        DP("identity: 0x%x", jm, jm->identity);
 
330
        DP("base: %u", jm, jm->segment.base);
 
331
        DP("range: %u", jm, jm->segment.range);
 
332
        DP("range2: %u", jm, jm->segment.range2);
 
333
        DP("name: \"%s\"", jm, jm->name);
 
334
        DP("name: %u", jm, jm->mode);
 
335
        DP("block: %u", jm, jm->block);
 
336
        DP("attribute: %u", jm, jm->attribute);
 
337
 
 
338
        for (i = 0; i < JM_SPARES; i++)
 
339
                P2("spare[%d]: 0x%x", jm, i, jm->spare[i]);
 
340
 
 
341
        for (i = 0; i < JM_MEMBERS; i++)
 
342
                P2("member[%d]: 0x%x", jm, i, jm->member[i]);
 
343
}
 
344
#endif
 
345
 
 
346
static struct dmraid_format jm_format = {
 
347
        .name = HANDLER,
 
348
        .descr = "JMicron ATARAID",
 
349
        .caps = "S,0,1",
 
350
        .format = FMT_RAID,
 
351
        .read = jm_read,
 
352
        .write = jm_write,
 
353
        .group = jm_group,
 
354
        .check = jm_check,
 
355
        .events = &jm_event_handlers,
 
356
#ifdef DMRAID_NATIVE_LOG
 
357
        .log = jm_log,
 
358
#endif
 
359
};
 
360
 
 
361
/* Register this format handler with the format core. */
 
362
int
 
363
register_jm(struct lib_context *lc)
 
364
{
 
365
        return register_format_handler(lc, &jm_format);
 
366
}
 
367
 
 
368
/* Calculate RAID device size in sectors depending on RAID type. */
 
369
static inline uint64_t
 
370
sectors(struct jm *jm)
 
371
{
 
372
        /* range * 32MB[sectors] + range2 */
 
373
        return jm->segment.range * 32 * 2048 + jm->segment.range2;
 
374
}
 
375
 
 
376
/* Set the RAID device contents up derived from the JMicron ones */
 
377
static int
 
378
setup_rd(struct lib_context *lc, struct raid_dev *rd,
 
379
         struct dev_info *di, void *meta, union read_info *info)
 
380
{
 
381
        struct jm *jm = meta;
 
382
 
 
383
        if (!(rd->meta_areas = alloc_meta_areas(lc, rd, handler, 1)))
 
384
                return 0;
 
385
 
 
386
        rd->meta_areas->offset = JM_CONFIGOFFSET >> 9;
 
387
        rd->meta_areas->size = sizeof(*jm);
 
388
        rd->meta_areas->area = (void *) jm;
 
389
 
 
390
        rd->di = di;
 
391
        rd->fmt = &jm_format;
 
392
 
 
393
        rd->status = status(jm);
 
394
        rd->type = type(jm);
 
395
 
 
396
        rd->offset = jm->segment.base;
 
397
        if (!(rd->sectors = sectors(jm)))
 
398
                return log_zero_sectors(lc, di->path, handler);
 
399
 
 
400
        return (rd->name = name(lc, rd, 1)) ? 1 : 0;
 
401
}