Lines 25-54
Link Here
|
25 |
#endif |
25 |
#endif |
26 |
|
26 |
|
27 |
static const char *handler = HANDLER; |
27 |
static const char *handler = HANDLER; |
|
|
28 |
static struct isw_disk *_get_disk(struct isw *isw, struct dev_info *di); |
29 |
int is_raid10(struct isw *isw); |
28 |
|
30 |
|
29 |
/* |
31 |
static size_t _name(struct isw *isw, char *str, size_t len, int subset, |
30 |
* Make up RAID set name from family_num and volume name. |
32 |
int num, struct isw_dev *dev) |
31 |
*/ |
|
|
32 |
static size_t _name(struct isw *isw, struct isw_dev *dev, |
33 |
char *str, size_t len) |
34 |
{ |
33 |
{ |
35 |
return snprintf(str, len, dev ? "isw_%u_%s" : "isw_%u", |
34 |
switch(subset) { |
|
|
35 |
case 2: |
36 |
return snprintf(str, len, "isw_%u", isw->family_num); |
37 |
case 1: |
38 |
if(!is_raid10(isw)) |
39 |
return snprintf(str, len, "isw_%u_%s", |
36 |
isw->family_num, (char*) dev->volume); |
40 |
isw->family_num, (char*) dev->volume); |
37 |
} |
41 |
else |
|
|
42 |
return snprintf(str, len, "isw_%u_%s-%u", |
43 |
isw->family_num, (char*) dev->volume, num); |
44 |
case 0: |
45 |
return snprintf(str, len, "isw_%u_%s", isw->family_num, |
46 |
(char*) dev->volume); |
47 |
} |
48 |
return 0; |
49 |
} |
50 |
|
51 |
static char *name(struct lib_context *lc, struct raid_dev *rd, |
52 |
unsigned int subset) |
53 |
{ |
54 |
size_t len; |
55 |
char *ret = NULL; |
56 |
int id = 0; |
57 |
struct isw *isw = META(rd, isw); |
58 |
struct isw_disk *disk = isw->disk; |
59 |
struct isw_dev *dev = (struct isw_dev*) (isw->disk + isw->num_disks); |
38 |
|
60 |
|
39 |
static char *name(struct lib_context *lc, struct isw *isw, struct isw_dev *dev) |
61 |
if((subset == 1) && (is_raid10(isw))) { |
40 |
{ |
62 |
if ((disk = _get_disk(isw, rd->di))) { |
41 |
size_t len; |
63 |
if(disk == isw->disk) id = 0; |
42 |
char *ret; |
64 |
else if(disk == isw->disk + 1) id = 1; |
|
|
65 |
else if(disk == isw->disk + 2) id = 2; |
66 |
else if(disk == isw->disk + 3) id = 3; |
67 |
else return ret; |
68 |
} |
69 |
id = id % 2; |
70 |
} |
43 |
|
71 |
|
44 |
if ((ret = dbg_malloc((len = _name(isw, dev, NULL, 0) + 1)))) { |
72 |
if ((ret = dbg_malloc((len = _name(isw, ret, 0, subset, id, |
45 |
_name(isw, dev, ret, len); |
73 |
dev) + 1)))) { |
46 |
mk_alpha(lc, ret + HANDLER_LEN, len - HANDLER_LEN - |
74 |
_name(isw, ret, len, subset, id, dev); |
47 |
(dev ? strlen((char*) dev->volume) - 2 : 1)); |
75 |
mk_alpha(lc, ret + HANDLER_LEN, snprintf(ret, 0, "%u", |
48 |
} else |
76 |
isw->family_num)); |
|
|
77 |
} else |
49 |
log_alloc_err(lc, handler); |
78 |
log_alloc_err(lc, handler); |
50 |
|
79 |
|
51 |
return ret; |
80 |
return ret; |
52 |
} |
81 |
} |
53 |
|
82 |
|
54 |
/* Find a disk table slot by serial number. */ |
83 |
/* Find a disk table slot by serial number. */ |
Lines 59-65
Link Here
|
59 |
|
88 |
|
60 |
do { |
89 |
do { |
61 |
if (!strncmp(di->serial, (const char*) disk->serial, |
90 |
if (!strncmp(di->serial, (const char*) disk->serial, |
62 |
MAX_RAID_SERIAL_LEN)) |
91 |
MAX_RAID_SERIAL_LEN)) |
63 |
return disk; |
92 |
return disk; |
64 |
} while (++disk < isw->disk + isw->num_disks); |
93 |
} while (++disk < isw->disk + isw->num_disks); |
65 |
} |
94 |
} |
Lines 102-122
Link Here
|
102 |
} |
131 |
} |
103 |
|
132 |
|
104 |
/* Neutralize disk type. */ |
133 |
/* Neutralize disk type. */ |
105 |
static enum type type(struct raid_dev *rd) |
134 |
static enum type type(struct isw *isw) |
106 |
{ |
135 |
{ |
107 |
/* Mapping of Intel types to generic types. */ |
136 |
/* Mapping of Intel types to generic types. */ |
108 |
static struct types types[] = { |
137 |
static struct types types[] = { |
109 |
{ ISW_T_RAID0, t_raid0}, |
138 |
{ ISW_T_RAID0, t_raid0}, |
110 |
{ ISW_T_RAID1, t_raid1}, |
139 |
{ ISW_T_RAID1, t_raid1}, |
111 |
{ ISW_T_RAID5, t_raid5_la}, |
140 |
{ ISW_T_RAID5, t_raid5_la}, |
|
|
141 |
{ ISW_T_RAID10, t_raid0}, |
112 |
{ 0, t_undef}, |
142 |
{ 0, t_undef}, |
113 |
}; |
143 |
}; |
114 |
struct isw_dev *dev = rd->private.ptr; |
144 |
|
|
|
145 |
struct isw_dev *dev = (struct isw_dev*) (isw->disk + isw->num_disks); |
146 |
|
147 |
if(is_raid10(isw)) |
148 |
dev->vol.map.raid_level = ISW_T_RAID10; |
115 |
|
149 |
|
116 |
return dev ? rd_type(types, (unsigned int) dev->vol.map.raid_level) : |
150 |
return dev ? rd_type(types, (unsigned int) dev->vol.map.raid_level) : |
117 |
t_group; |
151 |
t_group; |
118 |
} |
152 |
} |
119 |
|
153 |
|
|
|
154 |
int is_raid10(struct isw *isw) |
155 |
{ |
156 |
int ret; |
157 |
struct isw_dev *dev = (struct isw_dev*) (isw->disk + isw->num_disks); |
158 |
|
159 |
ret = ((dev->vol.map.raid_level == ISW_T_RAID10) || |
160 |
(dev->vol.map.raid_level == ISW_T_RAID1 && |
161 |
isw->num_disks > 3)); |
162 |
|
163 |
return ret; |
164 |
} |
165 |
|
120 |
/* |
166 |
/* |
121 |
* Generate checksum of Raid metadata for mpb_size/sizeof(u32) words |
167 |
* Generate checksum of Raid metadata for mpb_size/sizeof(u32) words |
122 |
* (checksum field itself ignored for this calculation). |
168 |
* (checksum field itself ignored for this calculation). |
Lines 298-304
Link Here
|
298 |
} |
344 |
} |
299 |
|
345 |
|
300 |
/* Check for RAID disk ok. */ |
346 |
/* Check for RAID disk ok. */ |
301 |
static int disk_ok(struct lib_context *lc, struct dev_info *di, struct isw *isw) |
347 |
static int disk_ok(struct lib_context *lc, struct dev_info *di, |
|
|
348 |
struct isw *isw) |
302 |
{ |
349 |
{ |
303 |
struct isw_disk *disk = get_disk(lc, di, isw); |
350 |
struct isw_disk *disk = get_disk(lc, di, isw); |
304 |
|
351 |
|
Lines 306-320
Link Here
|
306 |
} |
353 |
} |
307 |
|
354 |
|
308 |
static void *isw_read_metadata(struct lib_context *lc, struct dev_info *di, |
355 |
static void *isw_read_metadata(struct lib_context *lc, struct dev_info *di, |
309 |
size_t *sz, uint64_t *offset, |
356 |
size_t *sz, uint64_t *offset, |
310 |
union read_info *info) |
357 |
union read_info *info) |
311 |
{ |
358 |
{ |
312 |
size_t size = ISW_DISK_BLOCK_SIZE; |
359 |
size_t size = ISW_DISK_BLOCK_SIZE; |
313 |
uint64_t isw_sboffset = ISW_CONFIGOFFSET; |
360 |
uint64_t isw_sboffset = ISW_CONFIGOFFSET; |
314 |
struct isw *isw; |
361 |
struct isw *isw; |
315 |
|
362 |
|
316 |
if (!(isw = alloc_private_and_read(lc, handler, size, |
363 |
if (!(isw = alloc_private_and_read(lc, handler, size, |
317 |
di->path, isw_sboffset))) |
364 |
di->path, isw_sboffset))) |
318 |
goto out; |
365 |
goto out; |
319 |
|
366 |
|
320 |
/* |
367 |
/* |
Lines 391-397
Link Here
|
391 |
*/ |
438 |
*/ |
392 |
/* Check state if isw device map. */ |
439 |
/* Check state if isw device map. */ |
393 |
static int _check_map_state(struct lib_context *lc, struct raid_dev *rd, |
440 |
static int _check_map_state(struct lib_context *lc, struct raid_dev *rd, |
394 |
struct isw_dev *dev) |
441 |
struct isw_dev *dev) |
395 |
{ |
442 |
{ |
396 |
/* FIXME: FAILED_MAP etc. */ |
443 |
/* FIXME: FAILED_MAP etc. */ |
397 |
switch (dev->vol.map.map_state) { |
444 |
switch (dev->vol.map.map_state) { |
Lines 415-434
Link Here
|
415 |
struct raid_dev *r; |
462 |
struct raid_dev *r; |
416 |
|
463 |
|
417 |
if (!_check_map_state(lc, rd, dev) || |
464 |
if (!_check_map_state(lc, rd, dev) || |
418 |
!(r = alloc_raid_dev(lc, handler))) |
465 |
!(r = alloc_raid_dev(lc, handler))) |
419 |
return NULL; |
466 |
return NULL; |
420 |
|
467 |
|
421 |
if (!(r->private.ptr = alloc_private(lc, handler, sizeof(*dev)))) |
468 |
if (!(r->private.ptr = alloc_private(lc, handler, sizeof(*dev)))) |
422 |
goto free; |
469 |
goto free; |
423 |
|
|
|
424 |
memcpy(r->private.ptr, dev, sizeof(*dev)); |
470 |
memcpy(r->private.ptr, dev, sizeof(*dev)); |
425 |
if ((r->type = type(r)) == t_undef) { |
471 |
|
|
|
472 |
if (!(r->meta_areas = alloc_meta_areas(lc, rd, handler, 1))) |
473 |
return 0; |
474 |
|
475 |
r->meta_areas->offset = rd->meta_areas->offset; |
476 |
r->meta_areas->size = rd->meta_areas->size; |
477 |
r->meta_areas->area = rd->meta_areas->area; |
478 |
|
479 |
if ((r->type = type(isw)) == t_undef) { |
426 |
log_err(lc, "%s: RAID type %u not supported", |
480 |
log_err(lc, "%s: RAID type %u not supported", |
427 |
handler, (unsigned int) dev->vol.map.raid_level); |
481 |
handler, (unsigned int) dev->vol.map.raid_level); |
428 |
goto free; |
482 |
goto free; |
429 |
} |
483 |
} |
430 |
|
484 |
|
431 |
if (!(r->name = name(lc, isw, dev))) |
485 |
if (!(r->name = name(lc, rd, 1))) |
432 |
goto free; |
486 |
goto free; |
433 |
|
487 |
|
434 |
r->di = rd->di; |
488 |
r->di = rd->di; |
Lines 460-502
Link Here
|
460 |
return _get_disk(isw, RD(new)->di) < _get_disk(isw, RD(pos)->di); |
514 |
return _get_disk(isw, RD(new)->di) < _get_disk(isw, RD(pos)->di); |
461 |
} |
515 |
} |
462 |
|
516 |
|
|
|
517 |
static void super_created(struct raid_set *super, void *private) |
518 |
{ |
519 |
super->type = t_raid1; |
520 |
super->stride = ((struct isw_dev*) private)->vol.map.blocks_per_strip; |
521 |
} |
522 |
|
523 |
static int set_sort(struct list_head *pos, struct list_head *new) |
524 |
{ |
525 |
return 0; |
526 |
} |
527 |
|
463 |
/* |
528 |
/* |
464 |
* rs_group contains the top-level group RAID set (type: t_group) on entry |
529 |
* rs_group contains the top-level group RAID set (type: t_group) on entry |
465 |
* and shall be returned on success (or NULL on error). |
530 |
* and shall be returned on success (or NULL on error). |
466 |
*/ |
531 |
*/ |
467 |
static struct raid_set *group_rd(struct lib_context *lc, |
532 |
static struct raid_set *group_rd(struct lib_context *lc, |
468 |
struct raid_set *rs_group, |
533 |
struct raid_set *rs_group, |
469 |
struct raid_dev *rd_meta) |
534 |
struct raid_dev *rd_meta) |
470 |
{ |
535 |
{ |
471 |
unsigned int d; |
536 |
unsigned int d; |
472 |
void *private; |
537 |
void *private; |
473 |
struct isw *isw = META(rd_meta, isw); |
538 |
struct isw *isw = META(rd_meta, isw); |
474 |
struct isw_dev *dev; |
539 |
struct isw_dev *dev; |
475 |
struct raid_dev *rd; |
540 |
struct raid_dev *rd; |
476 |
struct raid_set *rs; |
541 |
struct raid_set *rs, *ss; |
477 |
|
542 |
char *nm = NULL; |
|
|
543 |
|
478 |
/* Loop the device/volume table. */ |
544 |
/* Loop the device/volume table. */ |
479 |
for (d = 0; d < isw->num_raid_devs; d++) { |
545 |
for (d = 0; d < isw->num_raid_devs; d++) { |
480 |
dev = raiddev(isw, d); |
546 |
dev = raiddev(isw, d); |
481 |
|
547 |
|
482 |
if (!(rd = _create_rd(lc, rd_meta, isw, dev))) |
548 |
if (!(rd = _create_rd(lc, rd_meta, isw, dev))) |
483 |
return NULL; |
549 |
return NULL; |
484 |
|
550 |
|
485 |
if (!(rs = find_or_alloc_raid_set(lc, rd->name, FIND_ALL, |
551 |
if(is_raid10(isw)) { |
486 |
rd, &rs_group->sets, |
552 |
nm = name(lc, rd, 0); |
487 |
create_rs, dev))) { |
553 |
ss = find_or_alloc_raid_set(lc, nm, FIND_TOP, rd, |
488 |
free_raid_dev(lc, &rd); |
554 |
LC_RS(lc), super_created, dev); |
489 |
return NULL; |
555 |
if (!(rs = find_or_alloc_raid_set(lc, rd->name, |
|
|
556 |
FIND_ALL, rd, &ss->sets, create_rs, |
557 |
dev))) { |
558 |
free_raid_dev(lc, &rd); |
559 |
return NULL; |
560 |
} |
561 |
} else { |
562 |
if (!(rs = find_or_alloc_raid_set(lc, rd->name, |
563 |
FIND_ALL, rd, &rs_group->sets, |
564 |
create_rs, dev))) { |
565 |
free_raid_dev(lc, &rd); |
566 |
return NULL; |
567 |
} |
490 |
} |
568 |
} |
491 |
|
569 |
|
|
|
570 |
rs->status = s_ok; |
571 |
|
492 |
/* Save and set to enable dev_sort(). */ |
572 |
/* Save and set to enable dev_sort(). */ |
493 |
private = rd->private.ptr; |
573 |
private = rd->private.ptr; |
494 |
rd->private.ptr = isw; |
574 |
rd->private.ptr = isw; |
495 |
|
|
|
496 |
list_add_sorted(lc, &rs->devs, &rd->devs, dev_sort); |
575 |
list_add_sorted(lc, &rs->devs, &rd->devs, dev_sort); |
497 |
|
|
|
498 |
/* Restore. */ |
576 |
/* Restore. */ |
499 |
rd->private.ptr = private; |
577 |
rd->private.ptr = private; |
|
|
578 |
|
579 |
if(is_raid10(isw)) { |
580 |
ss = join_superset(lc, name, super_created, set_sort, |
581 |
rs, rd); |
582 |
return ss; |
583 |
} |
500 |
} |
584 |
} |
501 |
|
585 |
|
502 |
return rs_group; |
586 |
return rs_group; |
Lines 504-534
Link Here
|
504 |
|
588 |
|
505 |
/* Add an Intel SW RAID device to a set */ |
589 |
/* Add an Intel SW RAID device to a set */ |
506 |
static struct raid_set *isw_group(struct lib_context *lc, |
590 |
static struct raid_set *isw_group(struct lib_context *lc, |
507 |
struct raid_dev *rd_meta) |
591 |
struct raid_dev *rd_meta) |
508 |
{ |
592 |
{ |
509 |
struct raid_set *rs_group; |
593 |
struct raid_set *rs_group = NULL; |
|
|
594 |
struct isw *isw = META(rd_meta, isw); |
510 |
|
595 |
|
511 |
if (T_SPARE(rd_meta)) |
596 |
if (T_SPARE(rd_meta)) |
512 |
return NULL; |
597 |
return NULL; |
513 |
|
598 |
|
514 |
/* |
599 |
if(!is_raid10(isw)) { |
515 |
* Once we get here, an Intel SW RAID disk containing a metadata area |
600 |
/* |
516 |
* with a volume table has been discovered by isw_read. |
601 |
* Once we get here, an Intel SW RAID disk containing a metadata |
517 |
*/ |
602 |
* area with a volume table has been discovered by isw_read. |
518 |
/* Check if a top level group RAID set already exists. */ |
603 |
*/ |
519 |
if (!(rs_group = find_or_alloc_raid_set(lc, rd_meta->name, FIND_TOP, |
604 |
/* Check if a top level group RAID set already exists. */ |
520 |
rd_meta, LC_RS(lc), |
605 |
if (!(rs_group = find_or_alloc_raid_set(lc, rd_meta->name, |
521 |
NO_CREATE, NO_CREATE_ARG))) |
606 |
FIND_TOP, rd_meta, LC_RS(lc), |
522 |
return NULL; |
607 |
NO_CREATE, NO_CREATE_ARG))) |
|
|
608 |
return NULL; |
523 |
|
609 |
|
524 |
/* |
610 |
/* |
525 |
* Add the whole underlying (meta) RAID device to the group set. |
611 |
* Add the whole underlying (meta) RAID device to the group set. |
526 |
* Sorting is no problem here, because RAID sets and devices will |
612 |
* Sorting is no problem here, because RAID sets and devices |
527 |
* be created for all the Volumes of an ISW set and those need sorting. |
613 |
* will be created for all the Volumes of an ISW set and those |
528 |
*/ |
614 |
* need sorting. |
529 |
rd_meta->private.ptr = rd_meta->meta_areas->area; |
615 |
*/ |
530 |
list_add_sorted(lc, &rs_group->devs, &rd_meta->devs, dev_sort); |
616 |
rd_meta->private.ptr = rd_meta->meta_areas->area; |
531 |
rd_meta->private.ptr = NULL; |
617 |
list_add_sorted(lc, &rs_group->devs, &rd_meta->devs, dev_sort); |
|
|
618 |
rd_meta->private.ptr = NULL; |
619 |
} |
532 |
|
620 |
|
533 |
/* |
621 |
/* |
534 |
* We need to run through the volume table and create a RAID set and |
622 |
* We need to run through the volume table and create a RAID set and |
Lines 552-568
Link Here
|
552 |
} |
640 |
} |
553 |
|
641 |
|
554 |
static int check_rd(struct lib_context *lc, struct raid_set *rs, |
642 |
static int check_rd(struct lib_context *lc, struct raid_set *rs, |
555 |
struct raid_dev *rd, void *context) |
643 |
struct raid_dev *rd, void *context) |
556 |
{ |
644 |
{ |
557 |
struct isw_dev *dev = rd->private.ptr; |
645 |
struct isw_dev *dev = rd->private.ptr; |
558 |
|
646 |
|
559 |
/* FIXME: more status checks ? */ |
647 |
/* FIXME: more status checks ? */ |
560 |
if (dev->status) |
648 |
if (dev->status) |
561 |
LOG_ERR(lc, 0, "%s device for volume \"%s\" broken on %s " |
649 |
LOG_ERR(lc, 0, "%s device for volume \"%s\" broken on %s " |
562 |
"in RAID set \"%s\"", |
650 |
"in RAID set \"%s\"", handler, dev->volume, |
563 |
handler, dev->volume, rd->di->path, rs->name); |
651 |
rd->di->path, rs->name); |
564 |
|
652 |
return 1; |
565 |
return 1; |
|
|
566 |
} |
653 |
} |
567 |
|
654 |
|
568 |
static int _isw_check(struct lib_context *lc, struct raid_set *rs) |
655 |
static int _isw_check(struct lib_context *lc, struct raid_set *rs) |
Lines 572-580
Link Here
|
572 |
|
659 |
|
573 |
static int isw_check(struct lib_context *lc, struct raid_set *rs) |
660 |
static int isw_check(struct lib_context *lc, struct raid_set *rs) |
574 |
{ |
661 |
{ |
575 |
return T_GROUP(rs) ? _isw_check(lc, rs) : 0; |
662 |
/* If it is a stacked set like RAID10 */ |
|
|
663 |
if((!T_GROUP(rs)) && SETS(rs)) { |
664 |
return check_raid_set(lc, rs, devices, NULL, |
665 |
NO_CHECK_RD, NULL, handler); |
666 |
} else { |
667 |
return T_GROUP(rs) ? _isw_check(lc, rs) : 0; |
668 |
} |
576 |
} |
669 |
} |
577 |
|
|
|
578 |
/* |
670 |
/* |
579 |
* IO error event handler. |
671 |
* IO error event handler. |
580 |
*/ |
672 |
*/ |
Lines 585-591
Link Here
|
585 |
struct isw_disk *disk; |
677 |
struct isw_disk *disk; |
586 |
|
678 |
|
587 |
if (!(disk = get_disk(lc, rd->di, isw))) |
679 |
if (!(disk = get_disk(lc, rd->di, isw))) |
588 |
LOG_ERR(lc, 0, "%s: disk", handler); |
680 |
LOG_ERR(lc, 0, "%s: disk", handler); |
589 |
|
681 |
|
590 |
/* Avoid write trashing. */ |
682 |
/* Avoid write trashing. */ |
591 |
if (S_BROKEN(status(lc, rd))) |
683 |
if (S_BROKEN(status(lc, rd))) |
Lines 629-635
Link Here
|
629 |
for (i = 0; i < ISW_FILLERS; i++) { |
721 |
for (i = 0; i < ISW_FILLERS; i++) { |
630 |
if (isw->filler[i]) |
722 |
if (isw->filler[i]) |
631 |
P("filler[%i]: %u", isw, |
723 |
P("filler[%i]: %u", isw, |
632 |
isw->filler[i], i, isw->filler[i]); |
724 |
isw->filler[i], i, isw->filler[i]); |
633 |
} |
725 |
} |
634 |
|
726 |
|
635 |
/* Disk table. */ |
727 |
/* Disk table. */ |
Lines 744-750
Link Here
|
744 |
static struct dmraid_format isw_format = { |
836 |
static struct dmraid_format isw_format = { |
745 |
.name = HANDLER, |
837 |
.name = HANDLER, |
746 |
.descr = "Intel Software RAID", |
838 |
.descr = "Intel Software RAID", |
747 |
.caps = "0,1", |
839 |
.caps = "0,1,10", |
748 |
.format = FMT_RAID, |
840 |
.format = FMT_RAID, |
749 |
.read = isw_read, |
841 |
.read = isw_read, |
750 |
.write = isw_write, |
842 |
.write = isw_write, |
Lines 797-801
Link Here
|
797 |
rd->status = status(lc, rd); |
889 |
rd->status = status(lc, rd); |
798 |
rd->type = t_group; |
890 |
rd->type = t_group; |
799 |
|
891 |
|
800 |
return (rd->name = name(lc, isw, NULL)) ? 1 : 0; |
892 |
return (rd->name = name(lc, rd, 2)) ? 1 : 0; |
801 |
} |
893 |
} |
|
|
894 |
|
895 |
|