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

« back to all changes in this revision

Viewing changes to 1.0.0.rc16/lib/format/ataraid/hpt37x.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
 * Highpoint 37X ATARAID series metadata format handler.
 
3
 *
 
4
 * Copyright (C) 2004-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
/*
 
11
 * hpt37x_read(), hpt37x_group() and group_rd() profited from
 
12
 * Carl-Daniel Hailfinger's raiddetect code.
 
13
 */
 
14
#define HANDLER "hpt37x"
 
15
 
 
16
#include "internal.h"
 
17
#define FORMAT_HANDLER
 
18
#include "hpt37x.h"
 
19
 
 
20
#if     BYTE_ORDER != LITTLE_ENDIAN
 
21
#  define       DM_BYTEORDER_SWAB
 
22
#  include      <datastruct/byteorder.h>
 
23
#endif
 
24
 
 
25
static const char *handler = HANDLER;
 
26
 
 
27
/* Make up RAID set name from magic_[01] numbers */
 
28
/* FIXME: better name ? */
 
29
static size_t
 
30
_name(struct hpt37x *hpt, char *str, size_t len, unsigned int subset)
 
31
{
 
32
        const char *fmt;
 
33
 
 
34
        if (hpt->magic_0)
 
35
                fmt = (subset &&
 
36
                       (hpt->type == HPT37X_T_RAID01_RAID0 ||
 
37
                        hpt->type == HPT37X_T_RAID01_RAID1)) ?
 
38
                        "hpt37x_%u-%u" : "hpt37x_%u";
 
39
        else
 
40
                fmt = "hpt37x_SPARE";
 
41
 
 
42
        /* FIXME: hpt->order not zero-based. */
 
43
        return snprintf(str, len, fmt,
 
44
                        hpt->magic_1 ? hpt->magic_1 : hpt->magic_0, hpt->order);
 
45
}
 
46
 
 
47
static char *
 
48
name(struct lib_context *lc, struct raid_dev *rd, unsigned int subset)
 
49
{
 
50
        size_t len;
 
51
        char *ret;
 
52
        struct hpt37x *hpt = META(rd, hpt37x);
 
53
 
 
54
        if ((ret = dbg_malloc((len = _name(hpt, NULL, 0, subset) + 1)))) {
 
55
                _name(hpt, ret, len, subset);
 
56
                mk_alpha(lc, ret + HANDLER_LEN, len - HANDLER_LEN -
 
57
                         (strrchr(ret, '-') ? 3 : 1));
 
58
        } else
 
59
                log_alloc_err(lc, handler);
 
60
 
 
61
        return ret;
 
62
}
 
63
 
 
64
/*
 
65
 * Retrieve status of device.
 
66
 * FIXME: is this sufficient to cover all state ?
 
67
 */
 
68
static enum status
 
69
status(struct hpt37x *hpt)
 
70
{
 
71
        return hpt->magic == HPT37X_MAGIC_BAD ? s_broken : s_ok;
 
72
}
 
73
 
 
74
/* Neutralize disk type. */
 
75
static enum type
 
76
type(struct hpt37x *hpt)
 
77
{
 
78
        /* Mapping of HPT 37X types to generic types. */
 
79
        static struct types types[] = {
 
80
                { HPT37X_T_SINGLEDISK, t_linear },
 
81
                { HPT37X_T_SPAN, t_linear },
 
82
                { HPT37X_T_RAID0, t_raid0 },
 
83
                { HPT37X_T_RAID1, t_raid1 },
 
84
                { HPT37X_T_RAID01_RAID0, t_raid0 },
 
85
                { HPT37X_T_RAID01_RAID1, t_raid1 },
 
86
                /* FIXME: support RAID 3+5 */
 
87
                { 0, t_undef },
 
88
        };
 
89
 
 
90
        return hpt->magic_0 ?
 
91
                rd_type(types, (unsigned int) hpt->type) : t_spare;
 
92
}
 
93
 
 
94
/* Decide about ordering sequence of RAID device. */
 
95
static int
 
96
dev_sort(struct list_head *pos, struct list_head *new)
 
97
{
 
98
        return META(RD(new), hpt37x)->disk_number <
 
99
               META(RD(pos), hpt37x)->disk_number;
 
100
}
 
101
 
 
102
/* Decide about ordering sequence of RAID subset. */
 
103
static int
 
104
set_sort(struct list_head *pos, struct list_head *new)
 
105
{
 
106
        return META(RD_RS(RS(new)), hpt37x)->order <
 
107
               META(RD_RS(RS(pos)), hpt37x)->order;
 
108
}
 
109
 
 
110
/* Magic check. */
 
111
static int
 
112
check_magic(void *meta)
 
