int test = 0;
int export = 0;
int assume_clean = 0;
+ char *prefer = NULL;
char *symlinks = NULL;
+ int grow_continue = 0;
/* autof indicates whether and how to create device node.
* bottom 3 bits are style. Rest (when shifted) are number of parts
* 0 - unset
int mdfd = -1;
+ int freeze_reshape = 0;
+
srandom(time(0) ^ getpid());
ident.uuid_set=0;
homehost = optarg;
continue;
+ /*
+ * --offroot sets first char of argv[0] to @. This is used
+ * by systemd to signal that the tast was launched from
+ * initrd/initramfs and should be preserved during shutdown
+ */
+ case OffRootOpt:
+ argv[0][0] = '@';
+ __offroot = 1;
+ continue;
+
+ case Prefer:
+ if (prefer)
+ free(prefer);
+ if (asprintf(&prefer, "/%s/", optarg) <= 0)
+ prefer = NULL;
+ continue;
+
case ':':
case '?':
fputs(Usage, stderr);
case 'I': newmode = INCREMENTAL;
shortopt = short_bitmap_auto_options; break;
case AutoDetect:
- newmode = AUTODETECT; break;
+ newmode = AUTODETECT;
+ break;
case MiscOpt:
case 'D':
case 'E':
case 'X':
- case 'Q': newmode = MISC; break;
+ case 'Q':
+ newmode = MISC;
+ break;
+
case 'R':
case 'S':
case 'o':
case DetailPlatform:
case KillSubarray:
case UpdateSubarray:
- if (opt == KillSubarray || opt == UpdateSubarray) {
- if (subarray) {
- fprintf(stderr, Name ": subarray can only"
- " be specified once\n");
- exit(2);
- }
- subarray = optarg;
- }
case UdevRules:
- case 'K': if (!mode) newmode = MISC; break;
- case NoSharing: newmode = MONITOR; break;
+ case 'K':
+ if (!mode)
+ newmode = MISC;
+ break;
+
+ case NoSharing:
+ newmode = MONITOR;
+ break;
}
if (mode && newmode == mode) {
/* everybody happy ! */
case O(CREATE,AssumeClean):
case O(BUILD,AssumeClean): /* assume clean */
+ case O(GROW,AssumeClean):
assume_clean = 1;
continue;
case O(ASSEMBLE,Force): /* force assembly */
case O(MISC,'f'): /* force zero */
case O(MISC,Force): /* force zero */
+ 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) {
continue;
case O(MONITOR,'1'): /* oneshot */
oneshot = 1;
+ spare_sharing = 0;
continue;
case O(MONITOR,'t'): /* test */
test = 1;
case O(MISC, DetailPlatform):
case O(MISC, KillSubarray):
case O(MISC, UpdateSubarray):
+ if (opt == KillSubarray || opt == UpdateSubarray) {
+ if (subarray) {
+ fprintf(stderr, Name ": subarray can only"
+ " be specified once\n");
+ exit(2);
+ }
+ subarray = optarg;
+ }
if (devmode && devmode != opt &&
(devmode == 'E' || (opt == 'E' && devmode != 'Q'))) {
fprintf(stderr, Name ": --examine/-E cannot be given with ");
backup_file = optarg;
continue;
+ case O(GROW, Continue):
+ /* Continue interrupted grow
+ */
+ grow_continue = 1;
+ continue;
case O(ASSEMBLE, InvalidBackup):
/* Acknowledge that the backupfile is invalid, but ask
* to continue anyway
case O(BUILD,BitmapChunk):
case O(CREATE,BitmapChunk): /* bitmap chunksize */
bitmap_chunk = parse_size(optarg);
- if (bitmap_chunk < 0 ||
+ if (bitmap_chunk <= 0 ||
bitmap_chunk & (bitmap_chunk - 1)) {
fprintf(stderr,
Name ": invalid bitmap chunksize: %s\n",
optarg);
exit(2);
}
- /* convert sectors to B, chunk of 0 means 512B */
- bitmap_chunk = bitmap_chunk ? bitmap_chunk * 512 : 512;
+ bitmap_chunk = bitmap_chunk * 512;
continue;
case O(GROW, WriteBehind):
require_homehost = 0;
}
- if ((mode != MISC || devmode != 'E') &&
+ if (!((mode == MISC && devmode == 'E')
+ || (mode == MONITOR && spare_sharing == 0)) &&
geteuid() != 0) {
fprintf(stderr, Name ": must be super-user to perform this action\n");
exit(1);
if (!rv && devs_found>1)
rv = Manage_subdevs(devlist->devname, mdfd,
devlist->next, verbose-quiet, test,
- update);
+ update, force);
if (!rv && readonly < 0)
rv = Manage_ro(devlist->devname, mdfd, readonly);
if (!rv && runstop)
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);
struct mddev_dev *devlist = conf_get_devs();
+ struct map_ent *map = NULL;
int cnt = 0;
int failures, successes;
+
+ if (conf_verify_devnames(array_list)) {
+ fprintf(stderr, Name
+ ": Duplicate MD device names in "
+ "conf file were found.\n");
+ exit(1);
+ }
if (devlist == NULL) {
fprintf(stderr, Name ": No devices listed in conf file were found.\n");
exit(1);
if (a->autof == 0)
a->autof = autof;
}
+ if (map_lock(&map))
+ fprintf(stderr, Name " %s: failed to get "
+ "exclusive lock on mapfile\n",
+ __func__);
do {
failures = 0;
successes = 0;
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++;
fprintf(stderr, Name ": No arrays found in config file\n");
rv = 1;
}
+ map_unlock(&map);
}
break;
case BUILD:
if (devmode == 'D')
rv |= Detail(name, v,
export, test,
- homehost);
+ homehost, prefer);
else
rv |= WaitClean(name, -1, v);
put_md_name(name);
case 'D':
rv |= Detail(dv->devname,
brief?1+verbose:0,
- export, test, homehost);
+ export, test, homehost, prefer);
continue;
case 'K': /* Zero superblock */
if (ss)
}
rv= Monitor(devlist, mailaddr, program,
delay?delay:60, daemonise, scan, oneshot,
- dosyslog, test, pidfile, increments, spare_sharing);
+ dosyslog, test, pidfile, increments,
+ spare_sharing, prefer);
break;
case GROW:
delay = DEFAULT_BITMAP_DELAY;
rv = Grow_addbitmap(devlist->devname, mdfd, bitmap_file,
bitmap_chunk, delay, write_behind, force);
- } else if (size >= 0 || raiddisks != 0 || layout_str != NULL
+ } else if (grow_continue)
+ rv = Grow_continue_command(devlist->devname,
+ mdfd, backup_file,
+ verbose);
+ else if (size >= 0 || raiddisks != 0 || layout_str != NULL
|| chunk != 0 || level != UnSet) {
rv = Grow_reshape(devlist->devname, mdfd, quiet, backup_file,
size, level, layout_str, chunk, raiddisks,
devlist->next,
- force);
+ assume_clean, force);
} else if (array_size < 0)
fprintf(stderr, Name ": no changes to --grow\n");
break;
else
rv = Incremental(devlist->devname, verbose-quiet,
runstop, ss, homehost,
- require_homehost, autof);
+ require_homehost, autof,
+ freeze_reshape);
break;
case AUTODETECT:
autodetect();