static int reshape_super(struct supertype *st, long long size, int level,
int layout, int chunksize, int raid_disks,
- char *backup_file, char *dev, int verbose)
+ int delta_disks, char *backup_file, char *dev,
+ int verbose)
{
/* nothing extra to check in the native case */
if (!st->ss->external)
}
return st->ss->reshape_super(st, size, level, layout, chunksize,
- raid_disks, backup_file, dev, verbose);
+ raid_disks, delta_disks, backup_file, dev,
+ verbose);
}
static void sync_metadata(struct supertype *st)
}
memset(buf, 0, 512);
- for (i=0; i < blocks + 1 ; i++) {
+ for (i=0; i < blocks + 8 ; i++) {
if (write(*fdlist, buf, 512) != 512) {
fprintf(stderr, Name ": %s: cannot create"
" backup file %s: %s\n",
if (size >= 0 && (size == 0 || size != array.size)) {
long long orig_size = array.size;
- if (reshape_super(st, size, UnSet, UnSet, 0, 0, NULL, devname, !quiet)) {
+ if (reshape_super(st, size, UnSet, UnSet, 0, 0, UnSet, NULL,
+ devname, !quiet)) {
rv = 1;
goto release;
}
/* restore metadata */
if (reshape_super(st, orig_size, UnSet, UnSet, 0, 0,
- NULL, devname, !quiet) == 0)
+ UnSet, NULL, devname, !quiet) == 0)
sync_metadata(st);
fprintf(stderr, Name ": Cannot set device size for %s: %s\n",
devname, strerror(err));
if (reshape_super(st, info.component_size, info.new_level,
info.new_layout, info.new_chunk,
- info.array.raid_disks + info.delta_disks,
+ info.array.raid_disks, info.delta_disks,
backup_file, devname, quiet)) {
rv = 1;
goto release;
fprintf(stderr, Name ": level of %s changed to %s\n",
devname, c);
orig_level = info->array.level;
+ sysfs_freeze_array(info);
if (reshape.level > 0 && st->ss->external) {
/* make sure mdmon is aware of the new level */
/* Now we need to open all these devices so we can read/write.
*/
- nrdisks = array.raid_disks + sra->array.spare_disks;
+ nrdisks = max(reshape.before.data_disks,
+ reshape.after.data_disks) + reshape.parity
+ + sra->array.spare_disks;
fdlist = malloc((1+nrdisks) * sizeof(int));
offsets = malloc((1+nrdisks) * sizeof(offsets[0]));
if (!fdlist || !offsets) {
goto release;
}
- d = reshape_prepare_fdlist(devname, sra, array.raid_disks,
+ odisks = reshape.before.data_disks + reshape.parity;
+ d = reshape_prepare_fdlist(devname, sra, odisks,
nrdisks, blocks, backup_file,
fdlist, offsets);
if (d < 0) {
fd = -1;
mlockall(MCL_FUTURE);
- odisks = reshape.before.data_disks + reshape.parity;
-
if (st->ss->external) {
/* metadata handler takes it from here */
done = st->ss->manage_reshape(
out:
if (forked)
return 0;
+ unfreeze(st);
exit(0);
release:
*/
if (reshape_super(st, -1, info->new_level,
info->new_layout, info->new_chunk,
- info->array.raid_disks + info->delta_disks,
- backup_file, devname, quiet))
+ info->array.raid_disks, info->delta_disks,
+ backup_file, devname, quiet)) {
+ unfreeze(st);
return 1;
+ }
sync_metadata(st);
switch (fork()) {
case -1: /* error */
perror("Cannot fork to complete reshape\n");
+ unfreeze(st);
return 1;
default: /* parent */
printf(Name ": multi-array reshape continues in background\n");
/* Round to chunk size as some kernels give an erroneously high number */
max_progress /= info->new_chunk/512;
max_progress *= info->new_chunk/512;
+ /* And round to old chunk size as the kernel wants that */
+ max_progress /= info->array.chunk_size/512;
+ max_progress *= info->array.chunk_size/512;
/* Limit progress to the whole device */
if (max_progress > info->component_size)
max_progress = info->component_size;
if (offset < suspend_point/data)
break;
}
+ if (actual_stripes == 0)
+ break;
grow_backup(sra, offset, actual_stripes,
fds, offsets,
disks, chunk, level, layout,