113
{
 
114
        struct hpt37x *hpt = meta;
 
115
 
 
116
        return (hpt->magic == HPT37X_MAGIC_OK ||
 
117
                hpt->magic == HPT37X_MAGIC_BAD) &&
 
118
               hpt->disk_number < 8;
 
119
}
 
120
 
 
121
/*
 
122
 * Read a Highpoint 37X RAID device.
 
123
 */
 
124
/* Endianess conversion. */
 
125
#if     BYTE_ORDER == LITTLE_ENDIAN
 
126
#  define       to_cpu  NULL
 
127
#else
 
128
static void
 
129
to_cpu(void *meta)
 
130
{
 
131
        struct hpt37x *hpt = meta;
 
132
 
 
133
        CVT32(hpt->magic);
 
134
        CVT32(hpt->magic_0);
 
135
        CVT32(hpt->magic_1);
 
136
        CVT32(hpt->order);
 
137
        CVT32(hpt->total_secs);
 
138
        CVT32(hpt->disk_mode);
 
139
        CVT32(hpt->boot_mode);
 
140
 
 
141
        /* Only convert error log entries in case we discover proper magic */
 
142
        if (check_magic(meta)) {
 
143
                struct hpt37x_errorlog *l;
 
144
 
 
145
                for (l = hpt->errorlog;
 
146
                     l < hpt->errorlog +
 
147
                     min(hpt->error_log_entries, HPT37X_MAX_ERRORLOG); l++) {
 
148
                        CVT32(l->timestamp);
 
149
                        CVT32(l->lba);
 
150
                }
 
151
        }
 
152
}
 
153
#endif
 
154
 
 
155
/* Use magic check to tell, if this is Highpoint 37x */
 
156
static int
 
157
is_hpt37x(struct lib_context *lc, struct dev_info *di, void *meta)
 
158
{
 
159
        return check_magic(meta);
 
160
}
 
161
 
 
162
static int setup_rd(struct lib_context *lc, struct raid_dev *rd,
 
163
                    struct dev_info *di, void *meta, union read_info *info);
 
164
static struct raid_dev *
 
165
hpt37x_read(struct lib_context *lc, struct dev_info *di)
 
166
{
 
167
        return read_raid_dev(lc, di, NULL,
 
168
                             sizeof(struct hpt37x), HPT37X_CONFIGOFFSET,
 
169
                             to_cpu, is_hpt37x, NULL, setup_rd, handler);
 
170
}
 
171
 
 
172
/*
 
173
 * Write a Highpoint 37X RAID device.
 
174
 */
 
175
static int
 
176
hpt37x_write(struct lib_context *lc, struct raid_dev *rd, int erase)
 
177
{
 
178
        int ret;
 
179
#if     BYTE_ORDER != LITTLE_ENDIAN
 
180
        struct hpt37x *hpt = META(rd, hpt37x);
 
181
 
 
182
        to_disk(hpt);
 
183
#endif
 
184
        ret = write_metadata(lc, handler, rd, -1, erase);
 
185
#if     BYTE_ORDER != LITTLE_ENDIAN
 
186
        to_cpu(hpt);
 
187
#endif
 
188
 
 
189
        return ret;
 
190
}
 
191
 
 
192
/*
 
193
 * Group the RAID disk into a set.
 
194
 *
 
195
 * Check device hierarchy and create sub sets appropriately.
 
196
 *
 
197
 */
 
198
static unsigned int
 
199
stride(struct hpt37x *hpt)
 
200
{
 
201
        return hpt->raid0_shift ? 1 << hpt->raid0_shift : 0;
 
202
}
 
203
 
 
204
static int
 
205
mismatch(struct lib_context *lc, struct raid_dev *rd, char magic)
 
206
{
 
207
        LOG_ERR(lc, 0, "%s: magic_%c mismatch on %s",
 
208
                handler, magic, rd->di->path);
 
209
}
 
210
 
 
211
static void
 
212
super_created(struct raid_set *ss, void *private)
 
213
{
 
214
        struct hpt37x *hpt = META(private, hpt37x);
 
215
 
 
216
        ss->type = hpt->type == HPT37X_T_RAID01_RAID0 ? t_raid1 : t_raid0;
 
217
        ss->stride = stride(hpt);
 
218
}
 
219
 
 
220
/* FIXME: handle spares in mirrors and check that types are correct. */
 
221
static int
 
222
group_rd(struct lib_context *lc, struct raid_set *rs,
 
223
         struct raid_set **ss, struct raid_dev *rd)
 
