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);
|
||||
}
|
||||
|
||||
#ifndef MDASSEMBLE
|
||||
static struct dl *serial_to_dl(__u8 *serial, struct intel_super *super)
|
||||
{
|
||||
struct dl *dl;
|
||||
|
@ -2886,7 +2885,6 @@ static struct dl *serial_to_dl(__u8 *serial, struct intel_super *super)
|
|||
|
||||
return dl;
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct imsm_disk *
|
||||
__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;
|
||||
}
|
||||
|
||||
#ifndef MDASSEMBLE
|
||||
/* find_missing - helper routine for load_super_imsm_all that identifies
|
||||
* disks that have disappeared from the system. This routine relies on
|
||||
* the mpb being uptodate, which it is at load time.
|
||||
|
@ -3480,6 +3477,7 @@ static int find_missing(struct intel_super *super)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifndef MDASSEMBLE
|
||||
static struct intel_disk *disk_list_get(__u8 *serial, struct intel_disk *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);
|
||||
}
|
||||
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
|
||||
* add_to_super_imsm_volume()
|
||||
|
||||
/* handle 'failed_disks' by either:
|
||||
* 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;
|
||||
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))
|
||||
return 0;
|
||||
|
@ -4170,15 +4196,14 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
|
|||
vol = &dev->vol;
|
||||
vol->migr_state = 0;
|
||||
set_migr_type(dev, MIGR_INIT);
|
||||
vol->dirty = 0;
|
||||
vol->dirty = !info->state;
|
||||
vol->curr_migr_unit = 0;
|
||||
map = get_imsm_map(dev, 0);
|
||||
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_strip = __cpu_to_le16(info_to_blocks_per_strip(info));
|
||||
map->failed_disk_num = ~0;
|
||||
map->map_state = info->level ? IMSM_T_STATE_UNINITIALIZED :
|
||||
IMSM_T_STATE_NORMAL;
|
||||
map->map_state = info->failed_disks ? IMSM_T_STATE_DEGRADED : IMSM_T_STATE_NORMAL;
|
||||
map->ddf = 1;
|
||||
|
||||
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 imsm_super *mpb = super->anchor;
|
||||
struct dl *dl;
|
||||
struct imsm_disk *_disk;
|
||||
struct imsm_dev *dev;
|
||||
struct imsm_map *map;
|
||||
struct dl *dl, *df;
|
||||
int slot;
|
||||
|
||||
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);
|
||||
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 (super->current_vol == 0) {
|
||||
__u32 sum;
|
||||
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) {
|
||||
fprintf(stderr, Name ": BUG mpb setup error\n");
|
||||
return 1;
|
||||
|
|
Loading…
Reference in New Issue