char *backup_file, int invalid_backup,
int readonly, int runstop,
char *update, char *homehost, int require_homehost,
- int verbose, int force)
+ int verbose, int force, int freeze_reshape)
{
/*
* The task of Assemble is to find a collection of
int err;
err = assemble_container_content(st, mdfd, content, runstop,
chosen_name, verbose,
- backup_file);
+ backup_file, freeze_reshape);
close(mdfd);
return err;
}
#ifndef MDASSEMBLE
if (content->reshape_active &&
content->delta_disks <= 0)
- rv = Grow_continue(mdfd, st, content, backup_file);
+ rv = Grow_continue(mdfd, st, content,
+ backup_file, freeze_reshape);
else
#endif
rv = ioctl(mdfd, RUN_ARRAY, NULL);
int assemble_container_content(struct supertype *st, int mdfd,
struct mdinfo *content, int runstop,
char *chosen_name, int verbose,
- char *backup_file)
+ char *backup_file, int freeze_reshape)
{
struct mdinfo *dev, *sra;
int working = 0, preexist = 0;
spare, backup_file, verbose) == 1)
return 1;
- err = Grow_continue(mdfd, st, content, backup_file);
+ err = Grow_continue(mdfd, st, content, backup_file,
+ freeze_reshape);
} else switch(content->array.level) {
case LEVEL_LINEAR:
case LEVEL_MULTIPATH:
struct supertype *st, struct mdinfo *info,
int force, struct mddev_dev *devlist,
char *backup_file, int quiet, int forked,
- int restart);
+ int restart, int freeze_reshape);
static int reshape_container(char *container, char *devname,
struct supertype *st,
struct mdinfo *info,
int force,
char *backup_file,
- int quiet, int restart);
+ int quiet, int restart, int freeze_reshape);
int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
long long size,
* performed at the level of the container
*/
rv = reshape_container(container, devname, st, &info,
- force, backup_file, quiet, 0);
+ force, backup_file, quiet, 0, 0);
frozen = 0;
} else {
/* get spare devices from external metadata
}
sync_metadata(st);
rv = reshape_array(container, fd, devname, st, &info, force,
- devlist, backup_file, quiet, 0, 0);
+ devlist, backup_file, quiet, 0, 0, 0);
frozen = 0;
}
release:
struct supertype *st, struct mdinfo *info,
int force, struct mddev_dev *devlist,
char *backup_file, int quiet, int forked,
- int restart)
+ int restart, int freeze_reshape)
{
struct reshape reshape;
int spares_needed;
}
if (restart)
sysfs_set_str(sra, NULL, "array_state", "active");
+ if (freeze_reshape) {
+ free(fdlist);
+ free(offsets);
+ sysfs_free(sra);
+ fprintf(stderr, Name ": Reshape has to be continued from"
+ " location %llu when root fileststem has been mounted\n",
+ sra->reshape_progress);
+ return 1;
+ }
/* Now we just need to kick off the reshape and watch, while
* handling backups of the data...
struct mdinfo *info,
int force,
char *backup_file,
- int quiet, int restart)
+ int quiet, int restart, int freeze_reshape)
{
struct mdinfo *cc = NULL;
int rv = restart;
unfreeze(st);
return 1;
default: /* parent */
- printf(Name ": multi-array reshape continues in background\n");
+ if (!freeze_reshape)
+ printf(Name ": multi-array reshape continues"
+ " in background\n");
return 0;
case 0: /* child */
map_fork();
rv = reshape_array(container, fd, adev, st,
content, force, NULL,
- backup_file, quiet, 1, restart);
+ backup_file, quiet, 1, restart,
+ freeze_reshape);
close(fd);
+
+ if (freeze_reshape) {
+ sysfs_free(cc);
+ exit(0);
+ }
+
restart = 0;
if (rv)
break;
}
int Grow_continue(int mdfd, struct supertype *st, struct mdinfo *info,
- char *backup_file)
+ char *backup_file, int freeze_reshape)
{
char buf[40];
char *container = NULL;
close(cfd);
return reshape_container(container, NULL,
st, info, 0, backup_file,
- 0, 1);
+ 0, 1, freeze_reshape);
}
}
return reshape_array(container, mdfd, "array", st, info, 1,
- NULL, backup_file, 0, 0, 1);
+ NULL, backup_file, 0, 0, 1, freeze_reshape);
}
static int Incremental_container(struct supertype *st, char *devname,
char *homehost,
- int verbose, int runstop, int autof);
+ int verbose, int runstop, int autof,
+ int freeze_reshape);
static struct mddev_ident *search_mdstat(struct supertype *st,
struct mdinfo *info,
int Incremental(char *devname, int verbose, int runstop,
struct supertype *st, char *homehost, int require_homehost,
- int autof)
+ int autof, int freeze_reshape)
{
/* Add this device to an array, creating the array if necessary
* and starting the array if sensible or - if runstop>0 - if possible.
close(dfd);
if (!rv && st->ss->container_content)
return Incremental_container(st, devname, homehost,
- verbose, runstop, autof);
+ verbose, runstop, autof,
+ freeze_reshape);
fprintf(stderr, Name ": %s is not part of an md array.\n",
devname);
close(mdfd);
sysfs_free(sra);
rv = Incremental(chosen_name, verbose, runstop,
- NULL, homehost, require_homehost, autof);
+ NULL, homehost, require_homehost, autof,
+ freeze_reshape);
if (rv == 1)
/* Don't fail the whole -I if a subarray didn't
* have enough devices to start yet
static int Incremental_container(struct supertype *st, char *devname,
char *homehost, int verbose,
- int runstop, int autof)
+ int runstop, int autof, int freeze_reshape)
{
/* Collect the contents of this container and for each
* array, choose a device name and assemble the array.
}
assemble_container_content(st, mdfd, ra, runstop,
- chosen_name, verbose, NULL);
+ chosen_name, verbose, NULL,
+ freeze_reshape);
close(mdfd);
}
{"scan", 0, 0, 's'},
{"force", 0, 0, Force},
{"update", 1, 0, 'U'},
+ {"freeze-reshape", 0, 0, FreezeReshape},
/* Management */
{"add", 0, 0, Add},
int mdfd = -1;
+ int freeze_reshape = 0;
+
srandom(time(0) ^ getpid());
ident.uuid_set=0;
case O(MANAGE,Force): /* add device which is too large */
force=1;
continue;
-
/* now for the Assemble options */
+ case O(ASSEMBLE, FreezeReshape): /* Freeze reshape during
+ * initrd phase */
+ case O(INCREMENTAL, FreezeReshape):
+ freeze_reshape = 1;
+ continue;
case O(CREATE,'u'): /* uuid of array */
case O(ASSEMBLE,'u'): /* uuid of array */
if (ident.uuid_set) {
NULL, backup_file, invalid_backup,
readonly, runstop, update,
homehost, require_homehost,
- verbose-quiet, force);
+ verbose-quiet, force,
+ freeze_reshape);
}
} else if (!scan)
rv = Assemble(ss, devlist->devname, &ident,
devlist->next, backup_file, invalid_backup,
readonly, runstop, update,
homehost, require_homehost,
- verbose-quiet, force);
+ verbose-quiet, force,
+ freeze_reshape);
else if (devs_found>0) {
if (update && devs_found > 1) {
fprintf(stderr, Name ": can only update a single array at a time\n");
NULL, backup_file, invalid_backup,
readonly, runstop, update,
homehost, require_homehost,
- verbose-quiet, force);
+ verbose-quiet, force,
+ freeze_reshape);
}
} else {
struct mddev_ident *a, *array_list = conf_get_ident(NULL);
NULL, NULL, 0,
readonly, runstop, NULL,
homehost, require_homehost,
- verbose-quiet, force);
+ verbose-quiet, force,
+ freeze_reshape);
if (r == 0) {
a->assembled = 1;
successes++;
rv2 = Assemble(ss, NULL,
&ident,
devlist, NULL, 0,
- readonly, runstop, NULL,
- homehost, require_homehost,
- verbose-quiet, force);
+ readonly,
+ runstop, NULL,
+ homehost,
+ require_homehost,
+ verbose-quiet,
+ force,
+ freeze_reshape);
if (rv2==0) {
cnt++;
acnt++;
else
rv = Incremental(devlist->devname, verbose-quiet,
runstop, ss, homehost,
- require_homehost, autof);
+ require_homehost, autof,
+ freeze_reshape);
break;
case AUTODETECT:
autodetect();
RebuildMapOpt,
InvalidBackup,
UdevRules,
+ FreezeReshape,
};
/* structures read from config file */
extern int Grow_restart(struct supertype *st, struct mdinfo *info,
int *fdlist, int cnt, char *backup_file, int verbose);
extern int Grow_continue(int mdfd, struct supertype *st,
- struct mdinfo *info, char *backup_file);
+ struct mdinfo *info, char *backup_file,
+ int freeze_reshape);
+
extern int restore_backup(struct supertype *st,
struct mdinfo *content,
int working_disks,
char *backup_file, int invalid_backup,
int readonly, int runstop,
char *update, char *homehost, int require_homehost,
- int verbose, int force);
+ int verbose, int force, int freeze_reshape);
extern int Build(char *mddev, int chunk, int level, int layout,
int raiddisks, struct mddev_dev *devlist, int assume_clean,
extern int Incremental(char *devname, int verbose, int runstop,
struct supertype *st, char *homehost, int require_homehost,
- int autof);
+ int autof, int freeze_reshape);
extern void RebuildMap(void);
extern int IncrementalScan(int verbose);
extern int IncrementalRemove(char *devname, char *path, int verbose);
extern int assemble_container_content(struct supertype *st, int mdfd,
struct mdinfo *content, int runstop,
char *chosen_name, int verbose,
- char *backup_file);
+ char *backup_file, int freeze_reshape);
extern struct mdinfo *container_choose_spares(struct supertype *st,
unsigned long long min_size,
struct domainlist *domlist,