struct mddev_dev *devlist = NULL;
struct mddev_dev **devlistend = & devlist;
struct mddev_dev *dv;
+ mdu_array_info_t array;
int devs_found = 0;
char *symlinks = NULL;
int grow_continue = 0;
FILE *outf;
int mdfd = -1;
+ int locked = 0;
srandom(time(0) ^ getpid());
c.brief = 1;
continue;
+ case NoDevices:
+ c.no_devices = 1;
+ continue;
+
case 'Y': c.export++;
continue;
pr_err("raid level must be given before layout.\n");
exit(2);
+ case 0:
+ s.layout = map_name(r0layout, optarg);
+ if (s.layout == UnSet) {
+ pr_err("layout %s not understood for raid0.\n",
+ optarg);
+ exit(2);
+ }
+ break;
case 5:
s.layout = map_name(r5layout, optarg);
if (s.layout == UnSet) {
s.raiddisks, optarg);
exit(2);
}
- s.raiddisks = parse_num(optarg);
- if (s.raiddisks <= 0) {
+ if (parse_num(&s.raiddisks, optarg) != 0 || s.raiddisks <= 0) {
pr_err("invalid number of raid devices: %s\n",
optarg);
exit(2);
case O(ASSEMBLE, Nodes):
case O(GROW, Nodes):
case O(CREATE, Nodes):
- c.nodes = parse_num(optarg);
- if (c.nodes < 2) {
+ if (parse_num(&c.nodes, optarg) != 0 || c.nodes < 2) {
pr_err("clustered array needs two nodes at least: %s\n",
optarg);
exit(2);
s.level);
exit(2);
}
- s.sparedisks = parse_num(optarg);
- if (s.sparedisks < 0) {
+ if (parse_num(&s.sparedisks, optarg) != 0 || s.sparedisks < 0) {
pr_err("invalid number of spare-devices: %s\n",
optarg);
exit(2);
}
if (strcmp(optarg, "dev") == 0)
ident.super_minor = -2;
- else {
- ident.super_minor = parse_num(optarg);
- if (ident.super_minor < 0) {
- pr_err("Bad super-minor number: %s.\n", optarg);
- exit(2);
- }
+ else if (parse_num(&ident.super_minor, optarg) != 0 || ident.super_minor < 0) {
+ pr_err("Bad super-minor number: %s.\n", optarg);
+ exit(2);
}
continue;
continue;
if (strcmp(c.update, "devicesize") == 0)
continue;
+ if (strcmp(c.update, "bitmap") == 0)
+ continue;
if (strcmp(c.update, "no-bitmap") == 0)
continue;
if (strcmp(c.update, "bbl") == 0)
continue;
if (strcmp(c.update, "revert-reshape") == 0)
continue;
+ if (strcmp(c.update, "layout-original") == 0 ||
+ strcmp(c.update, "layout-alternate") == 0 ||
+ strcmp(c.update, "layout-unspecified") == 0)
+ continue;
if (strcmp(c.update, "byteorder") == 0) {
if (ss) {
pr_err("must not set metadata type with --update=byteorder.\n");
fprintf(outf, "Valid --update options are:\n"
" 'sparc2.2', 'super-minor', 'uuid', 'name', 'nodes', 'resync',\n"
" 'summaries', 'homehost', 'home-cluster', 'byteorder', 'devicesize',\n"
- " 'no-bitmap', 'metadata', 'revert-reshape'\n"
+ " 'bitmap', 'no-bitmap', 'metadata', 'revert-reshape'\n"
" 'bbl', 'no-bbl', 'force-no-bbl', 'ppl', 'no-ppl'\n"
+ " 'layout-original', 'layout-alternate', 'layout-unspecified'\n"
);
exit(outf == stdout ? 0 : 2);
case O(MONITOR,'r'): /* rebuild increments */
case O(MONITOR,Increment):
- increments = atoi(optarg);
- if (increments > 99 || increments < 1) {
+ if (parse_num(&increments, optarg) != 0
+ || increments > 99 || increments < 1) {
pr_err("please specify positive integer between 1 and 99 as rebuild increments.\n");
exit(2);
}
case O(BUILD,'d'): /* delay for bitmap updates */
case O(CREATE,'d'):
if (c.delay)
- pr_err("only specify delay once. %s ignored.\n",
- optarg);
- else {
- c.delay = parse_num(optarg);
- if (c.delay < 1) {
- pr_err("invalid delay: %s\n",
- optarg);
- exit(2);
- }
+ pr_err("only specify delay once. %s ignored.\n", optarg);
+ else if (parse_num(&c.delay, optarg) != 0 || c.delay < 1) {
+ pr_err("invalid delay: %s\n", optarg);
+ exit(2);
}
continue;
case O(MONITOR,'f'): /* daemonise */
case O(GROW, WriteBehind):
case O(BUILD, WriteBehind):
- case O(CREATE, WriteBehind): /* write-behind mode */
+ case O(CREATE, WriteBehind):
s.write_behind = DEFAULT_MAX_WRITE_BEHIND;
- if (optarg) {
- s.write_behind = parse_num(optarg);
- if (s.write_behind < 0 ||
- s.write_behind > 16383) {
- pr_err("Invalid value for maximum outstanding write-behind writes: %s.\n\tMust be between 0 and 16383.\n", optarg);
- exit(2);
- }
+ if (parse_num(&s.write_behind, optarg) != 0 ||
+ s.write_behind < 0 || s.write_behind > 16383) {
+ pr_err("Invalid value for maximum outstanding write-behind writes: %s.\n\tMust be between 0 and 16383.\n",
+ optarg);
+ exit(2);
}
continue;
-
case O(INCREMENTAL, 'r'):
case O(INCREMENTAL, RebuildMapOpt):
rebuild_map = 1;
mdfd = open_mddev(devlist->devname, 1);
if (mdfd < 0)
exit(1);
- } else
+ } else {
+ char *bname = basename(devlist->devname);
+
+ if (strlen(bname) > MD_NAME_MAX) {
+ pr_err("Name %s is too long.\n", devlist->devname);
+ exit(1);
+ }
/* non-existent device is OK */
mdfd = open_mddev(devlist->devname, 0);
+ }
if (mdfd == -2) {
pr_err("device %s exists but is not an md array.\n", devlist->devname);
exit(1);
}
}
+ if (c.update && strcmp(c.update, "nodes") == 0 && c.nodes == 0) {
+ pr_err("Please specify nodes number with --nodes\n");
+ exit(1);
+ }
+
if (c.backup_file && data_offset != INVALID_SECTORS) {
pr_err("--backup-file and --data-offset are incompatible\n");
exit(2);
/* --scan implied --brief unless -vv */
c.brief = 1;
+ if (mode == CREATE) {
+ if (s.bitmap_file && strcmp(s.bitmap_file, "clustered") == 0) {
+ locked = cluster_get_dlmlock();
+ if (locked != 1)
+ exit(1);
+ }
+ } else if (mode == MANAGE || mode == GROW || mode == INCREMENTAL) {
+ if (!md_get_array_info(mdfd, &array) && (devmode != 'c')) {
+ if (array.state & (1 << MD_SB_CLUSTERED)) {
+ locked = cluster_get_dlmlock();
+ if (locked != 1)
+ exit(1);
+ }
+ }
+ }
+
switch(mode) {
case MANAGE:
/* readonly, add/remove, readwrite, runstop */
rv = Manage_stop(devlist->devname, mdfd, c.verbose, 0);
break;
case ASSEMBLE:
- if (devs_found == 1 && ident.uuid_set == 0 &&
- ident.super_minor == UnSet && ident.name[0] == 0 &&
- !c.scan ) {
+ if (!c.scan && c.runstop == -1) {
+ pr_err("--no-degraded not meaningful without a --scan assembly.\n");
+ exit(1);
+ } else if (devs_found == 1 && ident.uuid_set == 0 &&
+ ident.super_minor == UnSet && ident.name[0] == 0 &&
+ !c.scan) {
/* Only a device has been given, so get details from config file */
struct mddev_ident *array_ident = conf_get_ident(devlist->devname);
if (array_ident == NULL) {
break;
}
- if (s.level != 1) {
- pr_err("--bitmap=clustered is currently supported with RAID mirror only\n");
+ if (s.level != 1 && s.level != 10) {
+ pr_err("--bitmap=clustered is currently supported with raid1/10 only\n");
+ rv = 1;
+ break;
+ }
+ if (s.level == 10 && !(is_near_layout_10(s.layout) || s.layout == UnSet)) {
+ pr_err("only near layout is supported with clustered raid10\n");
rv = 1;
break;
}
break;
}
if (c.delay == 0) {
- if (get_linux_version() > 2006016)
- /* mdstat responds to poll */
- c.delay = 1000;
- else
+ c.delay = conf_get_monitor_delay();
+ if (!c.delay)
c.delay = 60;
}
rv = Monitor(devlist, mailaddr, program,
autodetect();
break;
}
- if (mdfd > 0)
- close(mdfd);
+ if (locked)
+ cluster_release_dlmlock();
+ close_fd(&mdfd);
exit(rv);
}
if (devmode == 'D')
rv |= Detail(name, c);
else
- rv |= WaitClean(name, -1, c->verbose);
+ rv |= WaitClean(name, c->verbose);
put_md_name(name);
+ map_free(map);
+ map = NULL;
}
}
free_mdstat(ms);
rv |= Kill(dv->devname, NULL, c->force, v, 0);
v = -1;
} while (rv == 0);
- rv &= ~2;
+ rv &= ~4;
}
continue;
case 'Q':
rv |= Wait(dv->devname);
continue;
case Waitclean:
- rv |= WaitClean(dv->devname, -1, c->verbose);
+ rv |= WaitClean(dv->devname, c->verbose);
continue;
case KillSubarray:
rv |= Kill_subarray(dv->devname, c->subarray, c->verbose);
rv |= Manage_run(dv->devname, mdfd, c);
break;
case 'S':
+ if (c->scan) {
+ pr_err("--stop not meaningful with both a --scan assembly and a device name.\n");
+ rv |= 1;
+ break;
+ }
rv |= Manage_stop(dv->devname, mdfd, c->verbose, 0);
break;
case 'o':