diff --git a/Assemble.c b/Assemble.c index c6aad20..afca38e 100644 --- a/Assemble.c +++ b/Assemble.c @@ -138,7 +138,7 @@ int Assemble(struct supertype *st, char *mddev, 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 @@ -697,7 +697,7 @@ int Assemble(struct supertype *st, char *mddev, int err; err = assemble_container_content(st, mdfd, content, runstop, chosen_name, verbose, - backup_file); + backup_file, freeze_reshape); close(mdfd); return err; } @@ -1344,7 +1344,8 @@ int Assemble(struct supertype *st, char *mddev, #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); @@ -1511,7 +1512,7 @@ int Assemble(struct supertype *st, char *mddev, 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; @@ -1560,7 +1561,8 @@ int assemble_container_content(struct supertype *st, int mdfd, 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: diff --git a/Grow.c b/Grow.c index 90b84d7..a7e528f 100644 --- a/Grow.c +++ b/Grow.c @@ -1344,13 +1344,13 @@ static int reshape_array(char *container, int fd, char *devname, 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, @@ -1761,7 +1761,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, * 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 @@ -1789,7 +1789,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, } 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: @@ -1802,7 +1802,7 @@ static int reshape_array(char *container, int fd, char *devname, 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; @@ -2251,6 +2251,15 @@ started: } 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... @@ -2390,7 +2399,7 @@ int reshape_container(char *container, char *devname, 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; @@ -2419,7 +2428,9 @@ int reshape_container(char *container, char *devname, 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(); @@ -2475,8 +2486,15 @@ int reshape_container(char *container, char *devname, 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; @@ -3615,7 +3633,7 @@ int Grow_restart(struct supertype *st, struct mdinfo *info, int *fdlist, int cnt } 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; @@ -3642,9 +3660,9 @@ int Grow_continue(int mdfd, struct supertype *st, struct mdinfo *info, 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); } diff --git a/Incremental.c b/Incremental.c index a3e05a7..b90089b 100644 --- a/Incremental.c +++ b/Incremental.c @@ -44,7 +44,8 @@ static int try_spare(char *devname, int *dfdp, struct dev_policy *pol, 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, @@ -53,7 +54,7 @@ static struct mddev_ident *search_mdstat(struct supertype *st, 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. @@ -140,7 +141,8 @@ int Incremental(char *devname, int verbose, int runstop, 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); @@ -450,7 +452,8 @@ int Incremental(char *devname, int verbose, int runstop, 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 @@ -1416,7 +1419,7 @@ static char *container2devname(char *devname) 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. @@ -1554,7 +1557,8 @@ static int Incremental_container(struct supertype *st, char *devname, } assemble_container_content(st, mdfd, ra, runstop, - chosen_name, verbose, NULL); + chosen_name, verbose, NULL, + freeze_reshape); close(mdfd); } diff --git a/ReadMe.c b/ReadMe.c index b658841..89dd7af 100644 --- a/ReadMe.c +++ b/ReadMe.c @@ -153,6 +153,7 @@ struct option long_options[] = { {"scan", 0, 0, 's'}, {"force", 0, 0, Force}, {"update", 1, 0, 'U'}, + {"freeze-reshape", 0, 0, FreezeReshape}, /* Management */ {"add", 0, 0, Add}, diff --git a/mdadm.c b/mdadm.c index 1533510..af182d0 100644 --- a/mdadm.c +++ b/mdadm.c @@ -112,6 +112,8 @@ int main(int argc, char *argv[]) int mdfd = -1; + int freeze_reshape = 0; + srandom(time(0) ^ getpid()); ident.uuid_set=0; @@ -612,8 +614,12 @@ int main(int argc, char *argv[]) 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) { @@ -1228,14 +1234,16 @@ int main(int argc, char *argv[]) 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"); @@ -1259,7 +1267,8 @@ int main(int argc, char *argv[]) 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); @@ -1300,7 +1309,8 @@ int main(int argc, char *argv[]) NULL, NULL, 0, readonly, runstop, NULL, homehost, require_homehost, - verbose-quiet, force); + verbose-quiet, force, + freeze_reshape); if (r == 0) { a->assembled = 1; successes++; @@ -1325,9 +1335,13 @@ int main(int argc, char *argv[]) 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++; @@ -1681,7 +1695,8 @@ int main(int argc, char *argv[]) else rv = Incremental(devlist->devname, verbose-quiet, runstop, ss, homehost, - require_homehost, autof); + require_homehost, autof, + freeze_reshape); break; case AUTODETECT: autodetect(); diff --git a/mdadm.h b/mdadm.h index 9165f7a..4687a21 100644 --- a/mdadm.h +++ b/mdadm.h @@ -313,6 +313,7 @@ enum special_options { RebuildMapOpt, InvalidBackup, UdevRules, + FreezeReshape, }; /* structures read from config file */ @@ -1031,7 +1032,9 @@ extern int Grow_reshape(char *devname, int fd, int quiet, char *backup_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, @@ -1045,7 +1048,7 @@ extern int Assemble(struct supertype *st, char *mddev, 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, @@ -1079,7 +1082,7 @@ extern int WaitClean(char *dev, int sock, int verbose); 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); @@ -1158,7 +1161,7 @@ extern void append_metadata_update(struct supertype *st, void *buf, int len); 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,