imsm: prepare update for level migrations reshape

Introducing raid0->raid5 level migration metadata update structure
is prepared for future use.

Adding spare device is required to hold additional raid5 parity.
Mdadm just checks for spares, but it is not included in update.
If there are no spares available, abort. Otherwise we will create
degraded array what should be not allowed.
Mdmon will decide what spare device is used for parity.

Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
Signed-off-by: Przemyslaw Czarnowski <przemyslaw.hawrylewicz.czarnowski@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
This commit is contained in:
Przemyslaw Czarnowski 2011-05-04 17:11:07 +02:00 committed by NeilBrown
parent bfd80a5677
commit 48c5303aff
1 changed files with 104 additions and 2 deletions

View File

@ -305,6 +305,7 @@ enum imsm_update_type {
update_rename_array,
update_add_remove_disk,
update_reshape_container_disks,
update_reshape_migration,
update_takeover
};
@ -340,6 +341,20 @@ struct imsm_update_reshape {
enum imsm_update_type type;
int old_raid_disks;
int new_raid_disks;
int new_disks[1]; /* new_raid_disks - old_raid_disks makedev number */
};
struct imsm_update_reshape_migration {
enum imsm_update_type type;
int old_raid_disks;
int new_raid_disks;
/* fields for array migration changes
*/
int subdev;
int new_level;
int new_layout;
int new_disks[1]; /* new_raid_disks - old_raid_disks makedev number */
};
@ -6338,6 +6353,9 @@ static void imsm_process_update(struct supertype *st,
super->updates_pending++;
break;
}
case update_reshape_migration: {
break;
}
case update_activate_spare: {
struct imsm_update_activate_spare *u = (void *) update->buf;
struct imsm_dev *dev = get_imsm_dev(super, u->array);
@ -6731,6 +6749,9 @@ static void imsm_prepare_update(struct supertype *st,
dprintf("New anchor length is %llu\n", (unsigned long long)len);
break;
}
case update_reshape_migration: {
break;
}
case update_create_array: {
struct imsm_update_create_array *u = (void *) update->buf;
struct intel_dev *dv;
@ -7106,6 +7127,70 @@ abort:
return 0;
}
/******************************************************************************
* function: imsm_create_metadata_update_for_migration()
* Creates update for IMSM array.
*
******************************************************************************/
static int imsm_create_metadata_update_for_migration(
struct supertype *st,
struct geo_params *geo,
struct imsm_update_reshape_migration **updatep)
{
struct intel_super *super = st->sb;
int update_memory_size = 0;
struct imsm_update_reshape_migration *u = NULL;
struct imsm_dev *dev;
int previous_level = -1;
dprintf("imsm_create_metadata_update_for_migration(enter)"
" New Level = %i\n", geo->level);
/* size of all update data without anchor */
update_memory_size = sizeof(struct imsm_update_reshape_migration);
u = calloc(1, update_memory_size);
if (u == NULL) {
dprintf("error: cannot get memory for "
"imsm_create_metadata_update_for_migration\n");
return 0;
}
u->type = update_reshape_migration;
u->subdev = super->current_vol;
u->new_level = geo->level;
u->new_layout = geo->layout;
u->new_raid_disks = u->old_raid_disks = geo->raid_disks;
u->new_disks[0] = -1;
dev = get_imsm_dev(super, u->subdev);
if (dev) {
struct imsm_map *map;
map = get_imsm_map(dev, 0);
if (map)
previous_level = map->raid_level;
}
if ((geo->level == 5) && (previous_level == 0)) {
struct mdinfo *spares = NULL;
u->new_raid_disks++;
spares = get_spares_for_grow(st);
if ((spares == NULL) || (spares->array.spare_disks < 1)) {
free(u);
sysfs_free(spares);
update_memory_size = 0;
dprintf("error: cannot get spare device "
"for requested migration");
return 0;
}
sysfs_free(spares);
}
dprintf("imsm: reshape update preparation : OK\n");
*updatep = u;
return update_memory_size;
}
static void imsm_update_metadata_locally(struct supertype *st,
void *buf, int len)
{
@ -7394,9 +7479,26 @@ static int imsm_reshape_super(struct supertype *st, long long size, int level,
case CH_TAKEOVER:
ret_val = imsm_takeover(st, &geo);
break;
case CH_MIGRATION:
case CH_MIGRATION: {
struct imsm_update_reshape_migration *u = NULL;
int len =
imsm_create_metadata_update_for_migration(
st, &geo, &u);
if (len < 1) {
dprintf("imsm: "
"Cannot prepare update\n");
break;
}
ret_val = 0;
break;
/* update metadata locally */
imsm_update_metadata_locally(st, u, len);
/* and possibly remotely */
if (st->update_tail)
append_metadata_update(st, u, len);
else
free(u);
}
break;
default:
ret_val = 1;
}