External reshape (step 2): Freeze container
When growing the number of raid disks the reshape process will promote container-spares to subarray-spares (later the kernel promotes them to subarray-members in raid5_start_reshape()). The automatic spare promotion that mdmon performs upon seeing a degraded array must be disabled until the reshape process has been initiated. Otherwise, mdmon may start a rebuild before the reshape parameters can be specified. In the external case we arrange for the monitor to be blocked, and turn off the safemode delay. Mdmon is updated to check sync_action is not frozen before initiating recovery. Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: NeilBrown <neilb@suse.de>
This commit is contained in:
parent
7bc7119671
commit
7f2ba464e4
142
Grow.c
142
Grow.c
|
@ -458,29 +458,80 @@ static int child_same_size(int afd, struct mdinfo *sra, unsigned long blocks,
|
|||
int disks, int chunk, int level, int layout, int data,
|
||||
int dests, int *destfd, unsigned long long *destoffsets);
|
||||
|
||||
static int freeze_array(struct mdinfo *sra)
|
||||
static int freeze_container(struct supertype *st)
|
||||
{
|
||||
/* Try to freeze resync on this array.
|
||||
* Return -1 if the array is busy,
|
||||
* return 0 if this kernel doesn't support 'frozen'
|
||||
* return 1 if it worked.
|
||||
*/
|
||||
char buf[20];
|
||||
if (sysfs_get_str(sra, NULL, "sync_action", buf, 20) <= 0)
|
||||
return 0;
|
||||
if (strcmp(buf, "idle\n") != 0 &&
|
||||
strcmp(buf, "frozen\n") != 0)
|
||||
return -1;
|
||||
if (sysfs_set_str(sra, NULL, "sync_action", "frozen") < 0)
|
||||
return 0;
|
||||
int container_dev = (st->container_dev != NoMdDev
|
||||
? st->container_dev : st->devnum);
|
||||
char *container = devnum2devname(container_dev);
|
||||
|
||||
if (!container) {
|
||||
fprintf(stderr, Name
|
||||
": could not determine container name, freeze aborted\n");
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (block_monitor(container, 1)) {
|
||||
fprintf(stderr, Name ": failed to freeze container\n");
|
||||
return -2;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void unfreeze_array(struct mdinfo *sra, int frozen)
|
||||
static void unfreeze_container(struct supertype *st)
|
||||
{
|
||||
int container_dev = (st->container_dev != NoMdDev
|
||||
? st->container_dev : st->devnum);
|
||||
char *container = devnum2devname(container_dev);
|
||||
|
||||
if (!container) {
|
||||
fprintf(stderr, Name
|
||||
": could not determine container name, unfreeze aborted\n");
|
||||
return;
|
||||
}
|
||||
|
||||
unblock_monitor(container, 1);
|
||||
}
|
||||
|
||||
static int freeze(struct supertype *st)
|
||||
{
|
||||
/* Try to freeze resync/rebuild on this array/container.
|
||||
* Return -1 if the array is busy,
|
||||
* return -2 container cannot be frozen,
|
||||
* return 0 if this kernel doesn't support 'frozen'
|
||||
* return 1 if it worked.
|
||||
*/
|
||||
if (st->ss->external)
|
||||
return freeze_container(st);
|
||||
else {
|
||||
struct mdinfo *sra = sysfs_read(-1, st->devnum, GET_VERSION);
|
||||
int err;
|
||||
|
||||
if (!sra)
|
||||
return -1;
|
||||
err = sysfs_freeze_array(sra);
|
||||
sysfs_free(sra);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
static void unfreeze(struct supertype *st, int frozen)
|
||||
{
|
||||
/* If 'frozen' is 1, unfreeze the array */
|
||||
if (frozen > 0)
|
||||
sysfs_set_str(sra, NULL, "sync_action", "idle");
|
||||
if (frozen <= 0)
|
||||
return;
|
||||
|
||||
if (st->ss->external)
|
||||
return unfreeze_container(st);
|
||||
else {
|
||||
struct mdinfo *sra = sysfs_read(-1, st->devnum, GET_VERSION);
|
||||
|
||||
if (sra)
|
||||
sysfs_set_str(sra, NULL, "sync_action", "idle");
|
||||
else
|
||||
fprintf(stderr, Name ": failed to unfreeze array\n");
|
||||
sysfs_free(sra);
|
||||
}
|
||||
}
|
||||
|
||||
static void wait_reshape(struct mdinfo *sra)
|
||||
|
@ -670,38 +721,40 @@ static void revert_container_raid_disks(struct supertype *st, int fd, char *cont
|
|||
return;
|
||||
}
|
||||
|
||||
if (st->ss->load_container(st, fd, NULL)) {
|
||||
fprintf(stderr, Name
|
||||
": failed read metadata while aborting reshape\n");
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
for (e = ent; e; e = e->next) {
|
||||
int level_fixed = 0, disks_fixed = 0;
|
||||
struct mdinfo *sub, prev;
|
||||
struct mdinfo *sub, *prev;
|
||||
char *subarray;
|
||||
|
||||
if (!is_container_member(e, container))
|
||||
continue;
|
||||
|
||||
st->ss->free_super(st);
|
||||
sprintf(st->subarray, "%s", to_subarray(e, container));
|
||||
if (st->ss->load_super(st, fd, NULL)) {
|
||||
fprintf(stderr, Name
|
||||
": failed read metadata while aborting reshape\n");
|
||||
continue;
|
||||
}
|
||||
st->ss->getinfo_super(st, &prev);
|
||||
subarray = to_subarray(e, container);
|
||||
prev = st->ss->container_content(st, subarray);
|
||||
|
||||
/* changing level might change raid_disks so we do it
|
||||
* first and then check if raid_disks still needs fixing
|
||||
*/
|
||||
if (map_name(pers, e->level) != prev.array.level) {
|
||||
if (map_name(pers, e->level) != prev->array.level) {
|
||||
sub = sysfs_read(-1, e->devnum, GET_VERSION);
|
||||
if (sub &&
|
||||
!sysfs_set_num(sub, NULL, "level", prev.array.level))
|
||||
!sysfs_set_num(sub, NULL, "level", prev->array.level))
|
||||
level_fixed = 1;
|
||||
sysfs_free(sub);
|
||||
} else
|
||||
level_fixed = 1;
|
||||
|
||||
sub = sysfs_read(-1, e->devnum, GET_DISKS);
|
||||
if (sub && sub->array.raid_disks != prev.array.raid_disks) {
|
||||
if (sub && sub->array.raid_disks != prev->array.raid_disks) {
|
||||
if (!subarray_set_num(container, sub, "raid_disks",
|
||||
prev.array.raid_disks))
|
||||
prev->array.raid_disks))
|
||||
disks_fixed = 1;
|
||||
} else if (sub)
|
||||
disks_fixed = 1;
|
||||
|
@ -710,9 +763,11 @@ static void revert_container_raid_disks(struct supertype *st, int fd, char *cont
|
|||
if (!disks_fixed || !level_fixed)
|
||||
fprintf(stderr, Name
|
||||
": failed to restore %s to a %d-disk %s array\n",
|
||||
e->dev, prev.array.raid_disks,
|
||||
map_num(pers, prev.array.level));
|
||||
e->dev, prev->array.raid_disks,
|
||||
map_num(pers, prev->array.level));
|
||||
free(prev);
|
||||
}
|
||||
st->ss->free_super(st);
|
||||
free_mdstat(ent);
|
||||
}
|
||||
|
||||
|
@ -801,6 +856,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
|
|||
*/
|
||||
if (st->ss->external) {
|
||||
int container_dev;
|
||||
int rv;
|
||||
|
||||
if (subarray) {
|
||||
container_dev = st->container_dev;
|
||||
|
@ -820,18 +876,25 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
|
|||
if (cfd < 0) {
|
||||
fprintf(stderr, Name ": Unable to open container for %s\n",
|
||||
devname);
|
||||
free(subarray);
|
||||
return 1;
|
||||
}
|
||||
|
||||
container = devnum2devname(st->devnum);
|
||||
if (!container) {
|
||||
fprintf(stderr, Name ": Could not determine container name\n");
|
||||
free(subarray);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (st->ss->load_super(st, cfd, NULL)) {
|
||||
if (subarray)
|
||||
rv = st->ss->load_container(st, cfd, NULL);
|
||||
else
|
||||
rv = st->ss->load_super(st, cfd, NULL);
|
||||
if (rv) {
|
||||
fprintf(stderr, Name ": Cannot read superblock for %s\n",
|
||||
devname);
|
||||
free(subarray);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -841,23 +904,25 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
|
|||
|
||||
sra = sysfs_read(fd, 0, GET_LEVEL);
|
||||
if (sra) {
|
||||
if (st->ss->external && st->subarray[0] == 0) {
|
||||
if (st->ss->external && subarray == NULL) {
|
||||
array.level = LEVEL_CONTAINER;
|
||||
sra->array.level = LEVEL_CONTAINER;
|
||||
}
|
||||
frozen = freeze_array(sra);
|
||||
} else {
|
||||
fprintf(stderr, Name ": failed to read sysfs parameters for %s\n",
|
||||
devname);
|
||||
return 1;
|
||||
}
|
||||
if (frozen < 0) {
|
||||
frozen = freeze(st);
|
||||
if (frozen < -1) {
|
||||
/* freeze() already spewed the reason */
|
||||
return 1;
|
||||
} else if (frozen < 0) {
|
||||
fprintf(stderr, Name ": %s is performing resync/recovery and cannot"
|
||||
" be reshaped\n", devname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* ========= set size =============== */
|
||||
if (size >= 0 && (size == 0 || size != array.size)) {
|
||||
long long orig_size = array.size;
|
||||
|
@ -1642,8 +1707,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
|
|||
if (c && sysfs_set_str(sra, NULL, "level", c) == 0)
|
||||
fprintf(stderr, Name ": aborting level change\n");
|
||||
}
|
||||
if (sra)
|
||||
unfreeze_array(sra, frozen);
|
||||
unfreeze(st, frozen);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue