int layout = UnSet;
char *layout_str = NULL;
int raiddisks = 0;
- int max_disks = MD_SB_DISKS; /* just a default */
int sparedisks = 0;
struct mddev_ident_s ident;
char *configfile = NULL;
int dosyslog = 0;
int rebuild_map = 0;
int auto_update_home = 0;
+ char *subarray = NULL;
int print_help = 0;
FILE *outf;
case 'W':
case Waitclean:
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 'K': if (!mode) newmode = MISC; break;
}
if (mode && newmode == mode) {
fprintf(stderr, Name ": unrecognised metadata identifier: %s\n", optarg);
exit(2);
}
- max_disks = ss->max_devs;
continue;
case O(MANAGE,'W'):
case O(CREATE,'N'):
case O(ASSEMBLE,'N'):
+ case O(MISC,'N'):
if (ident.name[0]) {
fprintf(stderr, Name ": name cannot be set twice. "
"Second value %s.\n", optarg);
exit(2);
}
+ if (mode == MISC && !subarray) {
+ fprintf(stderr, Name ": -N/--name only valid with --update-subarray in misc mode\n");
+ exit(2);
+ }
if (strlen(optarg) > 32) {
fprintf(stderr, Name ": name '%s' is too long, 32 chars max.\n",
optarg);
continue;
case O(ASSEMBLE,'U'): /* update the superblock */
+ case O(MISC,'U'):
if (update) {
fprintf(stderr, Name ": Can only update one aspect of superblock, both %s and %s given.\n",
update, optarg);
exit(2);
}
+ if (mode == MISC && !subarray) {
+ fprintf(stderr, Name ": Only subarrays can be updated in misc mode\n");
+ exit(2);
+ }
update = optarg;
if (strcmp(update, "sparc2.2")==0)
continue;
continue;
if (strcmp(update, "devicesize")==0)
continue;
+ if (strcmp(update, "no-bitmap")==0)
+ continue;
if (strcmp(update, "byteorder")==0) {
if (ss) {
fprintf(stderr, Name ": must not set metadata type with --update=byteorder.\n");
}
fprintf(outf, "Valid --update options are:\n"
" 'sparc2.2', 'super-minor', 'uuid', 'name', 'resync',\n"
- " 'summaries', 'homehost', 'byteorder', 'devicesize'.\n");
+ " 'summaries', 'homehost', 'byteorder', 'devicesize',\n"
+ " 'no-bitmap'\n");
exit(outf == stdout ? 0 : 2);
case O(INCREMENTAL,NoDegraded):
+ fprintf(stderr, Name ": --no-degraded is deprecated in Incremental mode\n");
case O(ASSEMBLE,NoDegraded): /* --no-degraded */
runstop = -1; /* --stop isn't allowed for --assemble,
* so we overload slightly */
devmode = 'r';
continue;
case O(MANAGE,'f'): /* set faulty */
+ case O(INCREMENTAL,'f'): /* r for incremental is taken, use f
+ * even though we will both fail and
+ * remove the device */
devmode = 'f';
continue;
case O(INCREMENTAL,'R'):
}
runstop = -1;
continue;
+ case O(MANAGE,'t'):
+ test = 1;
+ continue;
case O(MISC,'Q'):
case O(MISC,'D'):
case O(MISC,'W'):
case O(MISC, Waitclean):
case O(MISC, DetailPlatform):
+ case O(MISC, KillSubarray):
+ case O(MISC, UpdateSubarray):
if (devmode && devmode != opt &&
(devmode == 'E' || (opt == 'E' && devmode != 'Q'))) {
- fprintf(stderr, Name ": --examine/-E cannot be given with -%c\n",
- devmode =='E'?opt:devmode);
+ fprintf(stderr, Name ": --examine/-E cannot be given with ");
+ if (devmode == 'E') {
+ if (option_index >= 0)
+ fprintf(stderr, "--%s\n",
+ long_options[option_index].name);
+ else
+ fprintf(stderr, "-%c\n", opt);
+ } else if (isalpha(devmode))
+ fprintf(stderr, "-%c\n", devmode);
+ else
+ fprintf(stderr, "previous option\n");
exit(2);
}
devmode = opt;
}
if (raiddisks) {
- if (raiddisks > max_disks) {
- fprintf(stderr, Name ": invalid number of raid devices: %d\n",
- raiddisks);
- exit(2);
- }
if (raiddisks == 1 && !force && level != -5) {
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"
exit(2);
}
}
- if (sparedisks) {
- if ( sparedisks > max_disks - raiddisks) {
- fprintf(stderr, Name ": invalid number of spare-devices: %d\n",
- sparedisks);
- exit(2);
- }
- }
if (homehost == NULL)
homehost = conf_get_homehost(&require_homehost);
}
}
+ if ((mode != MISC || devmode != 'E') &&
+ geteuid() != 0) {
+ fprintf(stderr, Name ": must be super-user to perform this action\n");
+ exit(1);
+ }
+
ident.autof = autof;
rv = 0;
rv = Manage_ro(devlist->devname, mdfd, readonly);
if (!rv && devs_found>1)
rv = Manage_subdevs(devlist->devname, mdfd,
- devlist->next, verbose-quiet);
+ devlist->next, verbose-quiet, test);
if (!rv && readonly < 0)
rv = Manage_ro(devlist->devname, mdfd, readonly);
if (!rv && runstop)
verbose-quiet, force);
}
} else {
- mddev_ident_t array_list = conf_get_ident(NULL);
+ mddev_ident_t a, array_list = conf_get_ident(NULL);
mddev_dev_t devlist = conf_get_devs();
int cnt = 0;
+ int failures, successes;
if (devlist == NULL) {
fprintf(stderr, Name ": No devices listed in conf file were found.\n");
exit(1);
fprintf(stderr, Name ": --backup_file not meaningful with a --scan assembly.\n");
exit(1);
}
- for (; array_list; array_list = array_list->next) {
- if (array_list->devname &&
- strcasecmp(array_list->devname, "<ignore>") == 0)
- continue;
- if (array_list->autof == 0)
- array_list->autof = autof;
+ for (a = array_list; a ; a = a->next) {
+ a->assembled = 0;
+ if (a->autof == 0)
+ a->autof = autof;
+ }
+ 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;
- rv |= Assemble(ss, array_list->devname,
- array_list,
- NULL, NULL,
- readonly, runstop, NULL,
- homehost, require_homehost,
- verbose-quiet, force);
- cnt++;
- }
+ r = Assemble(ss, a->devname,
+ a,
+ NULL, NULL,
+ readonly, runstop, NULL,
+ homehost, require_homehost,
+ verbose-quiet, force);
+ 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
do {
rv |= Kill(dv->devname, NULL, force, q, 0);
q = 1;
- } while ((rv & 2) == 0);
+ } while (rv == 0);
rv &= ~2;
}
continue;
rv |= Wait(dv->devname); continue;
case Waitclean:
rv |= WaitClean(dv->devname, -1, verbose-quiet); continue;
+ case KillSubarray:
+ rv |= Kill_subarray(dv->devname, subarray, quiet);
+ continue;
+ case UpdateSubarray:
+ if (update == NULL) {
+ fprintf(stderr,
+ Name ": -U/--update must be specified with --update-subarray\n");
+ rv |= 1;
+ continue;
+ }
+ rv |= Update_subarray(dv->devname, subarray, update, &ident, quiet);
+ continue;
}
mdfd = open_mddev(dv->devname, 1);
if (mdfd>=0) {
": --incremental --scan meaningless without --run.\n");
break;
}
+ if (devmode == 'f') {
+ fprintf(stderr, Name
+ ": --incremental --scan --fail not supported.\n");
+ break;
+ }
rv = IncrementalScan(verbose);
}
if (!devlist) {
rv = 1;
break;
}
+ if (devmode == 'f') {
+ rv = IncrementalRemove(devlist->devname, verbose-quiet);
+ break;
+ }
rv = Incremental(devlist->devname, verbose-quiet, runstop,
ss, homehost, require_homehost, autof);
break;