]> git.ipfire.org Git - thirdparty/mdadm.git/blame - mdadm.c
main: split scan_assemble into a separate function
[thirdparty/mdadm.git] / mdadm.c
CommitLineData
64c4757e 1/*
9a9dab36 2 * mdadm - manage Linux "md" devices aka RAID arrays.
64c4757e 3 *
18361a1a 4 * Copyright (C) 2001-2012 Neil Brown <neilb@suse.de>
64c4757e
NB
5 *
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 * Author: Neil Brown
e736b623 22 * Email: <neilb@suse.de>
c82f047c 23 *
aba69144 24 * Additions for bitmap and write-behind RAID options, Copyright (C) 2003-2004,
c82f047c 25 * Paul Clements, SteelEye Technology, Inc.
64c4757e
NB
26 */
27
9a9dab36 28#include "mdadm.h"
64c4757e 29#include "md_p.h"
dd0781e5 30#include <ctype.h>
64c4757e 31
3cbc4d12
N
32
33static int scan_assemble(int autof, struct supertype *ss,
34 int readonly, int runstop,
35 struct mddev_ident *ident,
36 char *homehost, int require_homehost,
37 int verbose, int force,
38 int freeze_reshape);
39
52826846
NB
40int main(int argc, char *argv[])
41{
e0d19036 42 int mode = 0;
52826846 43 int opt;
e0d19036 44 int option_index;
52826846
NB
45 char *c;
46 int rv;
f9ce90ba 47 int i;
52826846
NB
48
49 int chunk = 0;
5dd497ee 50 long long size = -1;
84e11361 51 long long array_size = -1;
98c6faba
NB
52 int level = UnSet;
53 int layout = UnSet;
19678e53 54 char *layout_str = NULL;
52826846
NB
55 int raiddisks = 0;
56 int sparedisks = 0;
fa56eddb 57 struct mddev_ident ident;
52826846 58 char *configfile = NULL;
cd29a5c8 59 char *cp;
5787fa49 60 char *update = NULL;
52826846 61 int scan = 0;
1c7a808c 62 int devmode = 0;
52826846
NB
63 int runstop = 0;
64 int readonly = 0;
dfd4d8ee 65 int write_behind = 0;
c82f047c
NB
66 int bitmap_fd = -1;
67 char *bitmap_file = NULL;
06b0d786 68 char *backup_file = NULL;
87f26d14 69 int invalid_backup = 0;
c82f047c 70 int bitmap_chunk = UnSet;
bd526cee 71 int SparcAdjust = 0;
a655e550
N
72 struct mddev_dev *devlist = NULL;
73 struct mddev_dev **devlistend = & devlist;
74 struct mddev_dev *dv;
52826846
NB
75 int devs_found = 0;
76 int verbose = 0;
dab6685f 77 int quiet = 0;
cd29a5c8 78 int brief = 0;
52826846 79 int force = 0;
feb716e9 80 int test = 0;
54bad364 81 int export = 0;
dd0781e5 82 int assume_clean = 0;
c2ecf5f6 83 char *prefer = NULL;
38098016 84 char *symlinks = NULL;
2dddadb0 85 int grow_continue = 0;
f1ae21c4
NB
86 /* autof indicates whether and how to create device node.
87 * bottom 3 bits are style. Rest (when shifted) are number of parts
88 * 0 - unset
89 * 1 - don't create (no)
90 * 2 - if is_standard, then create (yes)
91 * 3 - create as 'md' - reject is_standard mdp (md)
92 * 4 - create as 'mdp' - reject is_standard md (mdp)
93 * 5 - default to md if not is_standard (md in config file)
94 * 6 - default to mdp if not is_standard (part, or mdp in config file)
95 */
96 int autof = 0;
52826846 97
997aed5d 98 char *homehost = NULL;
05697ec1 99 char sys_hostname[256];
0ac91628 100 int require_homehost = 1;
52826846
NB
101 char *mailaddr = NULL;
102 char *program = NULL;
9a36a9b7 103 int increments = 20;
52826846 104 int delay = 0;
d013a55e 105 int daemonise = 0;
b5e64645 106 char *pidfile = NULL;
aa88f531 107 int oneshot = 0;
edde9560 108 int spare_sharing = 1;
82d9eba6 109 struct supertype *ss = NULL;
dfd4d8ee 110 int writemostly = 0;
fe80f49b 111 int re_add = 0;
c06487ce 112 char *shortopt = short_options;
773135f5 113 int dosyslog = 0;
8382f19b 114 int rebuild_map = 0;
33414a01 115 char *subarray = NULL;
950bc344 116 char *remove_path = NULL;
20b60dcd 117 char *udev_filename = NULL;
52826846 118
3d4064cc 119 int print_help = 0;
0047d254 120 FILE *outf;
e5329c37 121
52826846
NB
122 int mdfd = -1;
123
b76b30e0
AK
124 int freeze_reshape = 0;
125
dfe47e00
NB
126 srandom(time(0) ^ getpid());
127
52826846 128 ident.uuid_set=0;
98c6faba
NB
129 ident.level = UnSet;
130 ident.raid_disks = UnSet;
131 ident.super_minor= UnSet;
52826846 132 ident.devices=0;
a75f2fbc
NB
133 ident.spare_group = NULL;
134 ident.autof = 0;
a825febc 135 ident.st = NULL;
c82f047c 136 ident.bitmap_fd = -1;
7ef02d01 137 ident.bitmap_file = NULL;
947fd4dd 138 ident.name[0] = 0;
aef35714
N
139 ident.container = NULL;
140 ident.member = NULL;
52826846 141
e0d19036
NB
142 while ((option_index = -1) ,
143 (opt=getopt_long(argc, argv,
c06487ce 144 shortopt, long_options,
e0d19036
NB
145 &option_index)) != -1) {
146 int newmode = mode;
35904960 147 /* firstly, some mode-independent options */
52826846 148 switch(opt) {
1c7a808c
N
149 case HelpOptions:
150 print_help = 2;
151 continue;
52826846 152 case 'h':
1c7a808c 153 print_help = 1;
3d4064cc 154 continue;
52826846
NB
155
156 case 'V':
157 fputs(Version, stderr);
158 exit(0);
159
22892d56 160 case 'v': verbose++;
52826846
NB
161 continue;
162
dab6685f
NB
163 case 'q': quiet++;
164 continue;
165
c82f047c 166 case 'b':
1c7a808c
N
167 if (mode == ASSEMBLE || mode == BUILD || mode == CREATE
168 || mode == GROW || mode == INCREMENTAL
169 || mode == MANAGE)
c82f047c 170 break; /* b means bitmap */
1c7a808c 171 case Brief:
c82f047c 172 brief = 1;
cd29a5c8
NB
173 continue;
174
54bad364
KS
175 case 'Y': export++;
176 continue;
177
997aed5d 178 case HomeHost:
0ac91628
N
179 if (strcasecmp(optarg, "<ignore>") == 0)
180 require_homehost = 0;
181 else
182 homehost = optarg;
997aed5d
NB
183 continue;
184
08ca2adf
JS
185 /*
186 * --offroot sets first char of argv[0] to @. This is used
18361a1a 187 * by systemd to signal that the task was launched from
08ca2adf
JS
188 * initrd/initramfs and should be preserved during shutdown
189 */
190 case OffRootOpt:
191 argv[0][0] = '@';
a0963a86 192 __offroot = 1;
08ca2adf
JS
193 continue;
194
c2ecf5f6
N
195 case Prefer:
196 if (prefer)
197 free(prefer);
198 if (asprintf(&prefer, "/%s/", optarg) <= 0)
199 prefer = NULL;
200 continue;
201
e0d19036
NB
202 case ':':
203 case '?':
204 fputs(Usage, stderr);
205 exit(2);
206 }
207 /* second, figure out the mode.
208 * Some options force the mode. Others
aba69144 209 * set the mode if it isn't already
e0d19036
NB
210 */
211
212 switch(opt) {
1c7a808c 213 case ManageOpt:
c06487ce 214 newmode = MANAGE;
024768c4 215 shortopt = short_bitmap_options;
c06487ce 216 break;
e0d19036 217 case 'a':
1c7a808c 218 case Add:
e0d19036 219 case 'r':
1c7a808c 220 case Remove:
e0d19036 221 case 'f':
1c7a808c 222 case Fail:
41a3b72a 223 case ReAdd: /* re-add */
c06487ce
NB
224 if (!mode) {
225 newmode = MANAGE;
024768c4 226 shortopt = short_bitmap_options;
c06487ce 227 }
0320ea45 228 break;
e0d19036 229
18361a1a
N
230 case 'A': newmode = ASSEMBLE;
231 shortopt = short_bitmap_auto_options;
232 break;
233 case 'B': newmode = BUILD;
234 shortopt = short_bitmap_auto_options;
235 break;
236 case 'C': newmode = CREATE;
237 shortopt = short_bitmap_auto_options;
238 break;
239 case 'F': newmode = MONITOR;
240 break;
024768c4
DL
241 case 'G': newmode = GROW;
242 shortopt = short_bitmap_options;
243 break;
95b79df0 244 case 'I': newmode = INCREMENTAL;
18361a1a
N
245 shortopt = short_bitmap_auto_options;
246 break;
1f48664b 247 case AutoDetect:
5a53aeec
JS
248 newmode = AUTODETECT;
249 break;
e0d19036 250
1c7a808c 251 case MiscOpt:
e0d19036
NB
252 case 'D':
253 case 'E':
c82f047c 254 case 'X':
5a53aeec
JS
255 case 'Q':
256 newmode = MISC;
257 break;
258
e0d19036
NB
259 case 'R':
260 case 'S':
261 case 'o':
262 case 'w':
b90c0e9a 263 case 'W':
1c7a808c 264 case WaitOpt:
1770662b 265 case Waitclean:
4cce4069 266 case DetailPlatform:
33414a01 267 case KillSubarray:
aa534678 268 case UpdateSubarray:
20b60dcd 269 case UdevRules:
f7d3febc 270 case KillOpt:
5a53aeec
JS
271 if (!mode)
272 newmode = MISC;
273 break;
274
275 case NoSharing:
276 newmode = MONITOR;
277 break;
e0d19036
NB
278 }
279 if (mode && newmode == mode) {
280 /* everybody happy ! */
281 } else if (mode && newmode != mode) {
282 /* not allowed.. */
283 fprintf(stderr, Name ": ");
284 if (option_index >= 0)
285 fprintf(stderr, "--%s", long_options[option_index].name);
286 else
287 fprintf(stderr, "-%c", opt);
e6b64cd0 288 fprintf(stderr, " would set mdadm mode to \"%s\", but it is already set to \"%s\".\n",
e0d19036
NB
289 map_num(modes, newmode),
290 map_num(modes, mode));
291 exit(2);
292 } else if (!mode && newmode) {
293 mode = newmode;
dec18cae
N
294 if (mode == MISC && devs_found) {
295 fprintf(stderr, Name ": No action given for %s in --misc mode\n",
296 devlist->devname);
297 fprintf(stderr," Action options must come before device names\n");
298 exit(2);
299 }
e0d19036
NB
300 } else {
301 /* special case of -c --help */
1c7a808c 302 if ((opt == 'c' || opt == ConfigFile) &&
e0d19036
NB
303 ( strncmp(optarg, "--h", 3)==0 ||
304 strncmp(optarg, "-h", 2)==0)) {
0047d254 305 fputs(Help_config, stdout);
e0d19036 306 exit(0);
cd29a5c8 307 }
0320ea45
NB
308
309 /* If first option is a device, don't force the mode yet */
310 if (opt == 1) {
311 if (devs_found == 0) {
312 dv = malloc(sizeof(*dv));
313 if (dv == NULL) {
314 fprintf(stderr, Name ": malloc failed\n");
315 exit(3);
316 }
317 dv->devname = optarg;
318 dv->disposition = devmode;
dfd4d8ee 319 dv->writemostly = writemostly;
fe80f49b 320 dv->re_add = re_add;
da6b5ca9 321 dv->used = 0;
0320ea45
NB
322 dv->next = NULL;
323 *devlistend = dv;
324 devlistend = &dv->next;
aba69144 325
0320ea45
NB
326 devs_found++;
327 continue;
328 }
329 /* No mode yet, and this is the second device ... */
a1331cc4
N
330 fprintf(stderr, Name ": An option must be given to set the mode before a second device\n"
331 " (%s) is listed\n", optarg);
0320ea45
NB
332 exit(2);
333 }
e0d19036 334 if (option_index >= 0)
0320ea45 335 fprintf(stderr, Name ": --%s", long_options[option_index].name);
e0d19036 336 else
0320ea45
NB
337 fprintf(stderr, Name ": -%c", opt);
338 fprintf(stderr, " does not set the mode, and so cannot be the first option.\n");
e0d19036
NB
339 exit(2);
340 }
341
342 /* if we just set the mode, then done */
343 switch(opt) {
1c7a808c
N
344 case ManageOpt:
345 case MiscOpt:
e0d19036
NB
346 case 'A':
347 case 'B':
348 case 'C':
349 case 'F':
dd0781e5 350 case 'G':
8382f19b 351 case 'I':
1f48664b 352 case AutoDetect:
e0d19036
NB
353 continue;
354 }
355 if (opt == 1) {
356 /* an undecorated option - must be a device name.
357 */
1c7a808c
N
358 if (devs_found > 0 && mode == MANAGE && !devmode) {
359 fprintf(stderr, Name ": Must give one of -a/-r/-f"
360 " for subsequent devices at %s\n", optarg);
52826846
NB
361 exit(2);
362 }
1c7a808c
N
363 if (devs_found > 0 && mode == GROW && !devmode) {
364 fprintf(stderr, Name ": Must give -a/--add for"
365 " devices to add: %s\n", optarg);
e5329c37
NB
366 exit(2);
367 }
cd29a5c8
NB
368 dv = malloc(sizeof(*dv));
369 if (dv == NULL) {
370 fprintf(stderr, Name ": malloc failed\n");
371 exit(3);
372 }
373 dv->devname = optarg;
374 dv->disposition = devmode;
dfd4d8ee 375 dv->writemostly = writemostly;
fe80f49b 376 dv->re_add = re_add;
9008ed1c 377 dv->used = 0;
cd29a5c8
NB
378 dv->next = NULL;
379 *devlistend = dv;
380 devlistend = &dv->next;
aba69144 381
52826846
NB
382 devs_found++;
383 continue;
682c7051 384 }
682c7051 385
52826846
NB
386 /* We've got a mode, and opt is now something else which
387 * could depend on the mode */
1c7a808c 388#define O(a,b) ((a<<16)|b)
52826846 389 switch (O(mode,opt)) {
7236ee7a 390 case O(GROW,'c'):
1c7a808c 391 case O(GROW,ChunkSize):
e0d19036 392 case O(CREATE,'c'):
1c7a808c 393 case O(CREATE,ChunkSize):
e0d19036 394 case O(BUILD,'c'): /* chunk or rounding */
1c7a808c 395 case O(BUILD,ChunkSize): /* chunk or rounding */
52826846
NB
396 if (chunk) {
397 fprintf(stderr, Name ": chunk/rounding may only be specified once. "
398 "Second value is %s.\n", optarg);
399 exit(2);
400 }
36fad8ec 401 chunk = parse_size(optarg);
a252c078 402 if (chunk < 8 || (chunk&1)) {
52826846
NB
403 fprintf(stderr, Name ": invalid chunk/rounding value: %s\n",
404 optarg);
405 exit(2);
406 }
a252c078 407 /* Convert sectors to K */
36fad8ec 408 chunk /= 2;
52826846 409 continue;
64c4757e 410
8382f19b 411 case O(INCREMENTAL, 'e'):
f9ce90ba
NB
412 case O(CREATE,'e'):
413 case O(ASSEMBLE,'e'):
414 case O(MISC,'e'): /* set metadata (superblock) information */
415 if (ss) {
416 fprintf(stderr, Name ": metadata information already given\n");
417 exit(2);
418 }
aba69144 419 for(i=0; !ss && superlist[i]; i++)
82d9eba6
NB
420 ss = superlist[i]->match_metadata_desc(optarg);
421
f9ce90ba
NB
422 if (!ss) {
423 fprintf(stderr, Name ": unrecognised metadata identifier: %s\n", optarg);
424 exit(2);
425 }
426 continue;
427
dfd4d8ee 428 case O(MANAGE,'W'):
1c7a808c 429 case O(MANAGE,WriteMostly):
dfd4d8ee 430 case O(BUILD,'W'):
1c7a808c 431 case O(BUILD,WriteMostly):
dfd4d8ee 432 case O(CREATE,'W'):
1c7a808c 433 case O(CREATE,WriteMostly):
dfd4d8ee
NB
434 /* set write-mostly for following devices */
435 writemostly = 1;
436 continue;
437
b3d31955
N
438 case O(MANAGE,'w'):
439 /* clear write-mostly for following devices */
440 writemostly = 2;
441 continue;
442
443
dd0781e5 444 case O(GROW,'z'):
25affb56
PC
445 case O(CREATE,'z'):
446 case O(BUILD,'z'): /* size */
dd0781e5 447 if (size >= 0) {
52826846
NB
448 fprintf(stderr, Name ": size may only be specified once. "
449 "Second value is %s.\n", optarg);
450 exit(2);
451 }
dd0781e5
NB
452 if (strcmp(optarg, "max")==0)
453 size = 0;
454 else {
5f4fc0e1
N
455 size = parse_size(optarg);
456 if (size < 8) {
dd0781e5
NB
457 fprintf(stderr, Name ": invalid size: %s\n",
458 optarg);
459 exit(2);
460 }
5f4fc0e1
N
461 /* convert sectors to K */
462 size /= 2;
52826846
NB
463 }
464 continue;
64c4757e 465
84e11361
N
466 case O(GROW,'Z'): /* array size */
467 if (array_size >= 0) {
468 fprintf(stderr, Name ": array-size may only be specified once. "
469 "Second value is %s.\n", optarg);
470 exit(2);
471 }
472 if (strcmp(optarg, "max") == 0)
473 array_size = 0;
474 else {
475 array_size = parse_size(optarg);
476 if (array_size <= 0) {
477 fprintf(stderr, Name ": invalid array size: %s\n",
478 optarg);
479 exit(2);
480 }
481 }
482 continue;
483
7236ee7a 484 case O(GROW,'l'):
e0d19036
NB
485 case O(CREATE,'l'):
486 case O(BUILD,'l'): /* set raid level*/
98c6faba 487 if (level != UnSet) {
52826846
NB
488 fprintf(stderr, Name ": raid level may only be set once. "
489 "Second value is %s.\n", optarg);
490 exit(2);
491 }
492 level = map_name(pers, optarg);
98c6faba 493 if (level == UnSet) {
52826846
NB
494 fprintf(stderr, Name ": invalid raid level: %s\n",
495 optarg);
496 exit(2);
497 }
e0fe762a
N
498 if (level != 0 && level != LEVEL_LINEAR && level != 1 &&
499 level != LEVEL_MULTIPATH && level != LEVEL_FAULTY &&
500 level != 10 &&
501 mode == BUILD) {
52826846
NB
502 fprintf(stderr, Name ": Raid level %s not permitted with --build.\n",
503 optarg);
504 exit(2);
505 }
e0d19036 506 if (sparedisks > 0 && level < 1 && level >= -1) {
b83d95f3 507 fprintf(stderr, Name ": raid level %s is incompatible with spare-devices setting.\n",
52826846
NB
508 optarg);
509 exit(2);
510 }
cd29a5c8 511 ident.level = level;
52826846 512 continue;
64c4757e 513
19678e53 514 case O(GROW, 'p'): /* new layout */
1c7a808c 515 case O(GROW, Layout):
19678e53
N
516 if (layout_str) {
517 fprintf(stderr,Name ": layout may only be sent once. "
518 "Second value was %s\n", optarg);
519 exit(2);
520 }
521 layout_str = optarg;
522 /* 'Grow' will parse the value */
523 continue;
524
e0d19036 525 case O(CREATE,'p'): /* raid5 layout */
1c7a808c 526 case O(CREATE,Layout):
b5e64645 527 case O(BUILD,'p'): /* faulty layout */
1c7a808c 528 case O(BUILD,Layout):
e5329c37 529 if (layout != UnSet) {
52826846
NB
530 fprintf(stderr,Name ": layout may only be sent once. "
531 "Second value was %s\n", optarg);
532 exit(2);
533 }
534 switch(level) {
535 default:
56eb10c0 536 fprintf(stderr, Name ": layout not meaningful for %s arrays.\n",
52826846
NB
537 map_num(pers, level));
538 exit(2);
98c6faba 539 case UnSet:
52826846
NB
540 fprintf(stderr, Name ": raid level must be given before layout.\n");
541 exit(2);
542
543 case 5:
544 layout = map_name(r5layout, optarg);
98c6faba 545 if (layout==UnSet) {
52826846
NB
546 fprintf(stderr, Name ": layout %s not understood for raid5.\n",
547 optarg);
548 exit(2);
549 }
550 break;
b640a252
N
551 case 6:
552 layout = map_name(r6layout, optarg);
553 if (layout==UnSet) {
554 fprintf(stderr, Name ": layout %s not understood for raid6.\n",
555 optarg);
556 exit(2);
557 }
558 break;
e5329c37
NB
559
560 case 10:
4a06e2c2
N
561 layout = parse_layout_10(optarg);
562 if (layout < 0) {
b578481c 563 fprintf(stderr, Name ": layout for raid10 must be 'nNN', 'oNN' or 'fNN' where NN is a number, not %s\n", optarg);
e5329c37
NB
564 exit(2);
565 }
e5329c37 566 break;
19678e53
N
567 case LEVEL_FAULTY:
568 /* Faulty
569 * modeNNN
570 */
4a06e2c2
N
571 layout = parse_layout_faulty(optarg);
572 if (layout == -1) {
b5e64645
NB
573 fprintf(stderr, Name ": layout %s not understood for faulty.\n",
574 optarg);
575 exit(2);
576 }
4a06e2c2 577 break;
52826846
NB
578 }
579 continue;
580
997aed5d
NB
581 case O(CREATE,AssumeClean):
582 case O(BUILD,AssumeClean): /* assume clean */
ce52f92f 583 case O(GROW,AssumeClean):
dd0781e5
NB
584 assume_clean = 1;
585 continue;
586
587 case O(GROW,'n'):
e0d19036
NB
588 case O(CREATE,'n'):
589 case O(BUILD,'n'): /* number of raid disks */
52826846 590 if (raiddisks) {
b83d95f3 591 fprintf(stderr, Name ": raid-devices set twice: %d and %s\n",
52826846
NB
592 raiddisks, optarg);
593 exit(2);
594 }
595 raiddisks = strtol(optarg, &c, 10);
e4c4352e 596 if (!optarg[0] || *c || raiddisks<=0) {
b83d95f3 597 fprintf(stderr, Name ": invalid number of raid devices: %s\n",
52826846
NB
598 optarg);
599 exit(2);
600 }
cd29a5c8 601 ident.raid_disks = raiddisks;
52826846
NB
602 continue;
603
18361a1a 604 case O(CREATE,'x'): /* number of spare (eXtra) disks */
52826846 605 if (sparedisks) {
b83d95f3 606 fprintf(stderr,Name ": spare-devices set twice: %d and %s\n",
52826846
NB
607 sparedisks, optarg);
608 exit(2);
609 }
98c6faba 610 if (level != UnSet && level <= 0 && level >= -1) {
b83d95f3 611 fprintf(stderr, Name ": spare-devices setting is incompatible with raid level %d\n",
52826846
NB
612 level);
613 exit(2);
614 }
615 sparedisks = strtol(optarg, &c, 10);
e4c4352e 616 if (!optarg[0] || *c || sparedisks < 0) {
b83d95f3 617 fprintf(stderr, Name ": invalid number of spare-devices: %s\n",
52826846
NB
618 optarg);
619 exit(2);
620 }
621 continue;
dd0781e5
NB
622
623 case O(CREATE,'a'):
1c7a808c 624 case O(CREATE,Auto):
dd0781e5 625 case O(BUILD,'a'):
1c7a808c 626 case O(BUILD,Auto):
95b79df0 627 case O(INCREMENTAL,'a'):
1c7a808c
N
628 case O(INCREMENTAL,Auto):
629 case O(ASSEMBLE,'a'):
630 case O(ASSEMBLE,Auto): /* auto-creation of device node */
f1ae21c4 631 autof = parse_auto(optarg, "--auto flag", 0);
dd0781e5
NB
632 continue;
633
38098016
NB
634 case O(CREATE,Symlinks):
635 case O(BUILD,Symlinks):
636 case O(ASSEMBLE,Symlinks): /* auto creation of symlinks in /dev to /dev/md */
637 symlinks = optarg;
638 continue;
639
aa88f531 640 case O(BUILD,'f'): /* force honouring '-n 1' */
1c7a808c 641 case O(BUILD,Force): /* force honouring '-n 1' */
bd72c2b2 642 case O(GROW,'f'): /* ditto */
1c7a808c 643 case O(GROW,Force): /* ditto */
e0d19036 644 case O(CREATE,'f'): /* force honouring of device list */
1c7a808c 645 case O(CREATE,Force): /* force honouring of device list */
e0d19036 646 case O(ASSEMBLE,'f'): /* force assembly */
1c7a808c 647 case O(ASSEMBLE,Force): /* force assembly */
e0d19036 648 case O(MISC,'f'): /* force zero */
1c7a808c 649 case O(MISC,Force): /* force zero */
11b391ec 650 case O(MANAGE,Force): /* add device which is too large */
52826846
NB
651 force=1;
652 continue;
52826846 653 /* now for the Assemble options */
b76b30e0
AK
654 case O(ASSEMBLE, FreezeReshape): /* Freeze reshape during
655 * initrd phase */
656 case O(INCREMENTAL, FreezeReshape):
657 freeze_reshape = 1;
658 continue;
3d3dd91e 659 case O(CREATE,'u'): /* uuid of array */
e0d19036 660 case O(ASSEMBLE,'u'): /* uuid of array */
52826846 661 if (ident.uuid_set) {
cd29a5c8 662 fprintf(stderr, Name ": uuid cannot be set twice. "
52826846
NB
663 "Second value %s.\n", optarg);
664 exit(2);
665 }
666 if (parse_uuid(optarg, ident.uuid))
667 ident.uuid_set = 1;
668 else {
669 fprintf(stderr,Name ": Bad uuid: %s\n", optarg);
670 exit(2);
671 }
672 continue;
673
947fd4dd
NB
674 case O(CREATE,'N'):
675 case O(ASSEMBLE,'N'):
aa534678 676 case O(MISC,'N'):
947fd4dd
NB
677 if (ident.name[0]) {
678 fprintf(stderr, Name ": name cannot be set twice. "
679 "Second value %s.\n", optarg);
680 exit(2);
681 }
aa534678
DW
682 if (mode == MISC && !subarray) {
683 fprintf(stderr, Name ": -N/--name only valid with --update-subarray in misc mode\n");
684 exit(2);
685 }
947fd4dd
NB
686 if (strlen(optarg) > 32) {
687 fprintf(stderr, Name ": name '%s' is too long, 32 chars max.\n",
688 optarg);
689 exit(2);
690 }
691 strcpy(ident.name, optarg);
692 continue;
693
e0d19036 694 case O(ASSEMBLE,'m'): /* super-minor for array */
1c7a808c 695 case O(ASSEMBLE,SuperMinor):
98c6faba 696 if (ident.super_minor != UnSet) {
cd29a5c8
NB
697 fprintf(stderr, Name ": super-minor cannot be set twice. "
698 "Second value: %s.\n", optarg);
699 exit(2);
700 }
d013a55e
NB
701 if (strcmp(optarg, "dev")==0)
702 ident.super_minor = -2;
703 else {
704 ident.super_minor = strtoul(optarg, &cp, 10);
705 if (!optarg[0] || *cp) {
706 fprintf(stderr, Name ": Bad super-minor number: %s.\n", optarg);
707 exit(2);
708 }
cd29a5c8
NB
709 }
710 continue;
711
5787fa49 712 case O(ASSEMBLE,'U'): /* update the superblock */
aa534678 713 case O(MISC,'U'):
5787fa49 714 if (update) {
833bb0f8
N
715 fprintf(stderr, Name ": Can only update one aspect"
716 " of superblock, both %s and %s given.\n",
5787fa49
NB
717 update, optarg);
718 exit(2);
719 }
aa534678 720 if (mode == MISC && !subarray) {
833bb0f8
N
721 fprintf(stderr, Name ": Only subarrays can be"
722 " updated in misc mode\n");
aa534678
DW
723 exit(2);
724 }
5787fa49 725 update = optarg;
aba69144 726 if (strcmp(update, "sparc2.2")==0)
e5329c37 727 continue;
5787fa49
NB
728 if (strcmp(update, "super-minor") == 0)
729 continue;
feb716e9
NB
730 if (strcmp(update, "summaries")==0)
731 continue;
e5329c37
NB
732 if (strcmp(update, "resync")==0)
733 continue;
7d99579f
NB
734 if (strcmp(update, "uuid")==0)
735 continue;
c4f12c13
NB
736 if (strcmp(update, "name")==0)
737 continue;
0237e0ca
NB
738 if (strcmp(update, "homehost")==0)
739 continue;
bee8ec56
NB
740 if (strcmp(update, "devicesize")==0)
741 continue;
5a31170d
N
742 if (strcmp(update, "no-bitmap")==0)
743 continue;
586ed405
NB
744 if (strcmp(update, "byteorder")==0) {
745 if (ss) {
833bb0f8
N
746 fprintf(stderr,
747 Name ": must not set metadata"
748 " type with --update=byteorder.\n");
586ed405
NB
749 exit(2);
750 }
aba69144 751 for(i=0; !ss && superlist[i]; i++)
833bb0f8
N
752 ss = superlist[i]->match_metadata_desc(
753 "0.swap");
586ed405 754 if (!ss) {
833bb0f8
N
755 fprintf(stderr, Name ": INTERNAL ERROR"
756 " cannot find 0.swap\n");
586ed405
NB
757 exit(2);
758 }
759
760 continue;
761 }
0047d254
NB
762 if (strcmp(update,"?") == 0 ||
763 strcmp(update, "help") == 0) {
764 outf = stdout;
765 fprintf(outf, Name ": ");
766 } else {
767 outf = stderr;
768 fprintf(outf,
769 Name ": '--update=%s' is invalid. ",
770 update);
771 }
772 fprintf(outf, "Valid --update options are:\n"
bee8ec56 773 " 'sparc2.2', 'super-minor', 'uuid', 'name', 'resync',\n"
5a31170d
N
774 " 'summaries', 'homehost', 'byteorder', 'devicesize',\n"
775 " 'no-bitmap'\n");
0047d254 776 exit(outf == stdout ? 0 : 2);
5787fa49 777
833bb0f8
N
778 case O(MANAGE,'U'):
779 /* update=devicesize is allowed with --re-add */
780 if (devmode != 'a' || re_add != 1) {
781 fprintf(stderr, Name "--update in Manage mode only"
782 " allowed with --re-add.\n");
783 exit(1);
784 }
785 if (update) {
786 fprintf(stderr, Name ": Can only update one aspect"
787 " of superblock, both %s and %s given.\n",
788 update, optarg);
789 exit(2);
790 }
791 update = optarg;
792 if (strcmp(update, "devicesize") != 0) {
793 fprintf(stderr, Name ": only 'devicesize' can be"
794 " updated with --re-add\n");
795 exit(2);
796 }
797 continue;
798
172356c9
DW
799 case O(INCREMENTAL,NoDegraded):
800 fprintf(stderr, Name ": --no-degraded is deprecated in Incremental mode\n");
997aed5d 801 case O(ASSEMBLE,NoDegraded): /* --no-degraded */
0047d254
NB
802 runstop = -1; /* --stop isn't allowed for --assemble,
803 * so we overload slightly */
b8a8ccf9
NB
804 continue;
805
1c7a808c
N
806 case O(ASSEMBLE,'c'):
807 case O(ASSEMBLE,ConfigFile):
7b187ed7 808 case O(INCREMENTAL, 'c'):
1c7a808c 809 case O(INCREMENTAL, ConfigFile):
2d465520 810 case O(MISC, 'c'):
1c7a808c 811 case O(MISC, ConfigFile):
e0d19036 812 case O(MONITOR,'c'):
1c7a808c 813 case O(MONITOR,ConfigFile):
52826846
NB
814 if (configfile) {
815 fprintf(stderr, Name ": configfile cannot be set twice. "
816 "Second value is %s.\n", optarg);
817 exit(2);
818 }
819 configfile = optarg;
8aec876d 820 set_conffile(configfile);
52826846
NB
821 /* FIXME possibly check that config file exists. Even parse it */
822 continue;
e0d19036
NB
823 case O(ASSEMBLE,'s'): /* scan */
824 case O(MISC,'s'):
825 case O(MONITOR,'s'):
8382f19b 826 case O(INCREMENTAL,'s'):
52826846
NB
827 scan = 1;
828 continue;
829
e0d19036 830 case O(MONITOR,'m'): /* mail address */
1c7a808c 831 case O(MONITOR,EMail):
52826846
NB
832 if (mailaddr)
833 fprintf(stderr, Name ": only specify one mailaddress. %s ignored.\n",
834 optarg);
835 else
836 mailaddr = optarg;
837 continue;
838
e0d19036 839 case O(MONITOR,'p'): /* alert program */
1c7a808c 840 case O(MONITOR,ProgramOpt): /* alert program */
52826846
NB
841 if (program)
842 fprintf(stderr, Name ": only specify one alter program. %s ignored.\n",
843 optarg);
844 else
845 program = optarg;
846 continue;
64c4757e 847
9a36a9b7 848 case O(MONITOR,'r'): /* rebuild increments */
1c7a808c 849 case O(MONITOR,Increment):
9a36a9b7 850 increments = atoi(optarg);
18361a1a 851 if (increments > 99 || increments < 1) {
9a36a9b7
ZB
852 fprintf(stderr, Name ": please specify positive integer between 1 and 99 as rebuild increments.\n");
853 exit(2);
854 }
855 continue;
856
e0d19036 857 case O(MONITOR,'d'): /* delay in seconds */
f5e166fe 858 case O(GROW, 'd'):
c82f047c
NB
859 case O(BUILD,'d'): /* delay for bitmap updates */
860 case O(CREATE,'d'):
52826846
NB
861 if (delay)
862 fprintf(stderr, Name ": only specify delay once. %s ignored.\n",
863 optarg);
864 else {
865 delay = strtol(optarg, &c, 10);
866 if (!optarg[0] || *c || delay<1) {
867 fprintf(stderr, Name ": invalid delay: %s\n",
868 optarg);
869 exit(2);
870 }
871 }
872 continue;
d013a55e 873 case O(MONITOR,'f'): /* daemonise */
1c7a808c 874 case O(MONITOR,Fork):
d013a55e
NB
875 daemonise = 1;
876 continue;
b5e64645
NB
877 case O(MONITOR,'i'): /* pid */
878 if (pidfile)
879 fprintf(stderr, Name ": only specify one pid file. %s ignored.\n",
880 optarg);
881 else
882 pidfile = optarg;
883 continue;
aa88f531
NB
884 case O(MONITOR,'1'): /* oneshot */
885 oneshot = 1;
3f555346 886 spare_sharing = 0;
aa88f531 887 continue;
98c6faba
NB
888 case O(MONITOR,'t'): /* test */
889 test = 1;
890 continue;
773135f5 891 case O(MONITOR,'y'): /* log messages to syslog */
6ac8aac2 892 openlog("mdadm", LOG_PID, SYSLOG_FACILITY);
773135f5
NB
893 dosyslog = 1;
894 continue;
edde9560
AC
895 case O(MONITOR, NoSharing):
896 spare_sharing = 0;
897 continue;
18361a1a 898
52826846
NB
899 /* now the general management options. Some are applicable
900 * to other modes. None have arguments.
901 */
e5329c37 902 case O(GROW,'a'):
1c7a808c
N
903 case O(GROW,Add):
904 case O(MANAGE,'a'):
905 case O(MANAGE,Add): /* add a drive */
52826846 906 devmode = 'a';
fe80f49b
NB
907 re_add = 0;
908 continue;
997aed5d 909 case O(MANAGE,ReAdd):
fe80f49b
NB
910 devmode = 'a';
911 re_add = 1;
52826846 912 continue;
e0d19036 913 case O(MANAGE,'r'): /* remove a drive */
1c7a808c 914 case O(MANAGE,Remove):
52826846
NB
915 devmode = 'r';
916 continue;
e0d19036 917 case O(MANAGE,'f'): /* set faulty */
1c7a808c
N
918 case O(MANAGE,Fail):
919 case O(INCREMENTAL,'f'):
920 case O(INCREMENTAL,Remove):
921 case O(INCREMENTAL,Fail): /* r for incremental is taken, use f
29ba4804
N
922 * even though we will both fail and
923 * remove the device */
52826846
NB
924 devmode = 'f';
925 continue;
8382f19b 926 case O(INCREMENTAL,'R'):
e0d19036
NB
927 case O(MANAGE,'R'):
928 case O(ASSEMBLE,'R'):
929 case O(BUILD,'R'):
930 case O(CREATE,'R'): /* Run the array */
52826846
NB
931 if (runstop < 0) {
932 fprintf(stderr, Name ": Cannot both Stop and Run an array\n");
933 exit(2);
934 }
935 runstop = 1;
936 continue;
e0d19036 937 case O(MANAGE,'S'):
52826846
NB
938 if (runstop > 0) {
939 fprintf(stderr, Name ": Cannot both Run and Stop an array\n");
940 exit(2);
941 }
942 runstop = -1;
943 continue;
7d2e6486
N
944 case O(MANAGE,'t'):
945 test = 1;
946 continue;
52826846 947
e0d19036
NB
948 case O(MISC,'Q'):
949 case O(MISC,'D'):
950 case O(MISC,'E'):
f7d3febc 951 case O(MISC,KillOpt):
e0d19036
NB
952 case O(MISC,'R'):
953 case O(MISC,'S'):
c82f047c 954 case O(MISC,'X'):
e0d19036
NB
955 case O(MISC,'o'):
956 case O(MISC,'w'):
b90c0e9a 957 case O(MISC,'W'):
1c7a808c 958 case O(MISC, WaitOpt):
1770662b 959 case O(MISC, Waitclean):
4cce4069 960 case O(MISC, DetailPlatform):
33414a01 961 case O(MISC, KillSubarray):
aa534678 962 case O(MISC, UpdateSubarray):
5a53aeec
JS
963 if (opt == KillSubarray || opt == UpdateSubarray) {
964 if (subarray) {
965 fprintf(stderr, Name ": subarray can only"
966 " be specified once\n");
967 exit(2);
968 }
969 subarray = optarg;
970 }
e0d19036
NB
971 if (devmode && devmode != opt &&
972 (devmode == 'E' || (opt == 'E' && devmode != 'Q'))) {
aa534678
DW
973 fprintf(stderr, Name ": --examine/-E cannot be given with ");
974 if (devmode == 'E') {
975 if (option_index >= 0)
976 fprintf(stderr, "--%s\n",
977 long_options[option_index].name);
978 else
979 fprintf(stderr, "-%c\n", opt);
980 } else if (isalpha(devmode))
981 fprintf(stderr, "-%c\n", devmode);
982 else
983 fprintf(stderr, "previous option\n");
e0d19036
NB
984 exit(2);
985 }
986 devmode = opt;
987 continue;
20b60dcd
LM
988 case O(MISC, UdevRules):
989 if (devmode && devmode != opt) {
990 fprintf(stderr, Name ": --udev-rules must"
991 " be the only option.\n");
992 } else {
993 if (udev_filename)
994 fprintf(stderr, Name ": only specify one udev "
995 "rule filename. %s ignored.\n",
996 optarg);
997 else
998 udev_filename = optarg;
999 }
1000 devmode = opt;
1001 continue;
feb716e9
NB
1002 case O(MISC,'t'):
1003 test = 1;
1004 continue;
e0d19036 1005
997aed5d 1006 case O(MISC, Sparc22):
bd526cee
NB
1007 if (devmode != 'E') {
1008 fprintf(stderr, Name ": --sparc2.2 only allowed with --examine\n");
1009 exit(2);
1010 }
1011 SparcAdjust = 1;
1012 continue;
c82f047c
NB
1013
1014 case O(ASSEMBLE,'b'): /* here we simply set the bitmap file */
1c7a808c 1015 case O(ASSEMBLE,Bitmap):
c82f047c
NB
1016 if (!optarg) {
1017 fprintf(stderr, Name ": bitmap file needed with -b in --assemble mode\n");
1018 exit(2);
1019 }
55935d51
NB
1020 if (strcmp(optarg, "internal")==0) {
1021 fprintf(stderr, Name ": there is no need to specify --bitmap when assembling arrays with internal bitmaps\n");
1022 continue;
1023 }
c82f047c
NB
1024 bitmap_fd = open(optarg, O_RDWR);
1025 if (!*optarg || bitmap_fd < 0) {
1026 fprintf(stderr, Name ": cannot open bitmap file %s: %s\n", optarg, strerror(errno));
1027 exit(2);
1028 }
1029 ident.bitmap_fd = bitmap_fd; /* for Assemble */
1030 continue;
f5e166fe 1031
997aed5d
NB
1032 case O(ASSEMBLE, BackupFile):
1033 case O(GROW, BackupFile):
06b0d786
NB
1034 /* Specify a file into which grow might place a backup,
1035 * or from which assemble might recover a backup
1036 */
1037 if (backup_file) {
1038 fprintf(stderr, Name ": backup file already specified, rejecting %s\n", optarg);
1039 exit(2);
1040 }
1041 backup_file = optarg;
1042 continue;
1043
2dddadb0
AK
1044 case O(GROW, Continue):
1045 /* Continue interrupted grow
1046 */
1047 grow_continue = 1;
1048 continue;
87f26d14
N
1049 case O(ASSEMBLE, InvalidBackup):
1050 /* Acknowledge that the backupfile is invalid, but ask
1051 * to continue anyway
1052 */
1053 invalid_backup = 1;
1054 continue;
1055
c82f047c 1056 case O(BUILD,'b'):
1c7a808c
N
1057 case O(BUILD,Bitmap):
1058 case O(CREATE,'b'):
1059 case O(CREATE,Bitmap): /* here we create the bitmap */
85375d6d
NB
1060 if (strcmp(optarg, "none") == 0) {
1061 fprintf(stderr, Name ": '--bitmap none' only"
18361a1a 1062 " supported for --grow\n");
85375d6d
NB
1063 exit(2);
1064 }
1065 /* FALL THROUGH */
1066 case O(GROW,'b'):
1c7a808c 1067 case O(GROW,Bitmap):
1e0d770c
NB
1068 if (strcmp(optarg, "internal")== 0 ||
1069 strcmp(optarg, "none")== 0 ||
1070 strchr(optarg, '/') != NULL) {
1071 bitmap_file = optarg;
1072 continue;
1073 }
1074 /* probable typo */
a1331cc4
N
1075 fprintf(stderr, Name ": bitmap file must contain a '/', or be 'internal', or 'none'\n"
1076 " not '%s'\n", optarg);
1e0d770c 1077 exit(2);
c82f047c 1078
997aed5d
NB
1079 case O(GROW,BitmapChunk):
1080 case O(BUILD,BitmapChunk):
1081 case O(CREATE,BitmapChunk): /* bitmap chunksize */
36fad8ec 1082 bitmap_chunk = parse_size(optarg);
15632a96 1083 if (bitmap_chunk <= 0 ||
36fad8ec
N
1084 bitmap_chunk & (bitmap_chunk - 1)) {
1085 fprintf(stderr,
1086 Name ": invalid bitmap chunksize: %s\n",
1087 optarg);
c82f047c
NB
1088 exit(2);
1089 }
15632a96 1090 bitmap_chunk = bitmap_chunk * 512;
c82f047c 1091 continue;
dfd4d8ee 1092
7d19ad0d 1093 case O(GROW, WriteBehind):
997aed5d
NB
1094 case O(BUILD, WriteBehind):
1095 case O(CREATE, WriteBehind): /* write-behind mode */
dfd4d8ee
NB
1096 write_behind = DEFAULT_MAX_WRITE_BEHIND;
1097 if (optarg) {
1098 write_behind = strtol(optarg, &c, 10);
1099 if (write_behind < 0 || *c ||
1100 write_behind > 16383) {
1101 fprintf(stderr, Name ": Invalid value for maximum outstanding write-behind writes: %s.\n\tMust be between 0 and 16383.\n", optarg);
1102 exit(2);
1103 }
1104 }
1105 continue;
8382f19b
NB
1106
1107 case O(INCREMENTAL, 'r'):
1c7a808c 1108 case O(INCREMENTAL, RebuildMapOpt):
8382f19b
NB
1109 rebuild_map = 1;
1110 continue;
950bc344
PC
1111 case O(INCREMENTAL, IncrementalPath):
1112 remove_path = optarg;
1113 continue;
52826846
NB
1114 }
1115 /* We have now processed all the valid options. Anything else is
1116 * an error
1117 */
06b0d786
NB
1118 if (option_index > 0)
1119 fprintf(stderr, Name ":option --%s not valid in %s mode\n",
1120 long_options[option_index].name,
1121 map_num(modes, mode));
1122 else
1123 fprintf(stderr, Name ": option -%c not valid in %s mode\n",
1124 opt, map_num(modes, mode));
64c4757e 1125 exit(2);
52826846
NB
1126
1127 }
1128
3d4064cc
NB
1129 if (print_help) {
1130 char *help_text = Help;
1131 if (print_help == 2)
1132 help_text = OptionHelp;
1133 else
1134 switch (mode) {
1135 case ASSEMBLE : help_text = Help_assemble; break;
1136 case BUILD : help_text = Help_build; break;
1137 case CREATE : help_text = Help_create; break;
1138 case MANAGE : help_text = Help_manage; break;
1139 case MISC : help_text = Help_misc; break;
1140 case MONITOR : help_text = Help_monitor; break;
1141 case GROW : help_text = Help_grow; break;
8382f19b 1142 case INCREMENTAL:help_text= Help_incr; break;
3d4064cc 1143 }
0047d254 1144 fputs(help_text,stdout);
3d4064cc
NB
1145 exit(0);
1146 }
1147
0320ea45
NB
1148 if (!mode && devs_found) {
1149 mode = MISC;
1150 devmode = 'Q';
1151 if (devlist->disposition == 0)
1152 devlist->disposition = devmode;
1153 }
52826846
NB
1154 if (!mode) {
1155 fputs(Usage, stderr);
64c4757e 1156 exit(2);
64c4757e 1157 }
38098016
NB
1158
1159 if (symlinks) {
1160 struct createinfo *ci = conf_get_create_info();
1161
1162 if (strcasecmp(symlinks, "yes") == 0)
1163 ci->symlinks = 1;
1164 else if (strcasecmp(symlinks, "no") == 0)
1165 ci->symlinks = 0;
1166 else {
1167 fprintf(stderr, Name ": option --symlinks must be 'no' or 'yes'\n");
1168 exit(2);
1169 }
1170 }
52826846
NB
1171 /* Ok, got the option parsing out of the way
1172 * hopefully it's mostly right but there might be some stuff
1173 * missing
1174 *
e0d19036 1175 * That is mosty checked in the per-mode stuff but...
52826846 1176 *
18361a1a
N
1177 * For @,B,C and A without -s, the first device listed must be
1178 * an md device. We check that here and open it.
64c4757e 1179 */
52826846 1180
18361a1a
N
1181 if (mode == MANAGE || mode == BUILD || mode == CREATE
1182 || mode == GROW
1183 || (mode == ASSEMBLE && ! scan)) {
52826846
NB
1184 if (devs_found < 1) {
1185 fprintf(stderr, Name ": an md device must be given in this mode\n");
1186 exit(2);
1187 }
dd0781e5 1188 if ((int)ident.super_minor == -2 && autof) {
aba69144 1189 fprintf(stderr, Name ": --super-minor=dev is incompatible with --auto\n");
dd0781e5
NB
1190 exit(2);
1191 }
7f91af49 1192 if (mode == MANAGE || mode == GROW) {
6be1d39d 1193 mdfd = open_mddev(devlist->devname, 1);
7f91af49
N
1194 if (mdfd < 0)
1195 exit(1);
1196 } else
1197 /* non-existent device is OK */
1198 mdfd = open_mddev(devlist->devname, 0);
1199 if (mdfd == -2) {
1200 fprintf(stderr, Name ": device %s exists but is not an "
1201 "md array.\n", devlist->devname);
52826846 1202 exit(1);
7f91af49 1203 }
98c6faba 1204 if ((int)ident.super_minor == -2) {
d013a55e 1205 struct stat stb;
7f91af49
N
1206 if (mdfd < 0) {
1207 fprintf(stderr, Name ": --super-minor=dev given, and "
1208 "listed device %s doesn't exist.\n",
1209 devlist->devname);
1210 exit(1);
1211 }
d013a55e 1212 fstat(mdfd, &stb);
0df46c2a 1213 ident.super_minor = minor(stb.st_rdev);
d013a55e 1214 }
7f91af49
N
1215 if (mdfd >= 0 && mode != MANAGE && mode != GROW) {
1216 /* We don't really want this open yet, we just might
1217 * have wanted to check some things
1218 */
1219 close(mdfd);
1220 mdfd = -1;
1221 }
64c4757e 1222 }
52826846 1223
e4c4352e 1224 if (raiddisks) {
18361a1a 1225 if (raiddisks == 1 && !force && level != LEVEL_FAULTY) {
e4c4352e
NB
1226 fprintf(stderr, Name ": '1' is an unusual number of drives for an array, so it is probably\n"
1227 " a mistake. If you really mean it you will need to specify --force before\n"
1228 " setting the number of drives.\n");
1229 exit(2);
1230 }
1231 }
c82f047c 1232
997aed5d 1233 if (homehost == NULL)
0ac91628 1234 homehost = conf_get_homehost(&require_homehost);
0f23aa88 1235 if (homehost == NULL || strcasecmp(homehost, "<system>")==0) {
05697ec1
NB
1236 if (gethostname(sys_hostname, sizeof(sys_hostname)) == 0) {
1237 sys_hostname[sizeof(sys_hostname)-1] = 0;
1238 homehost = sys_hostname;
1239 }
1240 }
0f23aa88
N
1241 if (homehost && (!homehost[0] || strcasecmp(homehost, "<none>") == 0)) {
1242 homehost = NULL;
1243 require_homehost = 0;
1244 }
997aed5d 1245
18361a1a
N
1246 if ((mode == MISC && devmode == 'E')
1247 || (mode == MONITOR && spare_sharing == 0))
1248 /* Anyone may try this */;
1249 else if (geteuid() != 0) {
ac5678dd
N
1250 fprintf(stderr, Name ": must be super-user to perform this action\n");
1251 exit(1);
1252 }
1253
7f91af49
N
1254 ident.autof = autof;
1255
52826846
NB
1256 rv = 0;
1257 switch(mode) {
e0d19036 1258 case MANAGE:
52826846
NB
1259 /* readonly, add/remove, readwrite, runstop */
1260 if (readonly>0)
cd29a5c8 1261 rv = Manage_ro(devlist->devname, mdfd, readonly);
52826846 1262 if (!rv && devs_found>1)
cd29a5c8 1263 rv = Manage_subdevs(devlist->devname, mdfd,
833bb0f8 1264 devlist->next, verbose-quiet, test,
11b391ec 1265 update, force);
52826846 1266 if (!rv && readonly < 0)
cd29a5c8 1267 rv = Manage_ro(devlist->devname, mdfd, readonly);
52826846 1268 if (!rv && runstop)
ab56093f 1269 rv = Manage_runstop(devlist->devname, mdfd, runstop, quiet);
52826846 1270 break;
e0d19036 1271 case ASSEMBLE:
d013a55e 1272 if (devs_found == 1 && ident.uuid_set == 0 &&
947fd4dd 1273 ident.super_minor == UnSet && ident.name[0] == 0 && !scan ) {
d013a55e 1274 /* Only a device has been given, so get details from config file */
fa56eddb 1275 struct mddev_ident *array_ident = conf_get_ident(devlist->devname);
b5e64645
NB
1276 if (array_ident == NULL) {
1277 fprintf(stderr, Name ": %s not identified in config file.\n",
1278 devlist->devname);
d013a55e 1279 rv |= 1;
7f91af49
N
1280 if (mdfd >= 0)
1281 close(mdfd);
b5e64645 1282 } else {
7f91af49
N
1283 if (array_ident->autof == 0)
1284 array_ident->autof = autof;
1285 rv |= Assemble(ss, devlist->devname, array_ident,
87f26d14 1286 NULL, backup_file, invalid_backup,
0ac91628
N
1287 readonly, runstop, update,
1288 homehost, require_homehost,
b76b30e0
AK
1289 verbose-quiet, force,
1290 freeze_reshape);
d013a55e
NB
1291 }
1292 } else if (!scan)
7f91af49 1293 rv = Assemble(ss, devlist->devname, &ident,
87f26d14 1294 devlist->next, backup_file, invalid_backup,
0ac91628
N
1295 readonly, runstop, update,
1296 homehost, require_homehost,
b76b30e0
AK
1297 verbose-quiet, force,
1298 freeze_reshape);
18361a1a 1299 else if (devs_found > 0) {
5787fa49
NB
1300 if (update && devs_found > 1) {
1301 fprintf(stderr, Name ": can only update a single array at a time\n");
1302 exit(1);
1303 }
06b0d786
NB
1304 if (backup_file && devs_found > 1) {
1305 fprintf(stderr, Name ": can only assemble a single array when providing a backup file.\n");
1306 exit(1);
1307 }
cd29a5c8 1308 for (dv = devlist ; dv ; dv=dv->next) {
fa56eddb 1309 struct mddev_ident *array_ident = conf_get_ident(dv->devname);
52826846
NB
1310 if (array_ident == NULL) {
1311 fprintf(stderr, Name ": %s not identified in config file.\n",
cd29a5c8 1312 dv->devname);
52826846
NB
1313 rv |= 1;
1314 continue;
1315 }
7f91af49
N
1316 if (array_ident->autof == 0)
1317 array_ident->autof = autof;
1318 rv |= Assemble(ss, dv->devname, array_ident,
87f26d14 1319 NULL, backup_file, invalid_backup,
0ac91628
N
1320 readonly, runstop, update,
1321 homehost, require_homehost,
b76b30e0
AK
1322 verbose-quiet, force,
1323 freeze_reshape);
52826846 1324 }
5787fa49 1325 } else {
da6b5ca9
NB
1326 if (update) {
1327 fprintf(stderr, Name ": --update not meaningful with a --scan assembly.\n");
1328 exit(1);
1329 }
1330 if (backup_file) {
1331 fprintf(stderr, Name ": --backup_file not meaningful with a --scan assembly.\n");
1332 exit(1);
1333 }
3cbc4d12
N
1334 rv = scan_assemble(autof, ss, readonly, runstop,
1335 &ident, homehost,
1336 require_homehost,
1337 verbose - quiet,
1338 force, freeze_reshape);
52826846 1339 }
3cbc4d12 1340
52826846 1341 break;
e0d19036 1342 case BUILD:
c82f047c 1343 if (delay == 0) delay = DEFAULT_BITMAP_DELAY;
dfd4d8ee
NB
1344 if (write_behind && !bitmap_file) {
1345 fprintf(stderr, Name ": write-behind mode requires a bitmap.\n");
1346 rv = 1;
1347 break;
1348 }
5b28bd56 1349 if (raiddisks == 0) {
e5669f40 1350 fprintf(stderr, Name ": no raid-devices specified.\n");
5b28bd56
NB
1351 rv = 1;
1352 break;
1353 }
dfd4d8ee 1354
c82f047c 1355 if (bitmap_file) {
55935d51
NB
1356 if (strcmp(bitmap_file, "internal")==0) {
1357 fprintf(stderr, Name ": 'internal' bitmaps not supported with --build\n");
1358 rv |= 1;
1359 break;
1360 }
c82f047c 1361 }
7f91af49 1362 rv = Build(devlist->devname, chunk, level, layout,
c82f047c 1363 raiddisks, devlist->next, assume_clean,
7f91af49 1364 bitmap_file, bitmap_chunk, write_behind,
83208785 1365 delay, verbose-quiet, autof, size);
52826846 1366 break;
e0d19036 1367 case CREATE:
c82f047c 1368 if (delay == 0) delay = DEFAULT_BITMAP_DELAY;
dfd4d8ee
NB
1369 if (write_behind && !bitmap_file) {
1370 fprintf(stderr, Name ": write-behind mode requires a bitmap.\n");
1371 rv = 1;
1372 break;
1373 }
5b28bd56 1374 if (raiddisks == 0) {
e5669f40 1375 fprintf(stderr, Name ": no raid-devices specified.\n");
5b28bd56
NB
1376 rv = 1;
1377 break;
1378 }
f9ce90ba 1379
7f91af49 1380 rv = Create(ss, devlist->devname, chunk, level, layout, size<0 ? 0 : size,
05697ec1 1381 raiddisks, sparedisks, ident.name, homehost,
3d3dd91e 1382 ident.uuid_set ? ident.uuid : NULL,
47d79ef8 1383 devs_found-1, devlist->next, runstop, verbose-quiet, force, assume_clean,
7f91af49 1384 bitmap_file, bitmap_chunk, write_behind, delay, autof);
52826846 1385 break;
e0d19036 1386 case MISC:
e0d19036
NB
1387 if (devmode == 'E') {
1388 if (devlist == NULL && !scan) {
1389 fprintf(stderr, Name ": No devices to examine\n");
1390 exit(2);
1391 }
1392 if (devlist == NULL)
8aec876d 1393 devlist = conf_get_devs();
e0d19036 1394 if (devlist == NULL) {
c913b90e 1395 fprintf(stderr, Name ": No devices listed in %s\n", configfile?configfile:DefaultConfFile);
e0d19036
NB
1396 exit(1);
1397 }
e843d5d7
NB
1398 if (brief && verbose)
1399 brief = 2;
0d726f17
KS
1400 rv = Examine(devlist, scan?(verbose>1?0:verbose+1):brief,
1401 export, scan,
1402 SparcAdjust, ss, homehost);
4cce4069
DW
1403 } else if (devmode == DetailPlatform) {
1404 rv = Detail_Platform(ss ? ss->ss : NULL, ss ? scan : 1, verbose);
e0d19036
NB
1405 } else {
1406 if (devlist == NULL) {
fabbfd48
DW
1407 if ((devmode=='D' || devmode == Waitclean) && scan) {
1408 /* apply --detail or --wait-clean to
1409 * all devices in /proc/mdstat
1410 */
22a88995 1411 struct mdstat_ent *ms = mdstat_read(0, 1);
e0d19036 1412 struct mdstat_ent *e;
35904960 1413 struct map_ent *map = NULL;
8f1b2bbb 1414 int members;
fabbfd48
DW
1415 int v = verbose>1?0:verbose+1;
1416
8f1b2bbb 1417 for (members = 0; members <= 1; members++) {
e0d19036 1418 for (e=ms ; e ; e=e->next) {
35904960
N
1419 char *name;
1420 struct map_ent *me;
8f1b2bbb
N
1421 int member = e->metadata_version &&
1422 strncmp(e->metadata_version,
1423 "external:/", 10) == 0;
1424 if (members != member)
1425 continue;
35904960 1426 me = map_by_devnum(&map, e->devnum);
8615dcff
N
1427 if (me && me->path
1428 && strcmp(me->path, "/unknown") != 0)
35904960
N
1429 name = me->path;
1430 else
1431 name = get_md_name(e->devnum);
e0d19036
NB
1432
1433 if (!name) {
1434 fprintf(stderr, Name ": cannot find device file for %s\n",
1435 e->dev);
1436 continue;
1437 }
fabbfd48
DW
1438 if (devmode == 'D')
1439 rv |= Detail(name, v,
1440 export, test,
c2ecf5f6 1441 homehost, prefer);
fabbfd48 1442 else
9f1da824 1443 rv |= WaitClean(name, -1, v);
91f068bf
NB
1444 put_md_name(name);
1445 }
8f1b2bbb 1446 }
89a10d84 1447 free_mdstat(ms);
91f068bf
NB
1448 } else if (devmode == 'S' && scan) {
1449 /* apply --stop to all devices in /proc/mdstat */
1450 /* Due to possible stacking of devices, repeat until
1451 * nothing more can be stopped
1452 */
1453 int progress=1, err;
1454 int last = 0;
1455 do {
22a88995 1456 struct mdstat_ent *ms = mdstat_read(0, 0);
91f068bf
NB
1457 struct mdstat_ent *e;
1458
1459 if (!progress) last = 1;
1460 progress = 0; err = 0;
1461 for (e=ms ; e ; e=e->next) {
1462 char *name = get_md_name(e->devnum);
1463
1464 if (!name) {
1465 fprintf(stderr, Name ": cannot find device file for %s\n",
1466 e->dev);
1467 continue;
1468 }
6be1d39d 1469 mdfd = open_mddev(name, 1);
43fc1676 1470 if (mdfd >= 0) {
ab56093f 1471 if (Manage_runstop(name, mdfd, -1, quiet?1:last?0:-1))
91f068bf
NB
1472 err = 1;
1473 else
1474 progress = 1;
43fc1676
NB
1475 close(mdfd);
1476 }
91f068bf
NB
1477
1478 put_md_name(name);
e0d19036 1479 }
89a10d84 1480 free_mdstat(ms);
91f068bf 1481 } while (!last && err);
f9c25f1d 1482 if (err) rv |= 1;
20b60dcd
LM
1483 } else if (devmode == UdevRules) {
1484 rv = Write_rules(udev_filename);
91f068bf 1485 } else {
e0d19036
NB
1486 fprintf(stderr, Name ": No devices given.\n");
1487 exit(2);
1488 }
1489 }
1490 for (dv=devlist ; dv; dv=dv->next) {
1491 switch(dv->disposition) {
1492 case 'D':
54bad364
KS
1493 rv |= Detail(dv->devname,
1494 brief?1+verbose:0,
c2ecf5f6 1495 export, test, homehost, prefer);
54bad364 1496 continue;
f7d3febc 1497 case KillOpt: /* Zero superblock */
9277cc77
N
1498 if (ss)
1499 rv |= Kill(dv->devname, ss, force, quiet,0);
1500 else {
1501 int q = quiet;
1502 do {
1503 rv |= Kill(dv->devname, NULL, force, q, 0);
1504 q = 1;
4c619b29 1505 } while (rv == 0);
9277cc77
N
1506 rv &= ~2;
1507 }
111d01fc 1508 continue;
e0d19036
NB
1509 case 'Q':
1510 rv |= Query(dv->devname); continue;
c82f047c 1511 case 'X':
55935d51 1512 rv |= ExamineBitmap(dv->devname, brief, ss); continue;
b90c0e9a 1513 case 'W':
1c7a808c 1514 case WaitOpt:
b90c0e9a 1515 rv |= Wait(dv->devname); continue;
1770662b 1516 case Waitclean:
9f1da824 1517 rv |= WaitClean(dv->devname, -1, verbose-quiet); continue;
33414a01
DW
1518 case KillSubarray:
1519 rv |= Kill_subarray(dv->devname, subarray, quiet);
1520 continue;
aa534678
DW
1521 case UpdateSubarray:
1522 if (update == NULL) {
1523 fprintf(stderr,
1524 Name ": -U/--update must be specified with --update-subarray\n");
1525 rv |= 1;
1526 continue;
1527 }
1528 rv |= Update_subarray(dv->devname, subarray, update, &ident, quiet);
1529 continue;
e0d19036 1530 }
6be1d39d 1531 mdfd = open_mddev(dv->devname, 1);
43fc1676 1532 if (mdfd>=0) {
e0d19036
NB
1533 switch(dv->disposition) {
1534 case 'R':
ab56093f 1535 rv |= Manage_runstop(dv->devname, mdfd, 1, quiet); break;
e0d19036 1536 case 'S':
ab56093f 1537 rv |= Manage_runstop(dv->devname, mdfd, -1, quiet); break;
e0d19036
NB
1538 case 'o':
1539 rv |= Manage_ro(dv->devname, mdfd, 1); break;
1540 case 'w':
1541 rv |= Manage_ro(dv->devname, mdfd, -1); break;
1542 }
43fc1676 1543 close(mdfd);
7f48e210
NB
1544 } else
1545 rv |= 1;
e0d19036 1546 }
cd29a5c8 1547 }
9a9dab36 1548 break;
e0d19036 1549 case MONITOR:
e0d19036
NB
1550 if (!devlist && !scan) {
1551 fprintf(stderr, Name ": Cannot monitor: need --scan or at least one device\n");
1552 rv = 1;
1553 break;
1554 }
b5e64645
NB
1555 if (pidfile && !daemonise) {
1556 fprintf(stderr, Name ": Cannot write a pid file when not in daemon mode\n");
1557 rv = 1;
1558 break;
1559 }
ddc7201f 1560 if (delay == 0) {
3e82d76d 1561 if (get_linux_version() > 2006016)
ddc7201f
N
1562 /* mdstat responds to poll */
1563 delay = 1000;
1564 else
1565 delay = 60;
1566 }
d013a55e 1567 rv= Monitor(devlist, mailaddr, program,
773135f5 1568 delay?delay:60, daemonise, scan, oneshot,
c2ecf5f6
N
1569 dosyslog, test, pidfile, increments,
1570 spare_sharing, prefer);
9a9dab36 1571 break;
dd0781e5
NB
1572
1573 case GROW:
84e11361
N
1574 if (array_size >= 0) {
1575 /* alway impose array size first, independent of
1576 * anything else
9ce510be
N
1577 * Do not allow level or raid_disks changes at the
1578 * same time as that can be irreversibly destructive.
84e11361
N
1579 */
1580 struct mdinfo sra;
1581 int err;
9ce510be
N
1582 if (raiddisks || level != UnSet) {
1583 fprintf(stderr, Name ": cannot change array size in same operation "
1584 "as changing raiddisks or level.\n"
1585 " Change size first, then check that data is still intact.\n");
1586 rv = 1;
1587 break;
1588 }
84e11361
N
1589 sysfs_init(&sra, mdfd, 0);
1590 if (array_size == 0)
1591 err = sysfs_set_str(&sra, NULL, "array_size", "default");
1592 else
1593 err = sysfs_set_num(&sra, NULL, "array_size", array_size / 2);
1594 if (err < 0) {
1595 if (errno == E2BIG)
1596 fprintf(stderr, Name ": --array-size setting"
1597 " is too large.\n");
1598 else
1599 fprintf(stderr, Name ": current kernel does"
1600 " not support setting --array-size\n");
1601 rv = 1;
1602 break;
1603 }
1604 }
e2e53a2d 1605 if (devs_found > 1 && raiddisks == 0) {
e5329c37 1606 /* must be '-a'. */
e2e53a2d
N
1607 if (size >= 0 || chunk || layout_str != NULL || bitmap_file) {
1608 fprintf(stderr, Name ": --add cannot be used with "
1609 "other geometry changes in --grow mode\n");
e5329c37
NB
1610 rv = 1;
1611 break;
1612 }
1613 for (dv=devlist->next; dv ; dv=dv->next) {
e2e53a2d
N
1614 rv = Grow_Add_device(devlist->devname, mdfd,
1615 dv->devname);
e5329c37
NB
1616 if (rv)
1617 break;
1618 }
7236ee7a 1619 } else if (bitmap_file) {
e2e53a2d 1620 if (size >= 0 || raiddisks || chunk ||
1d8862cf 1621 layout_str != NULL || devs_found > 1) {
e2e53a2d
N
1622 fprintf(stderr, Name ": --bitmap changes cannot be "
1623 "used with other geometry changes "
1624 "in --grow mode\n");
7236ee7a
N
1625 rv = 1;
1626 break;
1627 }
1628 if (delay == 0)
1629 delay = DEFAULT_BITMAP_DELAY;
f5e166fe 1630 rv = Grow_addbitmap(devlist->devname, mdfd, bitmap_file,
8fac0577 1631 bitmap_chunk, delay, write_behind, force);
2dddadb0
AK
1632 } else if (grow_continue)
1633 rv = Grow_continue_command(devlist->devname,
1634 mdfd, backup_file,
1635 verbose);
1636 else if (size >= 0 || raiddisks != 0 || layout_str != NULL
7236ee7a
N
1637 || chunk != 0 || level != UnSet) {
1638 rv = Grow_reshape(devlist->devname, mdfd, quiet, backup_file,
691a36b7 1639 size, level, layout_str, chunk, raiddisks,
e2e53a2d 1640 devlist->next,
ce52f92f 1641 assume_clean, force);
84e11361 1642 } else if (array_size < 0)
b5e64645 1643 fprintf(stderr, Name ": no changes to --grow\n");
dd0781e5 1644 break;
8382f19b
NB
1645 case INCREMENTAL:
1646 if (rebuild_map) {
1647 RebuildMap();
1648 }
1649 if (scan) {
1650 if (runstop <= 0) {
1651 fprintf(stderr, Name
1652 ": --incremental --scan meaningless without --run.\n");
1653 break;
1654 }
29ba4804
N
1655 if (devmode == 'f') {
1656 fprintf(stderr, Name
1657 ": --incremental --scan --fail not supported.\n");
1658 break;
1659 }
8382f19b
NB
1660 rv = IncrementalScan(verbose);
1661 }
1662 if (!devlist) {
1663 if (!rebuild_map && !scan) {
1664 fprintf(stderr, Name
1665 ": --incremental requires a device.\n");
1666 rv = 1;
1667 }
1668 break;
1669 }
1670 if (devlist->next) {
1671 fprintf(stderr, Name
1672 ": --incremental can only handle one device.\n");
1673 rv = 1;
1674 break;
1675 }
950bc344
PC
1676 if (devmode == 'f')
1677 rv = IncrementalRemove(devlist->devname, remove_path,
1678 verbose-quiet);
1679 else
1680 rv = Incremental(devlist->devname, verbose-quiet,
1681 runstop, ss, homehost,
b76b30e0
AK
1682 require_homehost, autof,
1683 freeze_reshape);
1f48664b
NB
1684 break;
1685 case AUTODETECT:
1686 autodetect();
1687 break;
64c4757e 1688 }
52826846 1689 exit(rv);
64c4757e 1690}
3cbc4d12
N
1691
1692static int scan_assemble(int autof, struct supertype *ss,
1693 int readonly, int runstop,
1694 struct mddev_ident *ident,
1695 char *homehost, int require_homehost,
1696 int verbose, int force,
1697 int freeze_reshape)
1698{
1699 struct mddev_ident *a, *array_list = conf_get_ident(NULL);
1700 struct mddev_dev *devlist = conf_get_devs();
1701 struct map_ent *map = NULL;
1702 int cnt = 0;
1703 int rv = 0;
1704 int failures, successes;
1705
1706 if (conf_verify_devnames(array_list)) {
1707 fprintf(stderr, Name
1708 ": Duplicate MD device names in "
1709 "conf file were found.\n");
1710 return 1;
1711 }
1712 if (devlist == NULL) {
1713 fprintf(stderr, Name ": No devices listed in conf file were found.\n");
1714 return 1;
1715 }
1716 for (a = array_list; a ; a = a->next) {
1717 a->assembled = 0;
1718 if (a->autof == 0)
1719 a->autof = autof;
1720 }
1721 if (map_lock(&map))
1722 fprintf(stderr, Name " %s: failed to get "
1723 "exclusive lock on mapfile\n",
1724 __func__);
1725 do {
1726 failures = 0;
1727 successes = 0;
1728 rv = 0;
1729 for (a = array_list; a ; a = a->next) {
1730 int r;
1731 if (a->assembled)
1732 continue;
1733 if (a->devname &&
1734 strcasecmp(a->devname, "<ignore>") == 0)
1735 continue;
1736
1737 r = Assemble(ss, a->devname,
1738 a,
1739 NULL, NULL, 0,
1740 readonly, runstop, NULL,
1741 homehost, require_homehost,
1742 verbose, force,
1743 freeze_reshape);
1744 if (r == 0) {
1745 a->assembled = 1;
1746 successes++;
1747 } else
1748 failures++;
1749 rv |= r;
1750 cnt++;
1751 }
1752 } while (failures && successes);
1753 if (homehost && cnt == 0) {
1754 /* Maybe we can auto-assemble something.
1755 * Repeatedly call Assemble in auto-assemble mode
1756 * until it fails
1757 */
1758 int rv2;
1759 int acnt;
1760 ident->autof = autof;
1761 do {
1762 struct mddev_dev *devlist = conf_get_devs();
1763 acnt = 0;
1764 do {
1765 rv2 = Assemble(ss, NULL,
1766 ident,
1767 devlist, NULL, 0,
1768 readonly,
1769 runstop, NULL,
1770 homehost,
1771 require_homehost,
1772 verbose,
1773 force,
1774 freeze_reshape);
1775 if (rv2==0) {
1776 cnt++;
1777 acnt++;
1778 }
1779 } while (rv2!=2);
1780 /* Incase there are stacked devices, we need to go around again */
1781 } while (acnt);
1782 if (cnt == 0 && rv == 0) {
1783 fprintf(stderr, Name ": No arrays found in config file or automatically\n");
1784 rv = 1;
1785 } else if (cnt)
1786 rv = 0;
1787 } else if (cnt == 0 && rv == 0) {
1788 fprintf(stderr, Name ": No arrays found in config file\n");
1789 rv = 1;
1790 }
1791 map_unlock(&map);
1792 return rv;
1793}