224
{
 
225
        struct hpt37x *h, *hpt = META(rd, hpt37x);
 
226
 
 
227
        if (!init_raid_set(lc, rs, rd, stride(hpt), hpt->type, handler))
 
228
                return 0;
 
229
 
 
230
        list_add_sorted(lc, &rs->devs, &rd->devs, dev_sort);
 
231
        h = DEVS(rs) ? META(RD_RS(rs), hpt37x) : NULL;
 
232
 
 
233
        switch (hpt->type) {
 
234
        case HPT37X_T_SINGLEDISK:
 
235
        case HPT37X_T_SPAN:
 
236
        case HPT37X_T_RAID0:
 
237
        case HPT37X_T_RAID1:
 
238
                if (h && h->magic_0 != hpt->magic_0)
 
239
                        return mismatch(lc, rd, '0');
 
240
 
 
241
                if (!find_set(lc, NULL, rs->name, FIND_TOP))
 
242
                        list_add_tail(&rs->list, LC_RS(lc));
 
243
 
 
244
                break;
 
245
 
 
246
        case HPT37X_T_RAID01_RAID0:
 
247
        case HPT37X_T_RAID01_RAID1:
 
248
                if (h && h->magic_1 != hpt->magic_1)
 
249
                        return mismatch(lc, rd, '1');
 
250
 
 
251
                if (!(*ss = join_superset(lc, name, super_created,
 
252
                                          set_sort, rs, rd)))
 
253
                        return 0;
 
254
        }
 
255
 
 
256
        return 1;
 
257
}
 
258
 
 
259
/*
 
260
 * Add a Highpoint RAID device to a set.
 
261
 */
 
262
static struct raid_set *
 
263
hpt37x_group(struct lib_context *lc, struct raid_dev *rd)
 
264
{
 
265
        struct raid_set *rs, *ss = NULL;
 
266
 
 
267
        if (T_SPARE(rd))
 
268
                return NULL;
 
269
 
 
270
        if ((rs = find_or_alloc_raid_set(lc, rd->name, FIND_ALL, rd,
 
271
                                         NO_LIST, NO_CREATE, NO_CREATE_ARG)))
 
272
                return group_rd(lc, rs, &ss, rd) ? (ss ? ss : rs) : NULL;
 
273
 
 
274
        return NULL;
 
275
}
 
276
 
 
277
/*
 
278
 * Check a Highpoint 37X RAID set.
 
279
 *
 
280
 * FIXME: more sanity checks.
 
281
 */
 
282
static unsigned int
 
283
devices(struct raid_dev *rd, void *context)
 
284
{
 
285
        return META(rd, hpt37x)->raid_disks;
 
286
}
 
287
 
 
288
static int
 
289
check_rd(struct lib_context *lc, struct raid_set *rs,
 
290
         struct raid_dev *rd, void *context)
 
291
{
 
292
        /*
 
293
         * FIXME: raid_disks member wrong ?
 
294
         *        (eg, Peter Jonas RAID1 metadata, 2 disks and raid_disks = 1)
 
295
         */
 
296
        return T_RAID1(rd);
 
297
}
 
298
 
 
299
static int
 
300
hpt37x_check(struct lib_context *lc, struct raid_set *rs)
 
301
{
 
302
        return check_raid_set(lc, rs, devices, NULL, check_rd, NULL, handler);
 
303
}
 
304
 
 
305
/*
 
306
 * IO error event handler.
 
307
 */
 
308
static int
 
309
event_io(struct lib_context *lc, struct event_io *e_io)
 
310
{
 
311
        struct raid_dev *rd = e_io->rd;
 
312
        struct hpt37x *hpt = META(rd, hpt37x);
 
313
 
 
314
        /* Avoid write trashing. */
 
315
        if (status(hpt) & s_broken)
 
316
                return 0;
 
317
 
 
318
        hpt->magic = HPT37X_MAGIC_BAD;
 
319
        return 1;
 
320
}
 
321
 
 
322
static struct event_handlers hpt37x_event_handlers = {
 
323
        .io = event_io,
 
324
        .rd = NULL,             /* FIXME: no device add/remove event handler yet. */
 
325
};
 
326
 
 
327
#ifdef DMRAID_NATIVE_LOG
 
328
/*
 
329
 * Log native information about an HPT37X RAID device.
 
330
 */
 
331
static void
 
332
hpt37x_log(struct lib_context *lc, struct raid_dev *rd)
 
