imsm: support 'missing' devices at Create
Specifying missing devices at create is very useful for array recovery. For imsm create dummy disk entries at init_super_imsm time, and then use them to fill in unoccupied slots in the final array (if the container is unpopulated). If the container is already populated (has a subarray) 'missing' disks must be in reference to already recorded missing devices in the metadata. Also add support for --assume-clean for imsm arrays. Cc: Dave Jiang <dave.jiang@intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: NeilBrown <neilb@suse.de>
This commit is contained in:
parent
1d446d52a7
commit
3960e579bf
|
@ -2875,7 +2875,6 @@ static void serialcpy(__u8 *dest, __u8 *src)
|
||||||
strncpy((char *) dest, (char *) src, MAX_RAID_SERIAL_LEN);
|
strncpy((char *) dest, (char *) src, MAX_RAID_SERIAL_LEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef MDASSEMBLE
|
|
||||||
static struct dl *serial_to_dl(__u8 *serial, struct intel_super *super)
|
static struct dl *serial_to_dl(__u8 *serial, struct intel_super *super)
|
||||||
{
|
{
|
||||||
struct dl *dl;
|
struct dl *dl;
|
||||||
|
@ -2886,7 +2885,6 @@ static struct dl *serial_to_dl(__u8 *serial, struct intel_super *super)
|
||||||
|
|
||||||
return dl;
|
return dl;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static struct imsm_disk *
|
static struct imsm_disk *
|
||||||
__serial_to_disk(__u8 *serial, struct imsm_super *mpb, int *idx)
|
__serial_to_disk(__u8 *serial, struct imsm_super *mpb, int *idx)
|
||||||
|
@ -3444,7 +3442,6 @@ static int find_intel_hba_capability(int fd, struct intel_super *super, char *de
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef MDASSEMBLE
|
|
||||||
/* find_missing - helper routine for load_super_imsm_all that identifies
|
/* find_missing - helper routine for load_super_imsm_all that identifies
|
||||||
* disks that have disappeared from the system. This routine relies on
|
* disks that have disappeared from the system. This routine relies on
|
||||||
* the mpb being uptodate, which it is at load time.
|
* the mpb being uptodate, which it is at load time.
|
||||||
|
@ -3480,6 +3477,7 @@ static int find_missing(struct intel_super *super)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef MDASSEMBLE
|
||||||
static struct intel_disk *disk_list_get(__u8 *serial, struct intel_disk *disk_list)
|
static struct intel_disk *disk_list_get(__u8 *serial, struct intel_disk *disk_list)
|
||||||
{
|
{
|
||||||
struct intel_disk *idisk = disk_list;
|
struct intel_disk *idisk = disk_list;
|
||||||
|
@ -4133,12 +4131,40 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
|
||||||
memset(mpb_new + size_old, 0, size_round - size_old);
|
memset(mpb_new + size_old, 0, size_round - size_old);
|
||||||
}
|
}
|
||||||
super->current_vol = idx;
|
super->current_vol = idx;
|
||||||
/* when creating the first raid device in this container set num_disks
|
|
||||||
* to zero, i.e. delete this spare and add raid member devices in
|
/* handle 'failed_disks' by either:
|
||||||
* add_to_super_imsm_volume()
|
* a) create dummy disk entries in the table if this the first
|
||||||
|
* volume in the array. We add them here as this is the only
|
||||||
|
* opportunity to add them. add_to_super_imsm_volume()
|
||||||
|
* handles the non-failed disks and continues incrementing
|
||||||
|
* mpb->num_disks.
|
||||||
|
* b) validate that 'failed_disks' matches the current number
|
||||||
|
* of missing disks if the container is populated
|
||||||
*/
|
*/
|
||||||
if (super->current_vol == 0)
|
if (super->current_vol == 0) {
|
||||||
mpb->num_disks = 0;
|
mpb->num_disks = 0;
|
||||||
|
for (i = 0; i < info->failed_disks; i++) {
|
||||||
|
struct imsm_disk *disk;
|
||||||
|
|
||||||
|
mpb->num_disks++;
|
||||||
|
disk = __get_imsm_disk(mpb, i);
|
||||||
|
disk->status = CONFIGURED_DISK | FAILED_DISK;
|
||||||
|
disk->scsi_id = __cpu_to_le32(~(__u32)0);
|
||||||
|
snprintf((char *) disk->serial, MAX_RAID_SERIAL_LEN,
|
||||||
|
"missing:%d", i);
|
||||||
|
}
|
||||||
|
find_missing(super);
|
||||||
|
} else {
|
||||||
|
int missing = 0;
|
||||||
|
struct dl *d;
|
||||||
|
|
||||||
|
for (d = super->missing; d; d = d->next)
|
||||||
|
missing++;
|
||||||
|
if (info->failed_disks > missing) {
|
||||||
|
fprintf(stderr, Name": unable to add 'missing' disk to container\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!check_name(super, name, 0))
|
if (!check_name(super, name, 0))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -4170,15 +4196,14 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
|
||||||
vol = &dev->vol;
|
vol = &dev->vol;
|
||||||
vol->migr_state = 0;
|
vol->migr_state = 0;
|
||||||
set_migr_type(dev, MIGR_INIT);
|
set_migr_type(dev, MIGR_INIT);
|
||||||
vol->dirty = 0;
|
vol->dirty = !info->state;
|
||||||
vol->curr_migr_unit = 0;
|
vol->curr_migr_unit = 0;
|
||||||
map = get_imsm_map(dev, 0);
|
map = get_imsm_map(dev, 0);
|
||||||
map->pba_of_lba0 = __cpu_to_le32(super->create_offset);
|
map->pba_of_lba0 = __cpu_to_le32(super->create_offset);
|
||||||
map->blocks_per_member = __cpu_to_le32(info_to_blocks_per_member(info));
|
map->blocks_per_member = __cpu_to_le32(info_to_blocks_per_member(info));
|
||||||
map->blocks_per_strip = __cpu_to_le16(info_to_blocks_per_strip(info));
|
map->blocks_per_strip = __cpu_to_le16(info_to_blocks_per_strip(info));
|
||||||
map->failed_disk_num = ~0;
|
map->failed_disk_num = ~0;
|
||||||
map->map_state = info->level ? IMSM_T_STATE_UNINITIALIZED :
|
map->map_state = info->failed_disks ? IMSM_T_STATE_DEGRADED : IMSM_T_STATE_NORMAL;
|
||||||
IMSM_T_STATE_NORMAL;
|
|
||||||
map->ddf = 1;
|
map->ddf = 1;
|
||||||
|
|
||||||
if (info->level == 1 && info->raid_disks > 2) {
|
if (info->level == 1 && info->raid_disks > 2) {
|
||||||
|
@ -4286,9 +4311,10 @@ static int add_to_super_imsm_volume(struct supertype *st, mdu_disk_info_t *dk,
|
||||||
{
|
{
|
||||||
struct intel_super *super = st->sb;
|
struct intel_super *super = st->sb;
|
||||||
struct imsm_super *mpb = super->anchor;
|
struct imsm_super *mpb = super->anchor;
|
||||||
struct dl *dl;
|
struct imsm_disk *_disk;
|
||||||
struct imsm_dev *dev;
|
struct imsm_dev *dev;
|
||||||
struct imsm_map *map;
|
struct imsm_map *map;
|
||||||
|
struct dl *dl, *df;
|
||||||
int slot;
|
int slot;
|
||||||
|
|
||||||
dev = get_imsm_dev(super, super->current_vol);
|
dev = get_imsm_dev(super, super->current_vol);
|
||||||
|
@ -4335,12 +4361,37 @@ static int add_to_super_imsm_volume(struct supertype *st, mdu_disk_info_t *dk,
|
||||||
set_imsm_ord_tbl_ent(map, dk->raid_disk, dl->index);
|
set_imsm_ord_tbl_ent(map, dk->raid_disk, dl->index);
|
||||||
dl->disk.status = CONFIGURED_DISK;
|
dl->disk.status = CONFIGURED_DISK;
|
||||||
|
|
||||||
|
/* update size of 'missing' disks to be at least as large as the
|
||||||
|
* largest acitve member (we only have dummy missing disks when
|
||||||
|
* creating the first volume)
|
||||||
|
*/
|
||||||
|
if (super->current_vol == 0) {
|
||||||
|
for (df = super->missing; df; df = df->next) {
|
||||||
|
if (dl->disk.total_blocks > df->disk.total_blocks)
|
||||||
|
df->disk.total_blocks = dl->disk.total_blocks;
|
||||||
|
_disk = __get_imsm_disk(mpb, df->index);
|
||||||
|
*_disk = df->disk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* refresh unset/failed slots to point to valid 'missing' entries */
|
||||||
|
for (df = super->missing; df; df = df->next)
|
||||||
|
for (slot = 0; slot < mpb->num_disks; slot++) {
|
||||||
|
__u32 ord = get_imsm_ord_tbl_ent(dev, slot, -1);
|
||||||
|
|
||||||
|
if ((ord & IMSM_ORD_REBUILD) == 0)
|
||||||
|
continue;
|
||||||
|
set_imsm_ord_tbl_ent(map, slot, df->index | IMSM_ORD_REBUILD);
|
||||||
|
dprintf("set slot:%d to missing disk:%d\n", slot, df->index);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* if we are creating the first raid device update the family number */
|
/* if we are creating the first raid device update the family number */
|
||||||
if (super->current_vol == 0) {
|
if (super->current_vol == 0) {
|
||||||
__u32 sum;
|
__u32 sum;
|
||||||
struct imsm_dev *_dev = __get_imsm_dev(mpb, 0);
|
struct imsm_dev *_dev = __get_imsm_dev(mpb, 0);
|
||||||
struct imsm_disk *_disk = __get_imsm_disk(mpb, dl->index);
|
|
||||||
|
|
||||||
|
_disk = __get_imsm_disk(mpb, dl->index);
|
||||||
if (!_dev || !_disk) {
|
if (!_dev || !_disk) {
|
||||||
fprintf(stderr, Name ": BUG mpb setup error\n");
|
fprintf(stderr, Name ": BUG mpb setup error\n");
|
||||||
return 1;
|
return 1;
|
||||||
|
|
Loading…
Reference in New Issue