FIX: get updated information from metadata

Metadata is not modified by metadata preparation handler.
It has to be read again from array.
There is 2 read required:
1. before 'for' entry to get updated information after reshape_super() call
2. inside 'for' loop to get updated information for every processed array
  (it can happen /i.e. imsm case/ that container operation is a set of array operations
   and information in metadata is changed after every loop).

Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
This commit is contained in:
Adam Kwolek 2011-01-06 16:56:05 +11:00 committed by NeilBrown
parent d677e0b8ec
commit 1bb174ba0b
1 changed files with 52 additions and 16 deletions

68
Grow.c
View File

@ -2040,6 +2040,21 @@ static int reshape_array(char *container, int fd, char *devname,
release: release:
if (rv) {
unfreeze(st, frozen);
return rv;
}
if (container)
ping_monitor(container);
if (st->ss->external) {
/* Re-load the metadata as much could have changed */
int cfd = open_dev(st->container_dev);
if (cfd >= 0) {
st->ss->free_super(st);
st->ss->load_container(st, cfd, container);
close(cfd);
}
}
if (rv && orig_level != UnSet && sra) { if (rv && orig_level != UnSet && sra) {
c = map_num(pers, orig_level); c = map_num(pers, orig_level);
if (c && sysfs_set_str(sra, NULL, "level", c) == 0) if (c && sysfs_set_str(sra, NULL, "level", c) == 0)
@ -2056,7 +2071,8 @@ int reshape_container(char *container, int cfd, char *devname,
char *backup_file, char *backup_file,
int quiet) int quiet)
{ {
struct mdinfo *cc; struct mdinfo *cc = NULL;
if (reshape_super(st, info->component_size, info->new_level, if (reshape_super(st, info->component_size, info->new_level,
info->new_layout, info->new_chunk, info->new_layout, info->new_chunk,
info->array.raid_disks + info->delta_disks, info->array.raid_disks + info->delta_disks,
@ -2065,10 +2081,9 @@ int reshape_container(char *container, int cfd, char *devname,
sync_metadata(st); sync_metadata(st);
cc = st->ss->container_content(st, NULL); /* ping monitor to be sure that update is on disk
*/
if (!cc) ping_monitor(container);
return 1;
switch (fork()) { switch (fork()) {
case -1: /* error */ case -1: /* error */
@ -2081,21 +2096,39 @@ int reshape_container(char *container, int cfd, char *devname,
break; break;
} }
/* For each member array, we need to perform the reshape */ while(1) {
for (; cc; cc = cc->next) { /* For each member array with reshape_active,
* we need to perform the reshape.
* We pick the first array that needs reshaping and
* reshape it. reshape_array() will re-read the metadata
* so the next time through a different array should be
* ready for reshape.
*/
struct mdinfo *content;
int rv; int rv;
int fd; int fd;
struct mdstat_ent *mdstat; struct mdstat_ent *mdstat;
char *subarray = strchr(cc->text_version+1, '/')+1;
char *adev; char *adev;
if (!cc->reshape_active) sysfs_free(cc);
continue;
mdstat = mdstat_by_subdev(subarray, devname2devnum(container)); cc = st->ss->container_content(st, NULL);
for (content = cc; content ; content = content->next) {
char *subarray;
if (!content->reshape_active)
continue;
subarray = strchr(content->text_version+1, '/')+1;
mdstat = mdstat_by_subdev(subarray,
devname2devnum(container));
if (!mdstat)
continue;
break;
}
if (!content)
break;
if (!mdstat)
continue;
fd = open_dev_excl(mdstat->devnum); fd = open_dev_excl(mdstat->devnum);
if (fd < 0) if (fd < 0)
break; break;
@ -2103,15 +2136,18 @@ int reshape_container(char *container, int cfd, char *devname,
dev2minor(mdstat->devnum), dev2minor(mdstat->devnum),
0); 0);
if (!adev) if (!adev)
adev = cc->text_version; adev = content->text_version;
sysfs_init(cc, fd, mdstat->devnum); sysfs_init(content, fd, mdstat->devnum);
rv = reshape_array(container, fd, adev, st, cc, force,
rv = reshape_array(container, fd, adev, st,
content, force,
backup_file, quiet, 1); backup_file, quiet, 1);
close(fd); close(fd);
if (rv) if (rv)
break; break;
} }
sysfs_free(cc);
exit(0); exit(0);
} }