Use O_EXCL when opening component devices to be assembled into an array
[thirdparty/mdadm.git] / Assemble.c
1 /*
2  * mdadm - manage Linux "md" devices aka RAID arrays.
3  *
4  * Copyright (C) 2001-2002 Neil Brown <neilb@cse.unsw.edu.au>
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
22  *    Email: <neilb@cse.unsw.edu.au>
23  *    Paper: Neil Brown
24  *           School of Computer Science and Engineering
25  *           The University of New South Wales
26  *           Sydney, 2052
27  *           Australia
28  */
29
30 #include        "mdadm.h"
31 #include        "md_u.h"
32 #include        "md_p.h"
33
34 int Assemble(char *mddev, int mdfd,
35              mddev_ident_t ident, char *conffile,
36              mddev_dev_t devlist,
37              int readonly, int runstop,
38              char *update,
39              int verbose, int force)
40 {
41         /*
42          * The task of Assemble is to find a collection of
43          * devices that should (according to their superblocks)
44          * form an array, and to give this collection to the MD driver.
45          * In Linux-2.4 and later, this involves submitting a
46          * SET_ARRAY_INFO ioctl with no arg - to prepare
47          * the array - and then submit a number of
48          * ADD_NEW_DISK ioctls to add disks into
49          * the array.  Finally RUN_ARRAY might
50          * be submitted to start the array.
51          *
52          * Much of the work of Assemble is in finding and/or
53          * checking the disks to make sure they look right.
54          *
55          * If mddev is not set, then scan must be and we
56          *  read through the config file for dev+uuid mapping
57          *  We recurse, setting mddev, for each device that
58          *    - isn't running
59          *    - has a valid uuid (or any uuid if !uuidset
60          *
61          * If mddev is set, we try to determine state of md.
62          *   check version - must be at least 0.90.0
63          *   check kernel version.  must be at least 2.4.
64          *    If not, we can possibly fall back on START_ARRAY
65          *   Try to GET_ARRAY_INFO.
66          *     If possible, give up
67          *     If not, try to STOP_ARRAY just to make sure
68          *
69          * If !uuidset and scan, look in conf-file for uuid
70          *       If not found, give up
71          * If !devlist and scan and uuidset, get list of devs from conf-file 
72          *
73          * For each device:
74          *   Check superblock - discard if bad
75          *   Check uuid (set if we don't have one) - discard if no match
76          *   Check superblock similarity if we have a superblock - discard if different
77          *   Record events, devicenum, utime
78          * This should give us a list of devices for the array
79          * We should collect the most recent event and utime numbers
80          *
81          * Count disks with recent enough event count
82          * While force && !enough disks
83          *    Choose newest rejected disks, update event count
84          *     mark clean and rewrite superblock
85          * If recent kernel:
86          *    SET_ARRAY_INFO
87          *    foreach device with recent events : ADD_NEW_DISK
88          *    if runstop == 1 || "enough" disks and runstop==0 -> RUN_ARRAY
89          * If old kernel:
90          *    Check the device numbers in superblock are right
91          *    update superblock if any changes
92          *    START_ARRAY
93          *
94          */
95         int old_linux = 0;
96         int vers;
97         mdu_array_info_t array;
98         mdp_super_t first_super, super;
99         struct {
100                 char *devname;
101                 unsigned int major, minor;
102                 unsigned int oldmajor, oldminor;
103                 long long events;
104                 time_t utime;
105                 int uptodate;
106                 int state;
107                 int raid_disk;
108         } *devices;
109         int *best = NULL; /* indexed by raid_disk */
110         unsigned int bestcnt = 0;
111         int devcnt = 0;
112         unsigned int okcnt, sparecnt;
113         unsigned int req_cnt;
114         unsigned int i;
115         int most_recent = 0;
116         int chosen_drive;
117         int change = 0;
118         int inargv = 0;
119         int start_partial_ok = force || devlist==NULL;
120         unsigned int num_devs;
121         mddev_dev_t tmpdev;
122         
123         vers = md_get_version(mdfd);
124         if (vers <= 0) {
125                 fprintf(stderr, Name ": %s appears not to be an md device.\n", mddev);
126                 return 1;
127         }
128         if (vers < 9000) {
129                 fprintf(stderr, Name ": Assemble requires driver version 0.90.0 or later.\n"
130                         "    Upgrade your kernel or try --build\n");
131                 return 1;
132         }
133         if (get_linux_version() < 2004000)
134                 old_linux = 1;
135
136         if (ioctl(mdfd, GET_ARRAY_INFO, &array)>=0) {
137                 fprintf(stderr, Name ": device %s already active - cannot assemble it\n",
138                         mddev);
139                 return 1;
140         }
141         ioctl(mdfd, STOP_ARRAY, NULL); /* just incase it was started but has no content */
142
143         /*
144          * If any subdevs are listed, then any that don't
145          * match ident are discarded.  Remainder must all match and
146          * become the array.
147          * If no subdevs, then we scan all devices in the config file, but
148          * there must be something in the identity
149          */
150
151         if (!devlist &&
152             ident->uuid_set == 0 &&
153             ident->super_minor < 0 &&
154             ident->devices == NULL) {
155                 fprintf(stderr, Name ": No identity information available for %s - cannot assemble.\n",
156                         mddev);
157                 return 1;
158         }
159         if (devlist == NULL)
160                 devlist = conf_get_devs(conffile);
161         else inargv = 1;
162
163         tmpdev = devlist; num_devs = 0;
164         while (tmpdev) {
165                 num_devs++;
166                 tmpdev = tmpdev->next;
167         }
168         best = malloc(num_devs * sizeof(*best));
169         devices = malloc(num_devs * sizeof(*devices));
170
171         first_super.md_magic = 0;
172         for (i=0; i<num_devs; i++)
173                 best[i] = -1;
174
175         if (verbose)
176             fprintf(stderr, Name ": looking for devices for %s\n",
177                     mddev);
178
179         while ( devlist) {
180                 char *devname;
181                 int this_uuid[4];
182                 int dfd;
183                 struct stat stb;
184                 int havesuper=0;
185
186                 devname = devlist->devname;
187                 devlist = devlist->next;
188
189                 if (ident->devices &&
190                     !match_oneof(ident->devices, devname)) {
191                         if (inargv || verbose)
192                                 fprintf(stderr, Name ": %s is not one of %s\n", devname, ident->devices);
193                         continue;
194                 }
195                 
196                 dfd = open(devname, O_RDONLY|O_EXCL, 0);
197                 if (dfd < 0) {
198                         if (inargv || verbose)
199                                 fprintf(stderr, Name ": cannot open device %s: %s\n",
200                                         devname, strerror(errno));
201                 } else if (fstat(dfd, &stb)< 0) {
202                         /* Impossible! */
203                         fprintf(stderr, Name ": fstat failed for %s: %s\n",
204                                 devname, strerror(errno));
205                         close(dfd);
206                 } else if ((stb.st_mode & S_IFMT) != S_IFBLK) {
207                         fprintf(stderr, Name ": %s is not a block device.\n",
208                                 devname);
209                         close(dfd);
210                 } else if (load_super(dfd, &super)) {
211                         if (inargv || verbose)
212                                 fprintf( stderr, Name ": no RAID superblock on %s\n",
213                                          devname);
214                         close(dfd);
215                 } else {
216                         havesuper =1;
217                         uuid_from_super(this_uuid, &super);
218                         close(dfd);
219                 }
220
221                 if (ident->uuid_set &&
222                     (!havesuper || same_uuid(this_uuid, ident->uuid)==0)) {
223                         if (inargv || verbose)
224                                 fprintf(stderr, Name ": %s has wrong uuid.\n",
225                                         devname);
226                         continue;
227                 }
228                 if (ident->super_minor != UnSet &&
229                     (!havesuper || ident->super_minor != super.md_minor)) {
230                         if (inargv || verbose)
231                                 fprintf(stderr, Name ": %s has wrong super-minor.\n",
232                                         devname);
233                         continue;
234                 }
235                 if (ident->level != UnSet &&
236                     (!havesuper|| ident->level != (int)super.level)) {
237                         if (inargv || verbose)
238                                 fprintf(stderr, Name ": %s has wrong raid level.\n",
239                                         devname);
240                         continue;
241                 }
242                 if (ident->raid_disks != UnSet &&
243                     (!havesuper || ident->raid_disks!= super.raid_disks)) {
244                         if (inargv || verbose)
245                                 fprintf(stderr, Name ": %s requires wrong number of drives.\n",
246                                         devname);
247                         continue;
248                 }
249
250                 /* If we are this far, then we are commited to this device.
251                  * If the super_block doesn't exist, or doesn't match others,
252                  * then we cannot continue
253                  */
254
255                 if (!havesuper) {
256                         fprintf(stderr, Name ": %s has no superblock - assembly aborted\n",
257                                 devname);
258                         return 1;
259                 }
260                 if (compare_super(&first_super, &super)) {
261                         fprintf(stderr, Name ": superblock on %s doesn't match others - assembly aborted\n",
262                                 devname);
263                         return 1;
264                 }
265
266
267                 /* this is needed until we get a more relaxed super block format */
268                 if (devcnt >= MD_SB_DISKS) {
269                     fprintf(stderr, Name ": ouch - too many devices appear to be in this array. Ignoring %s\n",
270                             devname);
271                     continue;
272                 }
273                 
274                 /* looks like a good enough match to update the super block if needed */
275                 if (update) {
276                         if (strcmp(update, "sparc2.2")==0 ) {
277                                 /* 2.2 sparc put the events in the wrong place
278                                  * So we copy the tail of the superblock
279                                  * up 4 bytes before continuing
280                                  */
281                                 __u32 *sb32 = (__u32*)&super;
282                                 memcpy(sb32+MD_SB_GENERIC_CONSTANT_WORDS+7,
283                                        sb32+MD_SB_GENERIC_CONSTANT_WORDS+7+1,
284                                        (MD_SB_WORDS - (MD_SB_GENERIC_CONSTANT_WORDS+7+1))*4);
285                                 fprintf (stderr, Name ": adjusting superblock of %s for 2.2/sparc compatability.\n",
286                                          devname);
287                         }
288                         if (strcmp(update, "super-minor") ==0) {
289                                 struct stat stb2;
290                                 fstat(mdfd, &stb2);
291                                 super.md_minor = minor(stb2.st_rdev);
292                                 if (verbose)
293                                         fprintf(stderr, Name ": updating superblock of %s with minor number %d\n",
294                                                 devname, super.md_minor);
295                         }
296                         if (strcmp(update, "summaries") == 0) {
297                                 /* set nr_disks, active_disks, working_disks,
298                                  * failed_disks, spare_disks based on disks[] 
299                                  * array in superblock.
300                                  * Also make sure extra slots aren't 'failed'
301                                  */
302                                 super.nr_disks = super.active_disks =
303                                         super.working_disks = super.failed_disks =
304                                         super.spare_disks = 0;
305                                 for (i=0; i < MD_SB_DISKS ; i++) 
306                                         if (super.disks[i].major ||
307                                             super.disks[i].minor) {
308                                                 int state = super.disks[i].state;
309                                                 if (state & (1<<MD_DISK_REMOVED))
310                                                         continue;
311                                                 super.nr_disks++;
312                                                 if (state & (1<<MD_DISK_ACTIVE))
313                                                         super.active_disks++;
314                                                 if (state & (1<<MD_DISK_FAULTY))
315                                                         super.failed_disks++;
316                                                 else
317                                                         super.working_disks++;
318                                                 if (state == 0)
319                                                         super.spare_disks++;
320                                         } else if (i >= super.raid_disks && super.disks[i].number == 0)
321                                                 super.disks[i].state = 0;
322                         }
323                         if (strcmp(update, "resync") == 0) {
324                                 /* make sure resync happens */
325                                 super.state &= ~(1<<MD_SB_CLEAN);
326                                 super.recovery_cp = 0;
327                         }
328                         super.sb_csum = calc_sb_csum(&super);
329                         dfd = open(devname, O_RDWR|O_EXCL, 0);
330                         if (dfd < 0) 
331                                 fprintf(stderr, Name ": Cannot open %s for superblock update\n",
332                                         devname);
333                         else if (store_super(dfd, &super))
334                                 fprintf(stderr, Name ": Could not re-write superblock on %s.\n",
335                                         devname);
336                         if (dfd >= 0)
337                                 close(dfd);
338                 }
339
340                 if (verbose)
341                         fprintf(stderr, Name ": %s is identified as a member of %s, slot %d.\n",
342                                 devname, mddev, super.this_disk.raid_disk);
343                 devices[devcnt].devname = devname;
344                 devices[devcnt].major = major(stb.st_rdev);
345                 devices[devcnt].minor = minor(stb.st_rdev);
346                 devices[devcnt].oldmajor = super.this_disk.major;
347                 devices[devcnt].oldminor = super.this_disk.minor;
348                 devices[devcnt].events = md_event(&super);
349                 devices[devcnt].utime = super.utime;
350                 devices[devcnt].raid_disk = super.this_disk.raid_disk;
351                 devices[devcnt].uptodate = 0;
352                 devices[devcnt].state = super.this_disk.state;
353                 if (most_recent < devcnt) {
354                         if (devices[devcnt].events
355                             > devices[most_recent].events)
356                                 most_recent = devcnt;
357                 }
358                 if ((int)super.level == -4) 
359                         /* with multipath, the raid_disk from the superblock is meaningless */
360                         i = devcnt;
361                 else
362                         i = devices[devcnt].raid_disk;
363                 if (i < 10000) {
364                         if (i >= bestcnt) {
365                                 unsigned int newbestcnt = i+10;
366                                 int *newbest = malloc(sizeof(int)*newbestcnt);
367                                 unsigned int c;
368                                 for (c=0; c < newbestcnt; c++)
369                                         if (c < bestcnt)
370                                                 newbest[c] = best[c];
371                                         else
372                                                 newbest[c] = -1;
373                                 if (best)free(best);
374                                 best = newbest;
375                                 bestcnt = newbestcnt;
376                         }
377                         if (best[i] == -1
378                             || devices[best[i]].events < devices[devcnt].events)
379                                 best[i] = devcnt;
380                 }
381                 devcnt++;
382         }
383
384         if (devcnt == 0) {
385                 fprintf(stderr, Name ": no devices found for %s\n",
386                         mddev);
387                 return 1;
388         }
389         /* now we have some devices that might be suitable.
390          * I wonder how many
391          */
392         okcnt = 0;
393         sparecnt=0;
394         for (i=0; i< bestcnt ;i++) {
395                 int j = best[i];
396                 int event_margin = !force;
397                 if (j < 0) continue;
398                 /* note: we ignore error flags in multipath arrays
399                  * as they don't make sense
400                  */
401                 if ((int)first_super.level != -4)
402                         if (!(devices[j].state & (1<<MD_DISK_SYNC))) {
403                                 if (!(devices[j].state & (1<<MD_DISK_FAULTY)))
404                                         sparecnt++;
405                                 continue;
406                         }
407                 if (devices[j].events+event_margin >=
408                     devices[most_recent].events) {
409                         devices[j].uptodate = 1;
410                         if (i < first_super.raid_disks)
411                                 okcnt++;
412                         else
413                                 sparecnt++;
414                 }
415         }
416         while (force && !enough(first_super.level, first_super.raid_disks, okcnt)) {
417                 /* Choose the newest best drive which is
418                  * not up-to-date, update the superblock
419                  * and add it.
420                  */
421                 int fd;
422                 chosen_drive = -1;
423                 for (i=0; i<first_super.raid_disks && i < bestcnt; i++) {
424                         int j = best[i];
425                         if (j>=0 &&
426                             !devices[j].uptodate &&
427                             devices[j].events > 0 &&
428                             (chosen_drive < 0 ||
429                              devices[j].events > devices[chosen_drive].events))
430                                 chosen_drive = j;
431                 }
432                 if (chosen_drive < 0)
433                         break;
434                 fprintf(stderr, Name ": forcing event count in %s(%d) from %d upto %d\n",
435                         devices[chosen_drive].devname, devices[chosen_drive].raid_disk,
436                         (int)(devices[chosen_drive].events),
437                         (int)(devices[most_recent].events));
438                 fd = open(devices[chosen_drive].devname, O_RDWR|O_EXCL);
439                 if (fd < 0) {
440                         fprintf(stderr, Name ": Couldn't open %s for write - not updating\n",
441                                 devices[chosen_drive].devname);
442                         devices[chosen_drive].events = 0;
443                         continue;
444                 }
445                 if (load_super(fd, &super)) {
446                         close(fd);
447                         fprintf(stderr, Name ": RAID superblock disappeared from %s - not updating.\n",
448                                 devices[chosen_drive].devname);
449                         devices[chosen_drive].events = 0;
450                         continue;
451                 }
452                 super.events_hi = (devices[most_recent].events>>32)&0xFFFFFFFF;
453                 super.events_lo = (devices[most_recent].events)&0xFFFFFFFF;
454                 if (super.level == 5 || super.level == 4) {
455                         /* need to force clean */
456                         super.state = (1<<MD_SB_CLEAN);
457                 }
458                 super.sb_csum = calc_sb_csum(&super);
459 /*DRYRUN*/      if (store_super(fd, &super)) {
460                         close(fd);
461                         fprintf(stderr, Name ": Could not re-write superblock on %s\n",
462                                 devices[chosen_drive].devname);
463                         devices[chosen_drive].events = 0;
464                         continue;
465                 }
466                 close(fd);
467                 devices[chosen_drive].events = devices[most_recent].events;
468                 devices[chosen_drive].uptodate = 1;
469                 okcnt++;
470         }
471
472         /* Now we want to look at the superblock which the kernel will base things on
473          * and compare the devices that we think are working with the devices that the
474          * superblock thinks are working.
475          * If there are differences and --force is given, then update this chosen
476          * superblock.
477          */
478         chosen_drive = -1;
479         for (i=0; chosen_drive < 0 && i<bestcnt; i++) {
480                 int j = best[i];
481                 int fd;
482                 if (j<0)
483                         continue;
484                 if (!devices[j].uptodate)
485                         continue;
486                 chosen_drive = j;
487                 if ((fd=open(devices[j].devname, O_RDONLY|O_EXCL))< 0) {
488                         fprintf(stderr, Name ": Cannot open %s: %s\n",
489                                 devices[j].devname, strerror(errno));
490                         return 1;
491                 }
492                 if (load_super(fd, &super)) {
493                         close(fd);
494                         fprintf(stderr, Name ": RAID superblock has disappeared from %s\n",
495                                 devices[j].devname);
496                         return 1;
497                 }
498                 close(fd);
499         }
500
501         for (i=0; i<bestcnt; i++) {
502                 int j = best[i];
503                 unsigned int desired_state;
504
505                 if (i < super.raid_disks)
506                         desired_state = (1<<MD_DISK_ACTIVE) | (1<<MD_DISK_SYNC);
507                 else
508                         desired_state = 0;
509
510                 if (j<0)
511                         continue;
512                 if (!devices[j].uptodate)
513                         continue;
514 #if 0
515 This doesnt work yet 
516                 if (devices[j].major != super.disks[i].major ||
517                     devices[j].minor != super.disks[i].minor) {
518                         change |= 1;
519                         super.disks[i].major = devices[j].major;
520                         super.disks[i].minor = devices[j].minor;
521                 }
522 #endif 
523                 if (devices[j].oldmajor != super.disks[i].major ||
524                     devices[j].oldminor != super.disks[i].minor) {
525                         change |= 2;
526                         super.disks[i].major = devices[j].oldmajor;
527                         super.disks[i].minor = devices[j].oldminor;
528                 }
529                 if (devices[j].uptodate &&
530                     (super.disks[i].state != desired_state)) {
531                         if (force) {
532                                 fprintf(stderr, Name ": "
533                                         "clearing FAULTY flag for device %d in %s for %s\n",
534                                         j, mddev, devices[j].devname);
535                                 super.disks[i].state = desired_state;
536                                 change |= 2;
537                         } else {
538                                 fprintf(stderr, Name ": "
539                                         "device %d in %s has wrong state in superblock, but %s seems ok\n",
540                                         i, mddev, devices[j].devname);
541                         }
542                 }
543                 if (!devices[j].uptodate &&
544                     !(super.disks[i].state & (1 << MD_DISK_FAULTY))) {
545                         fprintf(stderr, Name ": devices %d of %s is not marked FAULTY in superblock, but cannot be found\n",
546                                 i, mddev);
547                 }
548         }
549         if (force && (super.level == 4 || super.level == 5) && 
550             okcnt == super.raid_disks-1) {
551                 super.state = (1<< MD_SB_CLEAN);
552                 change |= 2;
553         }
554
555         if ((force && (change & 2))
556             || (old_linux && (change & 1))) {
557                 int fd;
558                 super.sb_csum = calc_sb_csum(&super);
559                 fd = open(devices[chosen_drive].devname, O_RDWR|O_EXCL);
560                 if (fd < 0) {
561                         fprintf(stderr, Name ": Could open %s for write - cannot Assemble array.\n",
562                                 devices[chosen_drive].devname);
563                         return 1;
564                 }
565                 if (store_super(fd, &super)) {
566                         close(fd);
567                         fprintf(stderr, Name ": Could not re-write superblock on %s\n",
568                                 devices[chosen_drive].devname);
569                         return 1;
570                 }
571                 close(fd);
572                 change = 0;
573         }
574
575         /* count number of in-sync devices according to the superblock.
576          * We must have this number to start the array without -s or -R
577          */
578         req_cnt = 0;
579         for (i=0; i<MD_SB_DISKS; i++)
580                 if ((first_super.disks[i].state & (1<<MD_DISK_SYNC)) &&
581                     (first_super.disks[i].state & (1<<MD_DISK_ACTIVE)) &&
582                     !(first_super.disks[i].state & (1<<MD_DISK_FAULTY)))
583                         req_cnt ++;
584                                                                             
585
586         /* Almost ready to actually *do* something */
587         if (!old_linux) {
588                 if (ioctl(mdfd, SET_ARRAY_INFO, NULL) != 0) {
589                         fprintf(stderr, Name ": SET_ARRAY_INFO failed for %s: %s\n",
590                                 mddev, strerror(errno));
591                         return 1;
592                 }
593                 /* First, add the raid disks, but add the chosen one last */
594                 for (i=0; i<= bestcnt; i++) {
595                         int j;
596                         if (i < bestcnt) {
597                                 j = best[i];
598                                 if (j == chosen_drive)
599                                         continue;
600                         } else
601                                 j = chosen_drive;
602
603                         if (j >= 0 /* && devices[j].uptodate */) {
604                                 mdu_disk_info_t disk;
605                                 memset(&disk, 0, sizeof(disk));
606                                 disk.major = devices[j].major;
607                                 disk.minor = devices[j].minor;
608                                 if (ioctl(mdfd, ADD_NEW_DISK, &disk)!=0) {
609                                         fprintf(stderr, Name ": failed to add %s to %s: %s\n",
610                                                 devices[j].devname,
611                                                 mddev,
612                                                 strerror(errno));
613                                         if (i < first_super.raid_disks || i == bestcnt)
614                                                 okcnt--;
615                                         else
616                                                 sparecnt--;
617                                 } else if (verbose)
618                                         fprintf(stderr, Name ": added %s to %s as %d\n",
619                                                 devices[j].devname, mddev, devices[j].raid_disk);
620                         } else if (verbose && i < first_super.raid_disks)
621                                 fprintf(stderr, Name ": no uptodate device for slot %d of %s\n",
622                                         i, mddev);
623                 }
624                 
625                 if (runstop == 1 ||
626                     (runstop == 0 && 
627                      ( enough(first_super.level, first_super.raid_disks, okcnt) &&
628                        (okcnt >= req_cnt || start_partial_ok)
629                              ))) {
630                         if (ioctl(mdfd, RUN_ARRAY, NULL)==0) {
631                                 fprintf(stderr, Name ": %s has been started with %d drive%s",
632                                         mddev, okcnt, okcnt==1?"":"s");
633                                 if (okcnt < first_super.raid_disks) 
634                                         fprintf(stderr, " (out of %d)", first_super.raid_disks);
635                                 if (sparecnt)
636                                         fprintf(stderr, " and %d spare%s", sparecnt, sparecnt==1?"":"s");
637                                 fprintf(stderr, ".\n");
638                                 return 0;
639                         }
640                         fprintf(stderr, Name ": failed to RUN_ARRAY %s: %s\n",
641                                 mddev, strerror(errno));
642                         return 1;
643                 }
644                 if (runstop == -1) {
645                         fprintf(stderr, Name ": %s assembled from %d drive%s, but not started.\n",
646                                 mddev, okcnt, okcnt==1?"":"s");
647                         return 0;
648                 }
649                 fprintf(stderr, Name ": %s assembled from %d drive%s", mddev, okcnt, okcnt==1?"":"s");
650                 if (sparecnt)
651                         fprintf(stderr, " and %d spare%s", sparecnt, sparecnt==1?"":"s");
652                 if (!enough(first_super.level, first_super.raid_disks, okcnt))
653                         fprintf(stderr, " - not enough to start the array.\n");
654                 else {
655                         if (req_cnt == first_super.raid_disks)
656                                 fprintf(stderr, " - need all %d to start it", req_cnt);
657                         else
658                                 fprintf(stderr, " - need %d of %d to start", req_cnt, first_super.raid_disks);
659                         fprintf(stderr, " (use --run to insist).\n");
660                 }
661                 return 1;
662         } else {
663                 /* The "chosen_drive" is a good choice, and if necessary, the superblock has
664                  * been updated to point to the current locations of devices.
665                  * so we can just start the array
666                  */
667                 unsigned long dev;
668                 dev = makedev(devices[chosen_drive].major,
669                             devices[chosen_drive].minor);
670                 if (ioctl(mdfd, START_ARRAY, dev)) {
671                     fprintf(stderr, Name ": Cannot start array: %s\n",
672                             strerror(errno));
673                 }
674                 
675         }
676         return 0;
677 }