333
{
 
334
        struct hpt37x *hpt = META(rd, hpt37x);
 
335
        struct hpt37x_errorlog *el;
 
336
 
 
337
        log_print(lc, "%s (%s):", rd->di->path, handler);
 
338
        DP("magic: 0x%x", hpt, hpt->magic);
 
339
        DP("magic_0: 0x%x", hpt, hpt->magic_0);
 
340
        DP("magic_1: 0x%x", hpt, hpt->magic_1);
 
341
        DP("order: %u", hpt, hpt->order);
 
342
        DP("raid_disks: %u", hpt, hpt->raid_disks);
 
343
        DP("raid0_shift: %u", hpt, hpt->raid0_shift);
 
344
        DP("type: %u", hpt, hpt->type);
 
345
        DP("disk_number: %u", hpt, hpt->disk_number);
 
346
        DP("total_secs: %u", hpt, hpt->total_secs);
 
347
        DP("disk_mode: 0x%x", hpt, hpt->disk_mode);
 
348
        DP("boot_mode: 0x%x", hpt, hpt->boot_mode);
 
349
        DP("boot_disk: %u", hpt, hpt->boot_disk);
 
350
        DP("boot_protect: %u", hpt, hpt->boot_protect);
 
351
        DP("error_log_entries: %u", hpt, hpt->error_log_entries);
 
352
        DP("error_log_index: %u", hpt, hpt->error_log_index);
 
353
        if (hpt->error_log_entries)
 
354
                log_print(lc, "error_log:");
 
355
 
 
356
        for (el = hpt->errorlog; el < hpt->errorlog + 32; el++) {
 
357
                if (!el->timestamp)
 
358
                        break;
 
359
 
 
360
                DP("timestamp: %u", hpt, el->timestamp);
 
361
                DP("reason: %u", hpt, el->reason);
 
362
                DP("disk: %u", hpt, el->disk);
 
363
                DP("status: %u", hpt, el->status);
 
364
                DP("sectors: %u", hpt, el->sectors);
 
365
                DP("lba: %u", hpt, el->lba);
 
366
        };
 
367
}
 
368
#endif
 
369
 
 
370
static struct dmraid_format hpt37x_format = {
 
371
        .name = HANDLER,
 
372
        .descr = "Highpoint HPT37X",
 
373
        .caps = "S,0,1,10,01",
 
374
        .format = FMT_RAID,
 
375
        .read = hpt37x_read,
 
376
        .write = hpt37x_write,
 
377
        .group = hpt37x_group,
 
378
        .check = hpt37x_check,
 
379
        .events = &hpt37x_event_handlers,
 
380
#ifdef DMRAID_NATIVE_LOG
 
381
        .log = hpt37x_log,
 
382
#endif
 
383
};
 
384
 
 
385
/* Register this format handler with the format core. */
 
386
int
 
387
register_hpt37x(struct lib_context *lc)
 
388
{
 
389
        return register_format_handler(lc, &hpt37x_format);
 
390
}
 
391
 
 
392
/* Calculate RAID device size in sectors depending on RAID type. */
 
393
static uint64_t
 
394
sectors(struct raid_dev *rd, struct hpt37x *hpt)
 
395
{
 
396
        uint64_t ret = 0;
 
397
        struct dev_info *di = rd->di;
 
398
 
 
399
        switch (rd->type) {
 
400
        case t_raid0:
 
401
                ret = hpt->total_secs / (hpt->raid_disks ? hpt->raid_disks : 1);
 
402
                break;
 
403
 
 
404
        case t_raid1:
 
405
                ret = hpt->total_secs;
 
406
                break;
 
407
 
 
408
        default:
 
409
                ret = di->sectors;
 
410
        }
 
411
 
 
412
        /* Subtract offset sectors on drives > 0. */
 
413
        return ret - rd->offset;
 
414
}
 
415
 
 
416
/* Derive the RAID device contents from the Highpoint ones. */
 
417
static int
 
418
setup_rd(struct lib_context *lc, struct raid_dev *rd,
 
419
         struct dev_info *di, void *meta, union read_info *info)
 
420
{
 
421
        struct hpt37x *hpt = meta;
 
422
 
 
423
        if (!(rd->meta_areas = alloc_meta_areas(lc, rd, handler, 1)))
 
424
                return 0;
 
425
 
 
426
        rd->meta_areas->offset = HPT37X_CONFIGOFFSET >> 9;
 
427
        rd->meta_areas->size = sizeof(*hpt);
 
428
        rd->meta_areas->area = (void *) hpt;
 
429
 
 
430
        rd->di = di;
 
431
        rd->fmt = &hpt37x_format;
 
432
 
 
433
        rd->status = status(hpt);
 
434
        rd->type = type(hpt);
 
435
 
 
436
        /* Data offset from start of device; first device is special */
 
437
        rd->offset = hpt->disk_number ? HPT37X_DATAOFFSET : 0;
 
438
        if (!(rd->sectors = sectors(rd, hpt)))
 
439
                return log_zero_sectors(lc, di->path, handler);
 
440
 
 
441
        return (rd->name = name(lc, rd, 1)) ? 1 : 0;
 
442
}