Grow: check container is idle before freezing it.

Before we freeze a container in preparation for growing a subarray, we
need to be sure all the subarrays are idle.

This test is racy as recovery could start at any moment following a
failure.  However it is still useful as it stops us from even trying
to start a reshape while a reshape or recovery is active.

Signed-off-by: NeilBrown <neilb@suse.de>
This commit is contained in:
NeilBrown 2010-12-16 09:07:51 +11:00
parent 11877f4dc2
commit d7ca196cbd
1 changed files with 33 additions and 13 deletions

46
Grow.c
View File

@ -467,17 +467,41 @@ 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 check_idle(struct supertype *st)
{
/* Check that all member arrays for this container, or the
* container of this array, are idle
*/
int container_dev = (st->container_dev != NoMdDev
? st->container_dev : st->devnum);
char container[40];
struct mdstat_ent *ent, *e;
int is_idle = 1;
fmt_devname(container, container_dev);
ent = mdstat_read(0, 0);
for (e = ent ; e; e = e->next) {
if (!is_container_member(e, container))
continue;
if (e->percent >= 0) {
is_idle = 0;
break;
}
}
free_mdstat(ent);
return is_idle;
}
static int freeze_container(struct supertype *st)
{
int container_dev = (st->container_dev != NoMdDev
? st->container_dev : st->devnum);
char *container = devnum2devname(container_dev);
char container[40];
if (!container) {
fprintf(stderr, Name
": could not determine container name, freeze aborted\n");
return -2;
}
if (!check_idle(st))
return -1;
fmt_devname(container, container_dev);
if (block_monitor(container, 1)) {
fprintf(stderr, Name ": failed to freeze container\n");
@ -491,13 +515,9 @@ 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;
}
char container[40];
fmt_devname(container, container_dev);
unblock_monitor(container, 1);
}