Use new struct context and struct shape in Grow_reshape

Signed-off-by: NeilBrown <neilb@suse.de>
This commit is contained in:
NeilBrown 2012-07-09 17:22:09 +10:00
parent 99cc42f4a9
commit 32754b7d84
3 changed files with 72 additions and 78 deletions

138
Grow.c
View File

@ -1428,11 +1428,9 @@ static int reshape_container(char *container, char *devname,
char *backup_file, char *backup_file,
int verbose, int restart, int freeze_reshape); int verbose, int restart, int freeze_reshape);
int Grow_reshape(char *devname, int fd, int verbose, char *backup_file, int Grow_reshape(char *devname, int fd,
unsigned long long size,
int level, char *layout_str, int chunksize, int raid_disks,
struct mddev_dev *devlist, struct mddev_dev *devlist,
int assume_clean, int force) struct context *c, struct shape *s)
{ {
/* Make some changes in the shape of an array. /* Make some changes in the shape of an array.
* The kernel must support the change. * The kernel must support the change.
@ -1474,8 +1472,8 @@ int Grow_reshape(char *devname, int fd, int verbose, char *backup_file,
return 1; return 1;
} }
if (size > 0 && if (s->size > 0 &&
(chunksize || level!= UnSet || layout_str || raid_disks)) { (s->chunk || s->level!= UnSet || s->layout_str || s->raiddisks)) {
pr_err("cannot change component size at the same time " pr_err("cannot change component size at the same time "
"as other changes.\n" "as other changes.\n"
" Change size first, then check data is intact before " " Change size first, then check data is intact before "
@ -1483,7 +1481,7 @@ int Grow_reshape(char *devname, int fd, int verbose, char *backup_file,
return 1; return 1;
} }
if (raid_disks && raid_disks < array.raid_disks && array.level > 1 && if (s->raiddisks && s->raiddisks < array.raid_disks && array.level > 1 &&
get_linux_version() < 2006032 && get_linux_version() < 2006032 &&
!check_env("MDADM_FORCE_FEWER")) { !check_env("MDADM_FORCE_FEWER")) {
pr_err("reducing the number of devices is not safe before Linux 2.6.32\n" pr_err("reducing the number of devices is not safe before Linux 2.6.32\n"
@ -1496,7 +1494,7 @@ int Grow_reshape(char *devname, int fd, int verbose, char *backup_file,
pr_err("Unable to determine metadata format for %s\n", devname); pr_err("Unable to determine metadata format for %s\n", devname);
return 1; return 1;
} }
if (raid_disks > st->max_devs) { if (s->raiddisks > st->max_devs) {
pr_err("Cannot increase raid-disks on this array" pr_err("Cannot increase raid-disks on this array"
" beyond %d\n", st->max_devs); " beyond %d\n", st->max_devs);
return 1; return 1;
@ -1574,14 +1572,14 @@ int Grow_reshape(char *devname, int fd, int verbose, char *backup_file,
added_disks = 0; added_disks = 0;
for (dv = devlist; dv; dv = dv->next) for (dv = devlist; dv; dv = dv->next)
added_disks++; added_disks++;
if (raid_disks > array.raid_disks && if (s->raiddisks > array.raid_disks &&
array.spare_disks +added_disks < (raid_disks - array.raid_disks) && array.spare_disks +added_disks < (s->raiddisks - array.raid_disks) &&
!force) { !c->force) {
pr_err("Need %d spare%s to avoid degraded array," pr_err("Need %d spare%s to avoid degraded array,"
" and only have %d.\n" " and only have %d.\n"
" Use --force to over-ride this check.\n", " Use --force to over-ride this check.\n",
raid_disks - array.raid_disks, s->raiddisks - array.raid_disks,
raid_disks - array.raid_disks == 1 ? "" : "s", s->raiddisks - array.raid_disks == 1 ? "" : "s",
array.spare_disks + added_disks); array.spare_disks + added_disks);
return 1; return 1;
} }
@ -1611,7 +1609,7 @@ int Grow_reshape(char *devname, int fd, int verbose, char *backup_file,
} }
/* ========= set size =============== */ /* ========= set size =============== */
if (size > 0 && (size == MAX_DISKS || size != (unsigned)array.size)) { if (s->size > 0 && (s->size == MAX_DISKS || s->size != (unsigned)array.size)) {
unsigned long long orig_size = get_component_size(fd)/2; unsigned long long orig_size = get_component_size(fd)/2;
unsigned long long min_csize; unsigned long long min_csize;
struct mdinfo *mdi; struct mdinfo *mdi;
@ -1620,8 +1618,8 @@ int Grow_reshape(char *devname, int fd, int verbose, char *backup_file,
if (orig_size == 0) if (orig_size == 0)
orig_size = (unsigned) array.size; orig_size = (unsigned) array.size;
if (reshape_super(st, size, UnSet, UnSet, 0, 0, UnSet, NULL, if (reshape_super(st, s->size, UnSet, UnSet, 0, 0, UnSet, NULL,
devname, APPLY_METADATA_CHANGES, verbose > 0)) { devname, APPLY_METADATA_CHANGES, c->verbose > 0)) {
rv = 1; rv = 1;
goto release; goto release;
} }
@ -1643,7 +1641,7 @@ int Grow_reshape(char *devname, int fd, int verbose, char *backup_file,
dprintf("Metadata size correction from %llu to " dprintf("Metadata size correction from %llu to "
"%llu (%llu)\n", orig_size, new_size, "%llu (%llu)\n", orig_size, new_size,
new_size * data_disks); new_size * data_disks);
size = new_size; s->size = new_size;
sysfs_free(sizeinfo); sysfs_free(sizeinfo);
} }
} }
@ -1657,7 +1655,7 @@ int Grow_reshape(char *devname, int fd, int verbose, char *backup_file,
rv = 0; rv = 0;
for (mdi = sra->devs; mdi; mdi = mdi->next) { for (mdi = sra->devs; mdi; mdi = mdi->next) {
if (sysfs_set_num(sra, mdi, "size", if (sysfs_set_num(sra, mdi, "size",
size == MAX_SIZE ? 0 : size) < 0) { s->size == MAX_SIZE ? 0 : s->size) < 0) {
/* Probably kernel refusing to let us /* Probably kernel refusing to let us
* reduce the size - not an error. * reduce the size - not an error.
*/ */
@ -1682,19 +1680,19 @@ int Grow_reshape(char *devname, int fd, int verbose, char *backup_file,
"array members.\n"); "array members.\n");
goto size_change_error; goto size_change_error;
} }
if (min_csize && size > min_csize) { if (min_csize && s->size > min_csize) {
pr_err("Cannot safely make this array " pr_err("Cannot safely make this array "
"use more than 2TB per device on this kernel.\n"); "use more than 2TB per device on this kernel.\n");
rv = 1; rv = 1;
goto size_change_error; goto size_change_error;
} }
if (min_csize && size == MAX_SIZE) { if (min_csize && s->size == MAX_SIZE) {
/* Don't let the kernel choose a size - it will get /* Don't let the kernel choose a size - it will get
* it wrong * it wrong
*/ */
pr_err("Limited v0.90 array to " pr_err("Limited v0.90 array to "
"2TB per device\n"); "2TB per device\n");
size = min_csize; s->size = min_csize;
} }
if (st->ss->external) { if (st->ss->external) {
if (sra->array.level == 0) { if (sra->array.level == 0) {
@ -1718,14 +1716,14 @@ int Grow_reshape(char *devname, int fd, int verbose, char *backup_file,
st->update_tail = &st->updates; st->update_tail = &st->updates;
} }
array.size = size == MAX_SIZE ? 0 : size; array.size = s->size == MAX_SIZE ? 0 : s->size;
if ((unsigned)array.size != size) { if ((unsigned)array.size != s->size) {
/* got truncated to 32bit, write to /* got truncated to 32bit, write to
* component_size instead * component_size instead
*/ */
if (sra) if (sra)
rv = sysfs_set_num(sra, NULL, rv = sysfs_set_num(sra, NULL,
"component_size", size); "component_size", s->size);
else else
rv = -1; rv = -1;
} else { } else {
@ -1756,7 +1754,7 @@ size_change_error:
if (reshape_super(st, orig_size, UnSet, UnSet, 0, 0, if (reshape_super(st, orig_size, UnSet, UnSet, 0, 0,
UnSet, NULL, devname, UnSet, NULL, devname,
ROLLBACK_METADATA_CHANGES, ROLLBACK_METADATA_CHANGES,
verbose) == 0) c->verbose) == 0)
sync_metadata(st); sync_metadata(st);
pr_err("Cannot set device size for %s: %s\n", pr_err("Cannot set device size for %s: %s\n",
devname, strerror(err)); devname, strerror(err));
@ -1766,7 +1764,7 @@ size_change_error:
rv = 1; rv = 1;
goto release; goto release;
} }
if (assume_clean) { if (s->assume_clean) {
/* This will fail on kernels newer than 3.0 unless /* This will fail on kernels newer than 3.0 unless
* a backport has been arranged. * a backport has been arranged.
*/ */
@ -1775,33 +1773,33 @@ size_change_error:
pr_err("--assume-clean not support with --grow on this kernel\n"); pr_err("--assume-clean not support with --grow on this kernel\n");
} }
ioctl(fd, GET_ARRAY_INFO, &array); ioctl(fd, GET_ARRAY_INFO, &array);
size = get_component_size(fd)/2; s->size = get_component_size(fd)/2;
if (size == 0) if (s->size == 0)
size = array.size; s->size = array.size;
if (verbose >= 0) { if (c->verbose >= 0) {
if (size == orig_size) if (s->size == orig_size)
pr_err("component size of %s " pr_err("component size of %s "
"unchanged at %lluK\n", "unchanged at %lluK\n",
devname, size); devname, s->size);
else else
pr_err("component size of %s " pr_err("component size of %s "
"has been set to %lluK\n", "has been set to %lluK\n",
devname, size); devname, s->size);
} }
changed = 1; changed = 1;
} else if (array.level != LEVEL_CONTAINER) { } else if (array.level != LEVEL_CONTAINER) {
size = get_component_size(fd)/2; s->size = get_component_size(fd)/2;
if (size == 0) if (s->size == 0)
size = array.size; s->size = array.size;
} }
/* See if there is anything else to do */ /* See if there is anything else to do */
if ((level == UnSet || level == array.level) && if ((s->level == UnSet || s->level == array.level) &&
(layout_str == NULL) && (s->layout_str == NULL) &&
(chunksize == 0 || chunksize == array.chunk_size) && (s->chunk == 0 || s->chunk == array.chunk_size) &&
(raid_disks == 0 || raid_disks == array.raid_disks)) { (s->raiddisks == 0 || s->raiddisks == array.raid_disks)) {
/* Nothing more to do */ /* Nothing more to do */
if (!changed && verbose >= 0) if (!changed && c->verbose >= 0)
pr_err("%s: no change requested\n", pr_err("%s: no change requested\n",
devname); devname);
goto release; goto release;
@ -1813,9 +1811,9 @@ size_change_error:
* - far_copies == 1 * - far_copies == 1
* - near_copies == 2 * - near_copies == 2
*/ */
if ((level == 0 && array.level == 10 && sra && if ((s->level == 0 && array.level == 10 && sra &&
array.layout == ((1 << 8) + 2) && !(array.raid_disks & 1)) || array.layout == ((1 << 8) + 2) && !(array.raid_disks & 1)) ||
(level == 0 && array.level == 1 && sra)) { (s->level == 0 && array.level == 1 && sra)) {
int err; int err;
err = remove_disks_for_takeover(st, sra, array.layout); err = remove_disks_for_takeover(st, sra, array.layout);
if (err) { if (err) {
@ -1837,17 +1835,17 @@ size_change_error:
info.array = array; info.array = array;
sysfs_init(&info, fd, NoMdDev); sysfs_init(&info, fd, NoMdDev);
strcpy(info.text_version, sra->text_version); strcpy(info.text_version, sra->text_version);
info.component_size = size*2; info.component_size = s->size*2;
info.new_level = level; info.new_level = s->level;
info.new_chunk = chunksize * 1024; info.new_chunk = s->chunk * 1024;
if (info.array.level == LEVEL_CONTAINER) { if (info.array.level == LEVEL_CONTAINER) {
info.delta_disks = UnSet; info.delta_disks = UnSet;
info.array.raid_disks = raid_disks; info.array.raid_disks = s->raiddisks;
} else if (raid_disks) } else if (s->raiddisks)
info.delta_disks = raid_disks - info.array.raid_disks; info.delta_disks = s->raiddisks - info.array.raid_disks;
else else
info.delta_disks = UnSet; info.delta_disks = UnSet;
if (layout_str == NULL) { if (s->layout_str == NULL) {
info.new_layout = UnSet; info.new_layout = UnSet;
if (info.array.level == 6 && if (info.array.level == 6 &&
(info.new_level == 6 || info.new_level == UnSet) && (info.new_level == 6 || info.new_level == UnSet) &&
@ -1861,8 +1859,8 @@ size_change_error:
rv = 1; rv = 1;
goto release; goto release;
} }
} else if (strcmp(layout_str, "normalise") == 0 || } else if (strcmp(s->layout_str, "normalise") == 0 ||
strcmp(layout_str, "normalize") == 0) { strcmp(s->layout_str, "normalize") == 0) {
/* If we have a -6 RAID6 layout, remove the '-6'. */ /* If we have a -6 RAID6 layout, remove the '-6'. */
info.new_layout = UnSet; info.new_layout = UnSet;
if (info.array.level == 6 && info.new_level == UnSet) { if (info.array.level == 6 && info.new_level == UnSet) {
@ -1875,11 +1873,11 @@ size_change_error:
} }
} else { } else {
pr_err("%s is only meaningful when reshaping" pr_err("%s is only meaningful when reshaping"
" a RAID6 array.\n", layout_str); " a RAID6 array.\n", s->layout_str);
rv = 1; rv = 1;
goto release; goto release;
} }
} else if (strcmp(layout_str, "preserve") == 0) { } else if (strcmp(s->layout_str, "preserve") == 0) {
/* This means that a non-standard RAID6 layout /* This means that a non-standard RAID6 layout
* is OK. * is OK.
* In particular: * In particular:
@ -1898,7 +1896,7 @@ size_change_error:
info.new_layout = map_name(r6layout, l); info.new_layout = map_name(r6layout, l);
} else { } else {
pr_err("%s in only meaningful when reshaping" pr_err("%s in only meaningful when reshaping"
" to RAID6\n", layout_str); " to RAID6\n", s->layout_str);
rv = 1; rv = 1;
goto release; goto release;
} }
@ -1908,16 +1906,16 @@ size_change_error:
l = info.array.level; l = info.array.level;
switch (l) { switch (l) {
case 5: case 5:
info.new_layout = map_name(r5layout, layout_str); info.new_layout = map_name(r5layout, s->layout_str);
break; break;
case 6: case 6:
info.new_layout = map_name(r6layout, layout_str); info.new_layout = map_name(r6layout, s->layout_str);
break; break;
case 10: case 10:
info.new_layout = parse_layout_10(layout_str); info.new_layout = parse_layout_10(s->layout_str);
break; break;
case LEVEL_FAULTY: case LEVEL_FAULTY:
info.new_layout = parse_layout_faulty(layout_str); info.new_layout = parse_layout_faulty(s->layout_str);
break; break;
default: default:
pr_err("layout not meaningful" pr_err("layout not meaningful"
@ -1928,26 +1926,26 @@ size_change_error:
if (info.new_layout == UnSet) { if (info.new_layout == UnSet) {
pr_err("layout %s not understood" pr_err("layout %s not understood"
" for this level\n", " for this level\n",
layout_str); s->layout_str);
rv = 1; rv = 1;
goto release; goto release;
} }
} }
if (array.level == LEVEL_FAULTY) { if (array.level == LEVEL_FAULTY) {
if (level != UnSet && level != array.level) { if (s->level != UnSet && s->level != array.level) {
pr_err("cannot change level of Faulty device\n"); pr_err("cannot change level of Faulty device\n");
rv =1 ; rv =1 ;
} }
if (chunksize) { if (s->chunk) {
pr_err("cannot set chunksize of Faulty device\n"); pr_err("cannot set chunksize of Faulty device\n");
rv =1 ; rv =1 ;
} }
if (raid_disks && raid_disks != 1) { if (s->raiddisks && s->raiddisks != 1) {
pr_err("cannot set raid_disks of Faulty device\n"); pr_err("cannot set raid_disks of Faulty device\n");
rv =1 ; rv =1 ;
} }
if (layout_str) { if (s->layout_str) {
if (ioctl(fd, GET_ARRAY_INFO, &array) != 0) { if (ioctl(fd, GET_ARRAY_INFO, &array) != 0) {
dprintf("Cannot get array information.\n"); dprintf("Cannot get array information.\n");
goto release; goto release;
@ -1956,7 +1954,7 @@ size_change_error:
if (ioctl(fd, SET_ARRAY_INFO, &array) != 0) { if (ioctl(fd, SET_ARRAY_INFO, &array) != 0) {
pr_err("failed to set new layout\n"); pr_err("failed to set new layout\n");
rv = 1; rv = 1;
} else if (verbose >= 0) } else if (c->verbose >= 0)
printf("layout for %s set to %d\n", printf("layout for %s set to %d\n",
devname, array.layout); devname, array.layout);
} }
@ -1970,7 +1968,7 @@ size_change_error:
* performed at the level of the container * performed at the level of the container
*/ */
rv = reshape_container(container, devname, -1, st, &info, rv = reshape_container(container, devname, -1, st, &info,
force, backup_file, verbose, 0, 0); c->force, c->backup_file, c->verbose, 0, 0);
frozen = 0; frozen = 0;
} else { } else {
/* get spare devices from external metadata /* get spare devices from external metadata
@ -1992,14 +1990,14 @@ size_change_error:
if (reshape_super(st, -1, info.new_level, if (reshape_super(st, -1, 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,
backup_file, devname, APPLY_METADATA_CHANGES, c->backup_file, devname, APPLY_METADATA_CHANGES,
verbose)) { c->verbose)) {
rv = 1; rv = 1;
goto release; goto release;
} }
sync_metadata(st); sync_metadata(st);
rv = reshape_array(container, fd, devname, st, &info, force, rv = reshape_array(container, fd, devname, st, &info, c->force,
devlist, backup_file, verbose, 0, 0, 0); devlist, c->backup_file, c->verbose, 0, 0, 0);
frozen = 0; frozen = 0;
} }
release: release:

View File

@ -1450,10 +1450,8 @@ int main(int argc, char *argv[])
c.verbose); c.verbose);
else if (s.size > 0 || s.raiddisks || s.layout_str != NULL else if (s.size > 0 || s.raiddisks || s.layout_str != NULL
|| s.chunk != 0 || s.level != UnSet) { || s.chunk != 0 || s.level != UnSet) {
rv = Grow_reshape(devlist->devname, mdfd, c.verbose, c.backup_file, rv = Grow_reshape(devlist->devname, mdfd,
s.size, s.level, s.layout_str, s.chunk, s.raiddisks, devlist->next, &c, &s);
devlist->next,
s.assume_clean, c.force);
} else if (array_size == 0) } else if (array_size == 0)
pr_err("no changes to --grow\n"); pr_err("no changes to --grow\n");
break; break;

View File

@ -1088,11 +1088,9 @@ extern int Manage_subdevs(char *devname, int fd,
extern int autodetect(void); extern int autodetect(void);
extern int Grow_Add_device(char *devname, int fd, char *newdev); extern int Grow_Add_device(char *devname, int fd, char *newdev);
extern int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int delay, int write_behind, int force); extern int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int delay, int write_behind, int force);
extern int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, extern int Grow_reshape(char *devname, int fd,
unsigned long long size,
int level, char *layout_str, int chunksize, int raid_disks,
struct mddev_dev *devlist, struct mddev_dev *devlist,
int assume_clean, int force); struct context *c, struct shape *s);
extern int Grow_restart(struct supertype *st, struct mdinfo *info, extern int Grow_restart(struct supertype *st, struct mdinfo *info,
int *fdlist, int cnt, char *backup_file, int verbose); int *fdlist, int cnt, char *backup_file, int verbose);
extern int Grow_continue(int mdfd, struct supertype *st, extern int Grow_continue(int mdfd, struct supertype *st,