2
* JMicron metadata format handler.
4
* Copyright (C) 2006-2008 Heinz Mauelshagen, Red Hat GmbH.
7
* See file LICENSE at the top of this source tree for license information.
10
#define HANDLER "jmicron"
13
#define FORMAT_HANDLER
16
#if BYTE_ORDER != LITTLE_ENDIAN
17
# define DM_BYTEORDER_SWAB
18
# include <datastruct/byteorder.h>
21
static const char *handler = HANDLER;
24
static int member(struct jm *jm);
26
name(struct lib_context *lc, struct raid_dev *rd, unsigned int subset)
29
struct jm *jm = META(rd, jm);
30
char *ret, *name = (char *) jm->name;
31
char buf[JM_NAME_LEN + 1] = { '\0' };
33
/* Sanitize name, make sure it's null terminated */
34
strncpy(buf, name, JM_NAME_LEN);
35
while (i && isspace(buf[i])) {
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);
48
sprintf(ret, "%s_%s%s", handler, name, buf);
55
* Retrieve status of device.
56
* FIXME: is this sufficient to cover all state ?
61
return jm->attribute & ~(JM_MOUNT | JM_BOOTABLE | JM_BADSEC | JM_ACTIVE
62
| JM_UNSYNC | JM_NEWEST) ? s_broken : s_ok;
65
/* Neutralize disk type */
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 },
78
return rd_type(types, (unsigned int) jm->mode);
81
/* Calculate checksum on metadata */
83
checksum(struct jm *jm)
86
uint16_t *p = (uint16_t *) jm, sum = 0;
91
/* FIXME: shouldn't this be one value only ? */
92
return !sum || sum == 1;
95
static inline unsigned int
98
return (unsigned int) (m & JM_SEG_MASK);
101
static inline unsigned int
104
return (unsigned int) (m & JM_HDD_MASK);
108
member(struct jm *jm)
110
unsigned int i = JM_MEMBERS;
113
if (disk(jm->member[i]) == disk(jm->identity))
120
/* Decide about ordering sequence of RAID device. */
122
dev_sort(struct list_head *pos, struct list_head *new)
124
return member(META(RD(new), jm)) < member(META(RD(pos), jm));
127
/* Decide about ordering sequence of RAID subset. */
129
set_sort(struct list_head *pos, struct list_head *new)
131
return member(META(RD_RS(RS(pos)), jm)) > 1;
135
stride(unsigned int shift)
137
return 1 << (shift + 1);
141
super_created(struct raid_set *super, void *private)
143
super->type = t_raid0;
144
super->stride = stride(META((private), jm)->block);
148
* Group the RAID disk into a JM set.
150
* Check device hierarchy and create super set appropriately.
153
group_rd(struct lib_context *lc, struct raid_set *rs,
154
struct raid_set **ss, struct raid_dev *rd)
156
struct jm *jm = META(rd, jm);
158
if (!init_raid_set(lc, rs, rd, stride(jm->block), jm->mode, handler))
161
list_add_sorted(lc, &rs->devs, &rd->devs, dev_sort);
167
if (!find_set(lc, NULL, rs->name, FIND_TOP))
168
list_add_tail(&rs->list, LC_RS(lc));
172
if (!(*ss = join_superset(lc, name, super_created,
181
* Add a JMicron RAID device to a set.
183
static struct raid_set *
184
jm_group(struct lib_context *lc, struct raid_dev *rd)
186
struct raid_set *rs, *ss = NULL;
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;
199
* Read a JMicron RAID device.
201
/* Endianess conversion. */
202
#if BYTE_ORDER == LITTLE_ENDIAN
209
struct jm *jm = meta;
215
CVT32(jm->segment.base);
216
CVT32(jm->segment.range);
217
CVT16(jm->segment.range2);
219
CVT16(jm->attribute);
221
for (i = 0; i < JM_SPARES; i++)
224
for (i = 0; i < JM_MEMBERS; i++)
225
CVT32(jm->member[i]);
231
is_jm(struct lib_context *lc, struct dev_info *di, void *meta)
233
struct jm *jm = meta;
235
return !strncmp((const char *) jm->signature,
236
JM_SIGNATURE, JM_SIGNATURE_LEN) &&
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)
245
return read_raid_dev(lc, di, NULL,
246
sizeof(struct jm), JM_CONFIGOFFSET,
247
to_cpu, is_jm, NULL, setup_rd, handler);
251
* Write a JMicron RAID device.
254
jm_write(struct lib_context *lc, struct raid_dev *rd, int erase)
257
#if BYTE_ORDER != LITTLE_ENDIAN
258
struct jm *jm = META(rd, jm);
262
ret = write_metadata(lc, handler, rd, -1, erase);
263
#if BYTE_ORDER != LITTLE_ENDIAN
270
* Check a JMicron RAID set.
272
* FIXME: more sanity checks.
275
devices(struct raid_dev *rd, void *context)
277
unsigned int r = JM_MEMBERS;
278
struct jm *jm = META(rd, jm);
280
while (r-- && !jm->member[r]);
285
jm_check(struct lib_context *lc, struct raid_set *rs)
287
return check_raid_set(lc, rs, devices, NULL,
288
NO_CHECK_RD, NULL, handler);
292
* IO error event handler.
295
event_io(struct lib_context *lc, struct event_io *e_io)
297
struct raid_dev *rd = e_io->rd;
298
struct jm *jm = META(rd, jm);
300
/* Avoid write trashing. */
301
if (S_BROKEN(status(jm)))
304
jm->checksum = 1; /* FIXME: how to flag a JMicron disk bad? */
308
static struct event_handlers jm_event_handlers = {
310
.rd = NULL, /* FIXME: no device add/remove event handler yet. */
313
#ifdef DMRAID_NATIVE_LOG
315
* Log native information about an JM RAID device.
318
jm_log(struct lib_context *lc, struct raid_dev *rd)
321
struct jm *jm = META(rd, jm);
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);
338
for (i = 0; i < JM_SPARES; i++)
339
P2("spare[%d]: 0x%x", jm, i, jm->spare[i]);
341
for (i = 0; i < JM_MEMBERS; i++)
342
P2("member[%d]: 0x%x", jm, i, jm->member[i]);
346
static struct dmraid_format jm_format = {
348
.descr = "JMicron ATARAID",
355
.events = &jm_event_handlers,
356
#ifdef DMRAID_NATIVE_LOG
361
/* Register this format handler with the format core. */
363
register_jm(struct lib_context *lc)
365
return register_format_handler(lc, &jm_format);
368
/* Calculate RAID device size in sectors depending on RAID type. */
369
static inline uint64_t
370
sectors(struct jm *jm)
372
/* range * 32MB[sectors] + range2 */
373
return jm->segment.range * 32 * 2048 + jm->segment.range2;
376
/* Set the RAID device contents up derived from the JMicron ones */
378
setup_rd(struct lib_context *lc, struct raid_dev *rd,
379
struct dev_info *di, void *meta, union read_info *info)
381
struct jm *jm = meta;
383
if (!(rd->meta_areas = alloc_meta_areas(lc, rd, handler, 1)))
386
rd->meta_areas->offset = JM_CONFIGOFFSET >> 9;
387
rd->meta_areas->size = sizeof(*jm);
388
rd->meta_areas->area = (void *) jm;
391
rd->fmt = &jm_format;
393
rd->status = status(jm);
396
rd->offset = jm->segment.base;
397
if (!(rd->sectors = sectors(jm)))
398
return log_zero_sectors(lc, di->path, handler);
400
return (rd->name = name(lc, rd, 1)) ? 1 : 0;