~csurbhi/+junk/mdadm.fixes

« back to all changes in this revision

Viewing changes to Create.c

  • Committer: Surbhi Palande
  • Date: 2010-10-19 15:01:29 UTC
  • Revision ID: surbhi.palande@canonical.com-20101019150129-n40fnr8lnpt9f5h5
bzr repository initialized. Has mdadm auto-assembly related fixes

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * mdadm - manage Linux "md" devices aka RAID arrays.
 
3
 *
 
4
 * Copyright (C) 2001-2006 Neil Brown <neilb@suse.de>
 
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
#include        <ctype.h>
 
34
 
 
35
int Create(struct supertype *st, char *mddev, int mdfd,
 
36
           int chunk, int level, int layout, unsigned long long size, int raiddisks, int sparedisks,
 
37
           char *name, char *homehost, int *uuid,
 
38
           int subdevs, mddev_dev_t devlist,
 
39
           int runstop, int verbose, int force, int assume_clean,
 
40
           char *bitmap_file, int bitmap_chunk, int write_behind, int delay)
 
41
{
 
42
        /*
 
43
         * Create a new raid array.
 
44
         *
 
45
         * First check that necessary details are available
 
46
         * (i.e. level, raid-disks)
 
47
         *
 
48
         * Then check each disk to see what might be on it
 
49
         * and report anything interesting.
 
50
         *
 
51
         * If anything looks odd, and runstop not set,
 
52
         * abort.
 
53
         *
 
54
         * SET_ARRAY_INFO and ADD_NEW_DISK, and
 
55
         * if runstop==run, or raiddisks disks were used,
 
56
         * RUN_ARRAY
 
57
         */
 
58
        unsigned long long minsize=0, maxsize=0;
 
59
        char *mindisc = NULL;
 
60
        char *maxdisc = NULL;
 
61
        int dnum;
 
62
        mddev_dev_t dv;
 
63
        int fail=0, warn=0;
 
64
        struct stat stb;
 
65
        int first_missing = subdevs * 2;
 
66
        int second_missing = subdevs * 2;
 
67
        int missing_disks = 0;
 
68
        int insert_point = subdevs * 2; /* where to insert a missing drive */
 
69
        int pass;
 
70
        int vers;
 
71
        int rv;
 
72
        int bitmap_fd;
 
73
        unsigned long long bitmapsize;
 
74
        struct mdinfo info;
 
75
 
 
76
        int major_num = BITMAP_MAJOR_HI;
 
77
 
 
78
        memset(&info, 0, sizeof(info));
 
79
 
 
80
        vers = md_get_version(mdfd);
 
81
        if (vers < 9000) {
 
82
                fprintf(stderr, Name ": Create requires md driver version 0.90.0 or later\n");
 
83
                return 1;
 
84
        } else {
 
85
                mdu_array_info_t inf;
 
86
                memset(&inf, 0, sizeof(inf));
 
87
                ioctl(mdfd, GET_ARRAY_INFO, &inf);
 
88
                if (inf.working_disks != 0) {
 
89
                        fprintf(stderr, Name ": another array by this name"
 
90
                                " is already running.\n");
 
91
                        return 1;
 
92
                }
 
93
        }
 
94
        if (level == UnSet) {
 
95
                fprintf(stderr,
 
96
                        Name ": a RAID level is needed to create an array.\n");
 
97
                return 1;
 
98
        }
 
99
        if (raiddisks < 4 && level == 6) {
 
100
                fprintf(stderr,
 
101
                        Name ": at least 4 raid-devices needed for level 6\n");
 
102
                return 1;
 
103
        }
 
104
        if (raiddisks > 256 && level == 6) {
 
105
                fprintf(stderr,
 
106
                        Name ": no more than 256 raid-devices supported for level 6\n");
 
107
                return 1;
 
108
        }
 
109
        if (raiddisks < 2 && level >= 4) {
 
110
                fprintf(stderr,
 
111
                        Name ": at least 2 raid-devices needed for level 4 or 5\n");
 
112
                return 1;
 
113
        }
 
114
        if (level <= 0 && sparedisks) {
 
115
                fprintf(stderr,
 
116
                        Name ": This level does not support spare devices\n");
 
117
                return 1;
 
118
        }
 
119
        if (subdevs > raiddisks+sparedisks) {
 
120
                fprintf(stderr, Name ": You have listed more devices (%d) than are in the array(%d)!\n", subdevs, raiddisks+sparedisks);
 
121
                return 1;
 
122
        }
 
123
        if (subdevs < raiddisks+sparedisks) {
 
124
                fprintf(stderr, Name ": You haven't given enough devices (real or missing) to create this array\n");
 
125
                return 1;
 
126
        }
 
127
        if (bitmap_file && level <= 0) {
 
128
                fprintf(stderr, Name ": bitmaps not meaningful with level %s\n",
 
129
                        map_num(pers, level)?:"given");
 
130
                return 1;
 
131
        }
 
132
 
 
133
        /* now set some defaults */
 
134
        if (layout == UnSet)
 
135
                switch(level) {
 
136
                default: /* no layout */
 
137
                        layout = 0;
 
138
                        break;
 
139
                case 10:
 
140
                        layout = 0x102; /* near=2, far=1 */
 
141
                        if (verbose > 0)
 
142
                                fprintf(stderr,
 
143
                                        Name ": layout defaults to n1\n");
 
144
                        break;
 
145
                case 5:
 
146
                case 6:
 
147
                        layout = map_name(r5layout, "default");
 
148
                        if (verbose > 0)
 
149
                                fprintf(stderr,
 
150
                                        Name ": layout defaults to %s\n", map_num(r5layout, layout));
 
151
                        break;
 
152
                case LEVEL_FAULTY:
 
153
                        layout = map_name(faultylayout, "default");
 
154
 
 
155
                        if (verbose > 0)
 
156
                                fprintf(stderr,
 
157
                                        Name ": layout defaults to %s\n", map_num(faultylayout, layout));
 
158
                        break;
 
159
                }
 
160
 
 
161
        if (level == 10)
 
162
                /* check layout fits in array*/
 
163
                if ((layout&255) * ((layout>>8)&255) > raiddisks) {
 
164
                        fprintf(stderr, Name ": that layout requires at least %d devices\n",
 
165
                                (layout&255) * ((layout>>8)&255));
 
166
                        return 1;
 
167
                }
 
168
 
 
169
        switch(level) {
 
170
        case 4:
 
171
        case 5:
 
172
        case 10:
 
173
        case 6:
 
174
        case 0:
 
175
        case LEVEL_LINEAR: /* linear */
 
176
                if (chunk == 0) {
 
177
                        chunk = 64;
 
178
                        if (verbose > 0)
 
179
                                fprintf(stderr, Name ": chunk size defaults to 64K\n");
 
180
                }
 
181
                break;
 
182
        case 1:
 
183
        case LEVEL_FAULTY:
 
184
        case LEVEL_MULTIPATH:
 
185
                if (chunk) {
 
186
                        chunk = 0;
 
187
                        if (verbose > 0)
 
188
                                fprintf(stderr, Name ": chunk size ignored for this level\n");
 
189
                }
 
190
                break;
 
191
        default:
 
192
                fprintf(stderr, Name ": unknown level %d\n", level);
 
193
                return 1;
 
194
        }
 
195
 
 
196
        /* now look at the subdevs */
 
197
        info.array.active_disks = 0;
 
198
        info.array.working_disks = 0;
 
199
        dnum = 0;
 
200
        for (dv=devlist; dv; dv=dv->next, dnum++) {
 
201
                char *dname = dv->devname;
 
202
                unsigned long long ldsize, freesize;
 
203
                int fd;
 
204
                if (strcasecmp(dname, "missing")==0) {
 
205
                        if (first_missing > dnum)
 
206
                                first_missing = dnum;
 
207
                        if (second_missing > dnum && dnum > first_missing)
 
208
                                second_missing = dnum;
 
209
                        missing_disks ++;
 
210
                        continue;
 
211
                }
 
212
                info.array.working_disks++;
 
213
                if (dnum < raiddisks)
 
214
                        info.array.active_disks++;
 
215
                fd = open(dname, O_RDONLY|O_EXCL, 0);
 
216
                if (fd <0 ) {
 
217
                        fprintf(stderr, Name ": Cannot open %s: %s\n",
 
218
                                dname, strerror(errno));
 
219
                        fail=1;
 
220
                        continue;
 
221
                }
 
222
                if (!get_dev_size(fd, dname, &ldsize)) {
 
223
                        fail = 1;
 
224
                        close(fd);
 
225
                        continue;
 
226
                }
 
227
                if (st == NULL) {
 
228
                        struct createinfo *ci = conf_get_create_info();
 
229
                        if (ci)
 
230
                                st = ci->supertype;
 
231
                }
 
232
                if (st == NULL) {
 
233
                        /* Need to choose a default metadata, which is different
 
234
                         * depending on the sizes of devices
 
235
                         */
 
236
                        int i;
 
237
                        char *name = "default";
 
238
                        if (level >= 1 && ldsize > (0x7fffffffULL<<10))
 
239
                                name = "default/large";
 
240
                        for(i=0; !st && superlist[i]; i++)
 
241
                                st = superlist[i]->match_metadata_desc(name);
 
242
 
 
243
                        if (!st) {
 
244
                                fprintf(stderr, Name ": internal error - no default metadata style\n");
 
245
                                exit(2);
 
246
                        }
 
247
                        if (st->ss->major != 0 ||
 
248
                            st->minor_version != 90)
 
249
                                fprintf(stderr, Name ": Defaulting to version"
 
250
                                        " %d.%d metadata\n",
 
251
                                        st->ss->major,
 
252
                                        st->minor_version);
 
253
                }
 
254
                freesize = st->ss->avail_size(st, ldsize >> 9);
 
255
                if (freesize == 0) {
 
256
                        fprintf(stderr, Name ": %s is too small: %luK\n",
 
257
                                dname, (unsigned long)(ldsize>>10));
 
258
                        fail = 1;
 
259
                        close(fd);
 
260
                        continue;
 
261
                }
 
262
 
 
263
                freesize /= 2; /* convert to K */
 
264
                if (chunk) {
 
265
                        /* round to chunk size */
 
266
                        freesize = freesize & ~(chunk-1);
 
267
                }
 
268
 
 
269
                if (size && freesize < size) {
 
270
                        fprintf(stderr, Name ": %s is smaller that given size."
 
271
                                " %lluK < %lluK + superblock\n", dname, freesize, size);
 
272
                        fail = 1;
 
273
                        close(fd);
 
274
                        continue;
 
275
                }
 
276
                if (maxdisc == NULL || (maxdisc && freesize > maxsize)) {
 
277
                        maxdisc = dname;
 
278
                        maxsize = freesize;
 
279
                }
 
280
                if (mindisc ==NULL || (mindisc && freesize < minsize)) {
 
281
                        mindisc = dname;
 
282
                        minsize = freesize;
 
283
                }
 
284
                if (runstop != 1 || verbose >= 0) {
 
285
                        warn |= check_ext2(fd, dname);
 
286
                        warn |= check_reiser(fd, dname);
 
287
                        warn |= check_raid(fd, dname);
 
288
                }
 
289
                close(fd);
 
290
        }
 
291
        if (fail) {
 
292
                fprintf(stderr, Name ": create aborted\n");
 
293
                return 1;
 
294
        }
 
295
        if (size == 0) {
 
296
                if (mindisc == NULL) {
 
297
                        fprintf(stderr, Name ": no size and no drives given - aborting create.\n");
 
298
                        return 1;
 
299
                }
 
300
                if (level > 0 || level == LEVEL_MULTIPATH || level == LEVEL_FAULTY) {
 
301
                        /* size is meaningful */
 
302
                        if (minsize > 0x100000000ULL && st->ss->major == 0) {
 
303
                                fprintf(stderr, Name ": devices too large for RAID level %d\n", level);
 
304
                                return 1;
 
305
                        }
 
306
                        size = minsize;
 
307
                        if (verbose > 0)
 
308
                                fprintf(stderr, Name ": size set to %lluK\n", size);
 
309
                }
 
310
        }
 
311
        if (level > 0 && ((maxsize-size)*100 > maxsize)) {
 
312
                if (runstop != 1 || verbose >= 0)
 
313
                        fprintf(stderr, Name ": largest drive (%s) exceed size (%lluK) by more than 1%%\n",
 
314
                                maxdisc, size);
 
315
                warn = 1;
 
316
        }
 
317
 
 
318
        if (warn) {
 
319
                if (runstop!= 1) {
 
320
                        if (!ask("Continue creating array? ")) {
 
321
                                fprintf(stderr, Name ": create aborted.\n");
 
322
                                return 1;
 
323
                        }
 
324
                } else {
 
325
                        if (verbose > 0)
 
326
                                fprintf(stderr, Name ": creation continuing despite oddities due to --run\n");
 
327
                }
 
328
        }
 
329
 
 
330
        /* If this is raid4/5, we want to configure the last active slot
 
331
         * as missing, so that a reconstruct happens (faster than re-parity)
 
332
         * FIX: Can we do this for raid6 as well?
 
333
         */
 
334
        if (assume_clean==0 && force == 0 && first_missing >= raiddisks) {
 
335
                switch ( level ) {
 
336
                case 4:
 
337
                case 5:
 
338
                        insert_point = raiddisks-1;
 
339
                        sparedisks++;
 
340
                        info.array.active_disks--;
 
341
                        missing_disks++;
 
342
                        break;
 
343
                default:
 
344
                        break;
 
345
                }
 
346
        }
 
347
        /* For raid6, if creating with 1 missing drive, make a good drive
 
348
         * into a spare, else the create will fail
 
349
         */
 
350
        if (assume_clean == 0 && force == 0 && first_missing < raiddisks &&
 
351
            second_missing >= raiddisks && level == 6) {
 
352
                insert_point = raiddisks - 1;
 
353
                if (insert_point == first_missing)
 
354
                        insert_point--;
 
355
                sparedisks ++;
 
356
                info.array.active_disks--;
 
357
                missing_disks++;
 
358
        }
 
359
 
 
360
        if (level <= 0 && first_missing != subdevs * 2) {
 
361
                fprintf(stderr,
 
362
                        Name ": This level does not support missing devices\n");
 
363
                return 1;
 
364
        }
 
365
 
 
366
        /* Ok, lets try some ioctls */
 
367
 
 
368
        info.array.level = level;
 
369
        info.array.size = size;
 
370
        info.array.raid_disks = raiddisks;
 
371
        /* The kernel should *know* what md_minor we are dealing
 
372
         * with, but it chooses to trust me instead. Sigh
 
373
         */
 
374
        info.array.md_minor = 0;
 
375
        if (fstat(mdfd, &stb)==0)
 
376
                info.array.md_minor = minor(stb.st_rdev);
 
377
        info.array.not_persistent = 0;
 
378
 
 
379
        if ( ( (level == 4 || level == 5) &&
 
380
               (insert_point < raiddisks || first_missing < raiddisks) )
 
381
             ||
 
382
             ( level == 6 && (insert_point < raiddisks
 
383
                              || second_missing < raiddisks))
 
384
             ||
 
385
             assume_clean
 
386
                )
 
387
                info.array.state = 1; /* clean, but one+ drive will be missing*/
 
388
        else
 
389
                info.array.state = 0; /* not clean, but no errors */
 
390
 
 
391
        if (level == 10) {
 
392
                /* for raid10, the bitmap size is the capacity of the array,
 
393
                 * which is array.size * raid_disks / ncopies;
 
394
                 * .. but convert to sectors.
 
395
                 */
 
396
                int ncopies = ((layout>>8) & 255) * (layout & 255);
 
397
                bitmapsize = (unsigned long long)size * raiddisks / ncopies * 2;
 
398
/*              printf("bms=%llu as=%d rd=%d nc=%d\n", bitmapsize, size, raiddisks, ncopies);*/
 
399
        } else
 
400
                bitmapsize = (unsigned long long)size * 2;
 
401
 
 
402
        /* There is lots of redundancy in these disk counts,
 
403
         * raid_disks is the most meaningful value
 
404
         *          it describes the geometry of the array
 
405
         *          it is constant
 
406
         * nr_disks is total number of used slots.
 
407
         *          it should be raid_disks+spare_disks
 
408
         * spare_disks is the number of extra disks present
 
409
         *          see above
 
410
         * active_disks is the number of working disks in
 
411
         *          active slots. (With raid_disks)
 
412
         * working_disks is the total number of working disks,
 
413
         *          including spares
 
414
         * failed_disks is the number of disks marked failed
 
415
         *
 
416
         * Ideally, the kernel would keep these (except raid_disks)
 
417
         * up-to-date as we ADD_NEW_DISK, but it doesn't (yet).
 
418
         * So for now, we assume that all raid and spare
 
419
         * devices will be given.
 
420
         */
 
421
        info.array.spare_disks=sparedisks;
 
422
        info.array.failed_disks=missing_disks;
 
423
        info.array.nr_disks = info.array.working_disks
 
424
                + info.array.failed_disks;
 
425
        info.array.layout = layout;
 
426
        info.array.chunk_size = chunk*1024;
 
427
        info.array.major_version = st->ss->major;
 
428
 
 
429
        if (name == NULL || *name == 0) {
 
430
                /* base name on mddev */
 
431
                /*  /dev/md0 -> 0
 
432
                 *  /dev/md_d0 -> d0
 
433
                 *  /dev/md/1 -> 1
 
434
                 *  /dev/md/d1 -> d1
 
435
                 *  /dev/md/home -> home
 
436
                 *  /dev/mdhome -> home
 
437
                 */
 
438
                name = strrchr(mddev, '/');
 
439
                if (name) {
 
440
                        name++;
 
441
                        if (strncmp(name, "md_d", 4)==0 &&
 
442
                            strlen(name) > 4 &&
 
443
                            isdigit(name[4]) &&
 
444
                            (name-mddev) == 5 /* /dev/ */)
 
445
                                name += 3;
 
446
                        else if (strncmp(name, "md", 2)==0 &&
 
447
                                 strlen(name) > 2 &&
 
448
                                 isdigit(name[2]) &&
 
449
                                 (name-mddev) == 5 /* /dev/ */)
 
450
                                name += 2;
 
451
                }
 
452
        }
 
453
        if (!st->ss->init_super(st, &info.array, size, name, homehost, uuid))
 
454
                return 1;
 
455
 
 
456
        if (bitmap_file && vers < 9003) {
 
457
                major_num = BITMAP_MAJOR_HOSTENDIAN;
 
458
#ifdef __BIG_ENDIAN
 
459
                fprintf(stderr, Name ": Warning - bitmaps created on this kernel are not portable\n"
 
460
                        "  between different architectured.  Consider upgrading the Linux kernel.\n");
 
461
#endif
 
462
        }
 
463
 
 
464
        if (bitmap_file && strcmp(bitmap_file, "internal")==0) {
 
465
                if ((vers%100) < 2) {
 
466
                        fprintf(stderr, Name ": internal bitmaps not supported by this kernel.\n");
 
467
                        return 1;
 
468
                }
 
469
                if (!st->ss->add_internal_bitmap(st, &bitmap_chunk,
 
470
                                                 delay, write_behind,
 
471
                                                 bitmapsize, 1, major_num)) {
 
472
                        fprintf(stderr, Name ": Given bitmap chunk size not supported.\n");
 
473
                        return 1;
 
474
                }
 
475
                bitmap_file = NULL;
 
476
        }
 
477
 
 
478
 
 
479
 
 
480
        if ((vers % 100) >= 1) { /* can use different versions */
 
481
                mdu_array_info_t inf;
 
482
                memset(&inf, 0, sizeof(inf));
 
483
                inf.major_version = st->ss->major;
 
484
                inf.minor_version = st->minor_version;
 
485
                rv = ioctl(mdfd, SET_ARRAY_INFO, &inf);
 
486
        } else
 
487
                rv = ioctl(mdfd, SET_ARRAY_INFO, NULL);
 
488
        if (rv) {
 
489
                fprintf(stderr, Name ": SET_ARRAY_INFO failed for %s: %s\n",
 
490
                        mddev, strerror(errno));
 
491
                return 1;
 
492
        }
 
493
 
 
494
        if (bitmap_file) {
 
495
                int uuid[4];
 
496
 
 
497
                st->ss->uuid_from_super(st, uuid);
 
498
                if (CreateBitmap(bitmap_file, force, (char*)uuid, bitmap_chunk,
 
499
                                 delay, write_behind,
 
500
                                 bitmapsize,
 
501
                                 major_num)) {
 
502
                        return 1;
 
503
                }
 
504
                bitmap_fd = open(bitmap_file, O_RDWR);
 
505
                if (bitmap_fd < 0) {
 
506
                        fprintf(stderr, Name ": weird: %s cannot be openned\n",
 
507
                                bitmap_file);
 
508
                        return 1;
 
509
                }
 
510
                if (ioctl(mdfd, SET_BITMAP_FILE, bitmap_fd) < 0) {
 
511
                        fprintf(stderr, Name ": Cannot set bitmap file for %s: %s\n",
 
512
                                mddev, strerror(errno));
 
513
                        return 1;
 
514
                }
 
515
        }
 
516
 
 
517
 
 
518
 
 
519
        for (pass=1; pass <=2 ; pass++) {
 
520
                mddev_dev_t moved_disk = NULL; /* the disk that was moved out of the insert point */
 
521
 
 
522
                for (dnum=0, dv = devlist ; dv ;
 
523
                     dv=(dv->next)?(dv->next):moved_disk, dnum++) {
 
524
                        int fd;
 
525
                        struct stat stb;
 
526
 
 
527
                        info.disk.number = dnum;
 
528
                        if (dnum == insert_point) {
 
529
                                moved_disk = dv;
 
530
                        }
 
531
                        info.disk.raid_disk = info.disk.number;
 
532
                        if (info.disk.raid_disk < raiddisks)
 
533
                                info.disk.state = (1<<MD_DISK_ACTIVE) |
 
534
                                                (1<<MD_DISK_SYNC);
 
535
                        else
 
536
                                info.disk.state = 0;
 
537
                        if (dv->writemostly)
 
538
                                info.disk.state |= (1<<MD_DISK_WRITEMOSTLY);
 
539
 
 
540
                        if (dnum == insert_point ||
 
541
                            strcasecmp(dv->devname, "missing")==0) {
 
542
                                info.disk.major = 0;
 
543
                                info.disk.minor = 0;
 
544
                                info.disk.state = (1<<MD_DISK_FAULTY);
 
545
                        } else {
 
546
                                fd = open(dv->devname, O_RDONLY|O_EXCL, 0);
 
547
                                if (fd < 0) {
 
548
                                        fprintf(stderr, Name ": failed to open %s after earlier success - aborting\n",
 
549
                                                dv->devname);
 
550
                                        return 1;
 
551
                                }
 
552
                                fstat(fd, &stb);
 
553
                                info.disk.major = major(stb.st_rdev);
 
554
                                info.disk.minor = minor(stb.st_rdev);
 
555
                                remove_partitions(fd);
 
556
                                close(fd);
 
557
                        }
 
558
                        switch(pass){
 
559
                        case 1:
 
560
                                st->ss->add_to_super(st, &info.disk);
 
561
                                break;
 
562
                        case 2:
 
563
                                if (info.disk.state == 1) break;
 
564
                                Kill(dv->devname, 0, 1); /* Just be sure it is clean */
 
565
                                Kill(dv->devname, 0, 1); /* and again, there could be two superblocks */
 
566
                                st->ss->write_init_super(st, &info.disk,
 
567
                                                         dv->devname);
 
568
 
 
569
                                if (ioctl(mdfd, ADD_NEW_DISK, &info.disk)) {
 
570
                                        fprintf(stderr, Name ": ADD_NEW_DISK for %s failed: %s\n",
 
571
                                                dv->devname, strerror(errno));
 
572
                                        st->ss->free_super(st);
 
573
                                        return 1;
 
574
                                }
 
575
 
 
576
                                break;
 
577
                        }
 
578
                        if (dv == moved_disk && dnum != insert_point) break;
 
579
                }
 
580
        }
 
581
        st->ss->free_super(st);
 
582
 
 
583
        /* param is not actually used */
 
584
        if (runstop == 1 || subdevs >= raiddisks) {
 
585
                mdu_param_t param;
 
586
                if (ioctl(mdfd, RUN_ARRAY, &param)) {
 
587
                        fprintf(stderr, Name ": RUN_ARRAY failed: %s\n",
 
588
                                strerror(errno));
 
589
                        Manage_runstop(mddev, mdfd, -1, 0);
 
590
                        return 1;
 
591
                }
 
592
                if (verbose >= 0)
 
593
                        fprintf(stderr, Name ": array %s started.\n", mddev);
 
594
        } else {
 
595
                fprintf(stderr, Name ": not starting array - not enough devices.\n");
 
596
        }
 
597
        return 0;
 
598
}