/*
* mdadm - manage Linux "md" devices aka RAID arrays.
*
- * Copyright (C) 2001-2009 Neil Brown <neilb@suse.de>
+ * Copyright (C) 2001-2012 Neil Brown <neilb@suse.de>
*
*
* This program is free software; you can redistribute it and/or modify
#include <ctype.h>
+static int scan_assemble(int autof, struct supertype *ss,
+ int readonly, int runstop,
+ struct mddev_ident *ident,
+ char *homehost, int require_homehost,
+ int verbose, int force,
+ int freeze_reshape);
+
int main(int argc, char *argv[])
{
int mode = 0;
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.
/*
* --offroot sets first char of argv[0] to @. This is used
- * by systemd to signal that the tast was launched from
+ * by systemd to signal that the task was launched from
* initrd/initramfs and should be preserved during shutdown
*/
case OffRootOpt:
__offroot = 1;
continue;
+ case Prefer:
+ if (prefer)
+ free(prefer);
+ if (asprintf(&prefer, "/%s/", optarg) <= 0)
+ prefer = NULL;
+ continue;
+
case ':':
case '?':
fputs(Usage, stderr);
}
break;
- case 'A': newmode = ASSEMBLE; shortopt = short_bitmap_auto_options; break;
- case 'B': newmode = BUILD; shortopt = short_bitmap_auto_options; break;
- case 'C': newmode = CREATE; shortopt = short_bitmap_auto_options; break;
- case 'F': newmode = MONITOR;break;
+ case 'A': newmode = ASSEMBLE;
+ shortopt = short_bitmap_auto_options;
+ break;
+ case 'B': newmode = BUILD;
+ shortopt = short_bitmap_auto_options;
+ break;
+ case 'C': newmode = CREATE;
+ shortopt = short_bitmap_auto_options;
+ break;
+ case 'F': newmode = MONITOR;
+ break;
case 'G': newmode = GROW;
shortopt = short_bitmap_options;
break;
case 'I': newmode = INCREMENTAL;
- shortopt = short_bitmap_auto_options; break;
+ shortopt = short_bitmap_auto_options;
+ break;
case AutoDetect:
newmode = AUTODETECT;
break;
case KillSubarray:
case UpdateSubarray:
case UdevRules:
- case 'K':
+ case KillOpt:
if (!mode)
newmode = MISC;
break;
ident.raid_disks = raiddisks;
continue;
- case O(CREATE,'x'): /* number of spare (eXtra) discs */
+ case O(CREATE,'x'): /* number of spare (eXtra) disks */
if (sparedisks) {
fprintf(stderr,Name ": spare-devices set twice: %d and %s\n",
sparedisks, optarg);
case O(MONITOR,'r'): /* rebuild increments */
case O(MONITOR,Increment):
increments = atoi(optarg);
- if (increments>99 || increments<1) {
+ if (increments > 99 || increments < 1) {
fprintf(stderr, Name ": please specify positive integer between 1 and 99 as rebuild increments.\n");
exit(2);
}
case O(MONITOR, NoSharing):
spare_sharing = 0;
continue;
+
/* now the general management options. Some are applicable
* to other modes. None have arguments.
*/
case O(MISC,'Q'):
case O(MISC,'D'):
case O(MISC,'E'):
- case O(MISC,'K'):
+ case O(MISC,KillOpt):
case O(MISC,'R'):
case O(MISC,'S'):
case O(MISC,'X'):
case O(CREATE,Bitmap): /* here we create the bitmap */
if (strcmp(optarg, "none") == 0) {
fprintf(stderr, Name ": '--bitmap none' only"
- " support for --grow\n");
+ " supported for --grow\n");
exit(2);
}
/* FALL THROUGH */
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):
*
* That is mosty checked in the per-mode stuff but...
*
- * For @,B,C and A without -s, the first device listed must be an md device
- * we check that here and open it.
+ * For @,B,C and A without -s, the first device listed must be
+ * an md device. We check that here and open it.
*/
- if (mode==MANAGE || mode == BUILD || mode == CREATE || mode == GROW ||
- (mode == ASSEMBLE && ! scan)) {
+ if (mode == MANAGE || mode == BUILD || mode == CREATE
+ || mode == GROW
+ || (mode == ASSEMBLE && ! scan)) {
if (devs_found < 1) {
fprintf(stderr, Name ": an md device must be given in this mode\n");
exit(2);
}
if (raiddisks) {
- if (raiddisks == 1 && !force && level != -5) {
+ if (raiddisks == 1 && !force && level != LEVEL_FAULTY) {
fprintf(stderr, Name ": '1' is an unusual number of drives for an array, so it is probably\n"
" a mistake. If you really mean it you will need to specify --force before\n"
" setting the number of drives.\n");
require_homehost = 0;
}
- if (!((mode == MISC && devmode == 'E')
- || (mode == MONITOR && spare_sharing == 0)) &&
- geteuid() != 0) {
+ if ((mode == MISC && devmode == 'E')
+ || (mode == MONITOR && spare_sharing == 0))
+ /* Anyone may try this */;
+ else if (geteuid() != 0) {
fprintf(stderr, Name ": must be super-user to perform this action\n");
exit(1);
}
homehost, require_homehost,
verbose-quiet, force,
freeze_reshape);
- else if (devs_found>0) {
+ else if (devs_found > 0) {
if (update && devs_found > 1) {
fprintf(stderr, Name ": can only update a single array at a time\n");
exit(1);
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 (update) {
fprintf(stderr, Name ": --update not meaningful with a --scan assembly.\n");
exit(1);
fprintf(stderr, Name ": --backup_file not meaningful with a --scan assembly.\n");
exit(1);
}
- for (a = array_list; a ; a = a->next) {
- a->assembled = 0;
- 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;
- rv = 0;
- for (a = array_list; a ; a = a->next) {
- int r;
- if (a->assembled)
- continue;
- if (a->devname &&
- strcasecmp(a->devname, "<ignore>") == 0)
- continue;
-
- r = Assemble(ss, a->devname,
- a,
- NULL, NULL, 0,
- readonly, runstop, NULL,
- homehost, require_homehost,
- verbose-quiet, force,
- freeze_reshape);
- if (r == 0) {
- a->assembled = 1;
- successes++;
- } else
- failures++;
- rv |= r;
- cnt++;
- }
- } while (failures && successes);
- if (homehost && cnt == 0) {
- /* Maybe we can auto-assemble something.
- * Repeatedly call Assemble in auto-assemble mode
- * until it fails
- */
- int rv2;
- int acnt;
- ident.autof = autof;
- do {
- struct mddev_dev *devlist = conf_get_devs();
- acnt = 0;
- do {
- rv2 = Assemble(ss, NULL,
- &ident,
- devlist, NULL, 0,
- readonly,
- runstop, NULL,
- homehost,
- require_homehost,
- verbose-quiet,
- force,
- freeze_reshape);
- if (rv2==0) {
- cnt++;
- acnt++;
- }
- } while (rv2!=2);
- /* Incase there are stacked devices, we need to go around again */
- } while (acnt);
- if (cnt == 0 && rv == 0) {
- fprintf(stderr, Name ": No arrays found in config file or automatically\n");
- rv = 1;
- } else if (cnt)
- rv = 0;
- } else if (cnt == 0 && rv == 0) {
- fprintf(stderr, Name ": No arrays found in config file\n");
- rv = 1;
- }
- map_unlock(&map);
+ rv = scan_assemble(autof, ss, readonly, runstop,
+ &ident, homehost,
+ require_homehost,
+ verbose - quiet,
+ force, freeze_reshape);
}
+
break;
case BUILD:
if (delay == 0) delay = DEFAULT_BITMAP_DELAY;
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 */
+ case KillOpt: /* Zero superblock */
if (ss)
rv |= Kill(dv->devname, ss, force, quiet,0);
else {
}
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:
}
exit(rv);
}
+
+static int scan_assemble(int autof, struct supertype *ss,
+ int readonly, int runstop,
+ struct mddev_ident *ident,
+ char *homehost, int require_homehost,
+ int verbose, int force,
+ int freeze_reshape)
+{
+ 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 rv = 0;
+ int failures, successes;
+
+ if (conf_verify_devnames(array_list)) {
+ fprintf(stderr, Name
+ ": Duplicate MD device names in "
+ "conf file were found.\n");
+ return 1;
+ }
+ if (devlist == NULL) {
+ fprintf(stderr, Name ": No devices listed in conf file were found.\n");
+ return 1;
+ }
+ for (a = array_list; a ; a = a->next) {
+ a->assembled = 0;
+ 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;
+ rv = 0;
+ for (a = array_list; a ; a = a->next) {
+ int r;
+ if (a->assembled)
+ continue;
+ if (a->devname &&
+ strcasecmp(a->devname, "<ignore>") == 0)
+ continue;
+
+ r = Assemble(ss, a->devname,
+ a,
+ NULL, NULL, 0,
+ readonly, runstop, NULL,
+ homehost, require_homehost,
+ verbose, force,
+ freeze_reshape);
+ if (r == 0) {
+ a->assembled = 1;
+ successes++;
+ } else
+ failures++;
+ rv |= r;
+ cnt++;
+ }
+ } while (failures && successes);
+ if (homehost && cnt == 0) {
+ /* Maybe we can auto-assemble something.
+ * Repeatedly call Assemble in auto-assemble mode
+ * until it fails
+ */
+ int rv2;
+ int acnt;
+ ident->autof = autof;
+ do {
+ struct mddev_dev *devlist = conf_get_devs();
+ acnt = 0;
+ do {
+ rv2 = Assemble(ss, NULL,
+ ident,
+ devlist, NULL, 0,
+ readonly,
+ runstop, NULL,
+ homehost,
+ require_homehost,
+ verbose,
+ force,
+ freeze_reshape);
+ if (rv2==0) {
+ cnt++;
+ acnt++;
+ }
+ } while (rv2!=2);
+ /* Incase there are stacked devices, we need to go around again */
+ } while (acnt);
+ if (cnt == 0 && rv == 0) {
+ fprintf(stderr, Name ": No arrays found in config file or automatically\n");
+ rv = 1;
+ } else if (cnt)
+ rv = 0;
+ } else if (cnt == 0 && rv == 0) {
+ fprintf(stderr, Name ": No arrays found in config file\n");
+ rv = 1;
+ }
+ map_unlock(&map);
+ return rv;
+}