2
* Highpoint 37X ATARAID series metadata format handler.
4
* Copyright (C) 2004-2008 Heinz Mauelshagen, Red Hat GmbH.
7
* See file LICENSE at the top of this source tree for license information.
11
* hpt37x_read(), hpt37x_group() and group_rd() profited from
12
* Carl-Daniel Hailfinger's raiddetect code.
14
#define HANDLER "hpt37x"
17
#define FORMAT_HANDLER
20
#if BYTE_ORDER != LITTLE_ENDIAN
21
# define DM_BYTEORDER_SWAB
22
# include <datastruct/byteorder.h>
25
static const char *handler = HANDLER;
27
/* Make up RAID set name from magic_[01] numbers */
28
/* FIXME: better name ? */
30
_name(struct hpt37x *hpt, char *str, size_t len, unsigned int subset)
36
(hpt->type == HPT37X_T_RAID01_RAID0 ||
37
hpt->type == HPT37X_T_RAID01_RAID1)) ?
38
"hpt37x_%u-%u" : "hpt37x_%u";
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);
48
name(struct lib_context *lc, struct raid_dev *rd, unsigned int subset)
52
struct hpt37x *hpt = META(rd, hpt37x);
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));
59
log_alloc_err(lc, handler);
65
* Retrieve status of device.
66
* FIXME: is this sufficient to cover all state ?
69
status(struct hpt37x *hpt)
71
return hpt->magic == HPT37X_MAGIC_BAD ? s_broken : s_ok;
74
/* Neutralize disk type. */
76
type(struct hpt37x *hpt)
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 */
91
rd_type(types, (unsigned int) hpt->type) : t_spare;
94
/* Decide about ordering sequence of RAID device. */
96
dev_sort(struct list_head *pos, struct list_head *new)
98
return META(RD(new), hpt37x)->disk_number <
99
META(RD(pos), hpt37x)->disk_number;
102
/* Decide about ordering sequence of RAID subset. */
104
set_sort(struct list_head *pos, struct list_head *new)
106
return META(RD_RS(RS(new)), hpt37x)->order <
107
META(RD_RS(RS(pos)), hpt37x)->order;
112
check_magic(void *meta)
114
struct hpt37x *hpt = meta;
116
return (hpt->magic == HPT37X_MAGIC_OK ||
117
hpt->magic == HPT37X_MAGIC_BAD) &&
118
hpt->disk_number < 8;
122
* Read a Highpoint 37X RAID device.
124
/* Endianess conversion. */
125
#if BYTE_ORDER == LITTLE_ENDIAN
131
struct hpt37x *hpt = meta;
137
CVT32(hpt->total_secs);
138
CVT32(hpt->disk_mode);
139
CVT32(hpt->boot_mode);
141
/* Only convert error log entries in case we discover proper magic */
142
if (check_magic(meta)) {
143
struct hpt37x_errorlog *l;
145
for (l = hpt->errorlog;
147
min(hpt->error_log_entries, HPT37X_MAX_ERRORLOG); l++) {
155
/* Use magic check to tell, if this is Highpoint 37x */
157
is_hpt37x(struct lib_context *lc, struct dev_info *di, void *meta)
159
return check_magic(meta);
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)
167
return read_raid_dev(lc, di, NULL,
168
sizeof(struct hpt37x), HPT37X_CONFIGOFFSET,
169
to_cpu, is_hpt37x, NULL, setup_rd, handler);
173
* Write a Highpoint 37X RAID device.
176
hpt37x_write(struct lib_context *lc, struct raid_dev *rd, int erase)
179
#if BYTE_ORDER != LITTLE_ENDIAN
180
struct hpt37x *hpt = META(rd, hpt37x);
184
ret = write_metadata(lc, handler, rd, -1, erase);
185
#if BYTE_ORDER != LITTLE_ENDIAN
193
* Group the RAID disk into a set.
195
* Check device hierarchy and create sub sets appropriately.
199
stride(struct hpt37x *hpt)
201
return hpt->raid0_shift ? 1 << hpt->raid0_shift : 0;
205
mismatch(struct lib_context *lc, struct raid_dev *rd, char magic)
207
LOG_ERR(lc, 0, "%s: magic_%c mismatch on %s",
208
handler, magic, rd->di->path);
212
super_created(struct raid_set *ss, void *private)
214
struct hpt37x *hpt = META(private, hpt37x);
216
ss->type = hpt->type == HPT37X_T_RAID01_RAID0 ? t_raid1 : t_raid0;
217
ss->stride = stride(hpt);
220
/* FIXME: handle spares in mirrors and check that types are correct. */
222
group_rd(struct lib_context *lc, struct raid_set *rs,
223
struct raid_set **ss, struct raid_dev *rd)
225
struct hpt37x *h, *hpt = META(rd, hpt37x);
227
if (!init_raid_set(lc, rs, rd, stride(hpt), hpt->type, handler))
230
list_add_sorted(lc, &rs->devs, &rd->devs, dev_sort);
231
h = DEVS(rs) ? META(RD_RS(rs), hpt37x) : NULL;
234
case HPT37X_T_SINGLEDISK:
238
if (h && h->magic_0 != hpt->magic_0)
239
return mismatch(lc, rd, '0');
241
if (!find_set(lc, NULL, rs->name, FIND_TOP))
242
list_add_tail(&rs->list, LC_RS(lc));
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');
251
if (!(*ss = join_superset(lc, name, super_created,
260
* Add a Highpoint RAID device to a set.
262
static struct raid_set *
263
hpt37x_group(struct lib_context *lc, struct raid_dev *rd)
265
struct raid_set *rs, *ss = NULL;
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;
278
* Check a Highpoint 37X RAID set.
280
* FIXME: more sanity checks.
283
devices(struct raid_dev *rd, void *context)
285
return META(rd, hpt37x)->raid_disks;
289
check_rd(struct lib_context *lc, struct raid_set *rs,
290
struct raid_dev *rd, void *context)
293
* FIXME: raid_disks member wrong ?
294
* (eg, Peter Jonas RAID1 metadata, 2 disks and raid_disks = 1)
300
hpt37x_check(struct lib_context *lc, struct raid_set *rs)
302
return check_raid_set(lc, rs, devices, NULL, check_rd, NULL, handler);
306
* IO error event handler.
309
event_io(struct lib_context *lc, struct event_io *e_io)
311
struct raid_dev *rd = e_io->rd;
312
struct hpt37x *hpt = META(rd, hpt37x);
314
/* Avoid write trashing. */
315
if (status(hpt) & s_broken)
318
hpt->magic = HPT37X_MAGIC_BAD;
322
static struct event_handlers hpt37x_event_handlers = {
324
.rd = NULL, /* FIXME: no device add/remove event handler yet. */
327
#ifdef DMRAID_NATIVE_LOG
329
* Log native information about an HPT37X RAID device.
332
hpt37x_log(struct lib_context *lc, struct raid_dev *rd)
334
struct hpt37x *hpt = META(rd, hpt37x);
335
struct hpt37x_errorlog *el;
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:");
356
for (el = hpt->errorlog; el < hpt->errorlog + 32; el++) {
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);
370
static struct dmraid_format hpt37x_format = {
372
.descr = "Highpoint HPT37X",
373
.caps = "S,0,1,10,01",
376
.write = hpt37x_write,
377
.group = hpt37x_group,
378
.check = hpt37x_check,
379
.events = &hpt37x_event_handlers,
380
#ifdef DMRAID_NATIVE_LOG
385
/* Register this format handler with the format core. */
387
register_hpt37x(struct lib_context *lc)
389
return register_format_handler(lc, &hpt37x_format);
392
/* Calculate RAID device size in sectors depending on RAID type. */
394
sectors(struct raid_dev *rd, struct hpt37x *hpt)
397
struct dev_info *di = rd->di;
401
ret = hpt->total_secs / (hpt->raid_disks ? hpt->raid_disks : 1);
405
ret = hpt->total_secs;
412
/* Subtract offset sectors on drives > 0. */
413
return ret - rd->offset;
416
/* Derive the RAID device contents from the Highpoint ones. */
418
setup_rd(struct lib_context *lc, struct raid_dev *rd,
419
struct dev_info *di, void *meta, union read_info *info)
421
struct hpt37x *hpt = meta;
423
if (!(rd->meta_areas = alloc_meta_areas(lc, rd, handler, 1)))
426
rd->meta_areas->offset = HPT37X_CONFIGOFFSET >> 9;
427
rd->meta_areas->size = sizeof(*hpt);
428
rd->meta_areas->area = (void *) hpt;
431
rd->fmt = &hpt37x_format;
433
rd->status = status(hpt);
434
rd->type = type(hpt);
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);
441
return (rd->name = name(lc, rd, 1)) ? 1 : 0;