]> git.ipfire.org Git - thirdparty/mdadm.git/blob - Incremental.c
Provide a mdstat_ent to subarray helper
[thirdparty/mdadm.git] / Incremental.c
1 /*
2 * Incremental.c - support --incremental. Part of:
3 * mdadm - manage Linux "md" devices aka RAID arrays.
4 *
5 * Copyright (C) 2006-2009 Neil Brown <neilb@suse.de>
6 *
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 * Author: Neil Brown
23 * Email: <neilb@suse.de>
24 * Paper: Neil Brown
25 * Novell Inc
26 * GPO Box Q1283
27 * QVB Post Office, NSW 1230
28 * Australia
29 */
30
31 #include "mdadm.h"
32 #include <dirent.h>
33 #include <ctype.h>
34
35 static int count_active(struct supertype *st, int mdfd, char **availp,
36 struct mdinfo *info);
37 static void find_reject(int mdfd, struct supertype *st, struct mdinfo *sra,
38 int number, __u64 events, int verbose,
39 char *array_name);
40 static int try_spare(char *devname, int *dfdp, struct dev_policy *pol,
41 struct map_ent *target,
42 struct supertype *st, int verbose);
43
44 static int Incremental_container(struct supertype *st, char *devname,
45 char *homehost,
46 int verbose, int runstop, int autof);
47
48 static struct mddev_ident *search_mdstat(struct supertype *st,
49 struct mdinfo *info,
50 char *devname,
51 int verbose, int *rvp);
52
53 int Incremental(char *devname, int verbose, int runstop,
54 struct supertype *st, char *homehost, int require_homehost,
55 int autof)
56 {
57 /* Add this device to an array, creating the array if necessary
58 * and starting the array if sensible or - if runstop>0 - if possible.
59 *
60 * This has several steps:
61 *
62 * 1/ Check if device is permitted by mdadm.conf, reject if not.
63 * 2/ Find metadata, reject if none appropriate (check
64 * version/name from args)
65 * 3/ Check if there is a match in mdadm.conf
66 * 3a/ if not, check for homehost match. If no match, assemble as
67 * a 'foreign' array.
68 * 4/ Determine device number.
69 * - If in mdadm.conf with std name, use that
70 * - UUID in /var/run/mdadm.map use that
71 * - If name is suggestive, use that. unless in use with different uuid.
72 * - Choose a free, high number.
73 * - Use a partitioned device unless strong suggestion not to.
74 * e.g. auto=md
75 * Don't choose partitioned for containers.
76 * 5/ Find out if array already exists
77 * 5a/ if it does not
78 * - choose a name, from mdadm.conf or 'name' field in array.
79 * - create the array
80 * - add the device
81 * 5b/ if it does
82 * - check one drive in array to make sure metadata is a reasonably
83 * close match. Reject if not (e.g. different type)
84 * - add the device
85 * 6/ Make sure /var/run/mdadm.map contains this array.
86 * 7/ Is there enough devices to possibly start the array?
87 * For a container, this means running Incremental_container.
88 * 7a/ if not, finish with success.
89 * 7b/ if yes,
90 * - read all metadata and arrange devices like -A does
91 * - if number of OK devices match expected, or -R and there are enough,
92 * start the array (auto-readonly).
93 */
94 struct stat stb;
95 struct mdinfo info, dinfo;
96 struct mddev_ident *match;
97 char chosen_name[1024];
98 int rv = 1;
99 struct map_ent *mp, *map = NULL;
100 int dfd = -1, mdfd = -1;
101 char *avail;
102 int active_disks;
103 int trustworthy;
104 char *name_to_use;
105 mdu_array_info_t ainf;
106 struct dev_policy *policy = NULL;
107 struct map_ent target_array;
108 int have_target;
109
110 struct createinfo *ci = conf_get_create_info();
111
112 if (stat(devname, &stb) < 0) {
113 if (verbose >= 0)
114 fprintf(stderr, Name ": stat failed for %s: %s.\n",
115 devname, strerror(errno));
116 return rv;
117 }
118 if ((stb.st_mode & S_IFMT) != S_IFBLK) {
119 if (verbose >= 0)
120 fprintf(stderr, Name ": %s is not a block device.\n",
121 devname);
122 return rv;
123 }
124 dfd = dev_open(devname, O_RDONLY|O_EXCL);
125 if (dfd < 0) {
126 if (verbose >= 0)
127 fprintf(stderr, Name ": cannot open %s: %s.\n",
128 devname, strerror(errno));
129 return rv;
130 }
131 /* If the device is a container, we do something very different */
132 if (must_be_container(dfd)) {
133 if (!st)
134 st = super_by_fd(dfd, NULL);
135 if (st)
136 rv = st->ss->load_container(st, dfd, NULL);
137
138 close(dfd);
139 if (!rv && st->ss->container_content)
140 return Incremental_container(st, devname, homehost,
141 verbose, runstop, autof);
142
143 fprintf(stderr, Name ": %s is not part of an md array.\n",
144 devname);
145 return rv;
146 }
147
148 /* 1/ Check if device is permitted by mdadm.conf */
149
150 if (!conf_test_dev(devname)) {
151 if (verbose >= 0)
152 fprintf(stderr, Name
153 ": %s not permitted by mdadm.conf.\n",
154 devname);
155 goto out;
156 }
157
158 /* 2/ Find metadata, reject if none appropriate (check
159 * version/name from args) */
160
161 if (fstat(dfd, &stb) < 0) {
162 if (verbose >= 0)
163 fprintf(stderr, Name ": fstat failed for %s: %s.\n",
164 devname, strerror(errno));
165 goto out;
166 }
167 if ((stb.st_mode & S_IFMT) != S_IFBLK) {
168 if (verbose >= 0)
169 fprintf(stderr, Name ": %s is not a block device.\n",
170 devname);
171 goto out;
172 }
173
174 dinfo.disk.major = major(stb.st_rdev);
175 dinfo.disk.minor = minor(stb.st_rdev);
176
177 policy = disk_policy(&dinfo);
178 have_target = policy_check_path(&dinfo, &target_array);
179
180 if (st == NULL && (st = guess_super(dfd)) == NULL) {
181 if (verbose >= 0)
182 fprintf(stderr, Name
183 ": no recognisable superblock on %s.\n",
184 devname);
185 rv = try_spare(devname, &dfd, policy,
186 have_target ? &target_array : NULL,
187 st, verbose);
188 goto out;
189 }
190 if (st->ss->compare_super == NULL ||
191 st->ss->load_super(st, dfd, NULL)) {
192 if (verbose >= 0)
193 fprintf(stderr, Name ": no RAID superblock on %s.\n",
194 devname);
195 rv = try_spare(devname, &dfd, policy,
196 have_target ? &target_array : NULL,
197 st, verbose);
198 free(st);
199 goto out;
200 }
201 close (dfd); dfd = -1;
202
203 memset(&info, 0, sizeof(info));
204 st->ss->getinfo_super(st, &info, NULL);
205
206 /* 3/ Check if there is a match in mdadm.conf */
207 match = search_mdstat(st, &info, devname, verbose, &rv);
208 if (!match && rv == 2)
209 goto out;
210
211 if (match && match->devname
212 && strcasecmp(match->devname, "<ignore>") == 0) {
213 if (verbose >= 0)
214 fprintf(stderr, Name ": array containing %s is explicitly"
215 " ignored by mdadm.conf\n",
216 devname);
217 goto out;
218 }
219
220 /* 3a/ if not, check for homehost match. If no match, continue
221 * but don't trust the 'name' in the array. Thus a 'random' minor
222 * number will be assigned, and the device name will be based
223 * on that. */
224 if (match)
225 trustworthy = LOCAL;
226 else if (st->ss->match_home(st, homehost) == 1)
227 trustworthy = LOCAL;
228 else if (st->ss->match_home(st, "any") == 1)
229 trustworthy = LOCAL_ANY;
230 else
231 trustworthy = FOREIGN;
232
233
234 if (!match && !conf_test_metadata(st->ss->name, policy,
235 (trustworthy == LOCAL))) {
236 if (verbose >= 1)
237 fprintf(stderr, Name
238 ": %s has metadata type %s for which "
239 "auto-assembly is disabled\n",
240 devname, st->ss->name);
241 goto out;
242 }
243 if (trustworthy == LOCAL_ANY)
244 trustworthy = LOCAL;
245
246 /* There are three possible sources for 'autof': command line,
247 * ARRAY line in mdadm.conf, or CREATE line in mdadm.conf.
248 * ARRAY takes precedence, then command line, then
249 * CREATE.
250 */
251 if (match && match->autof)
252 autof = match->autof;
253 if (autof == 0)
254 autof = ci->autof;
255
256 name_to_use = info.name;
257 if (name_to_use[0] == 0 &&
258 info.array.level == LEVEL_CONTAINER &&
259 trustworthy == LOCAL) {
260 name_to_use = info.text_version;
261 trustworthy = METADATA;
262 }
263 if (name_to_use[0] && trustworthy != LOCAL &&
264 ! require_homehost &&
265 conf_name_is_free(name_to_use))
266 trustworthy = LOCAL;
267
268 /* strip "hostname:" prefix from name if we have decided
269 * to treat it as LOCAL
270 */
271 if (trustworthy == LOCAL && strchr(name_to_use, ':') != NULL)
272 name_to_use = strchr(name_to_use, ':')+1;
273
274 /* 4/ Check if array exists.
275 */
276 if (map_lock(&map))
277 fprintf(stderr, Name ": failed to get exclusive lock on "
278 "mapfile\n");
279 mp = map_by_uuid(&map, info.uuid);
280 if (mp)
281 mdfd = open_dev(mp->devnum);
282 else
283 mdfd = -1;
284
285 if (mdfd < 0) {
286 struct mdinfo *sra;
287
288 /* Couldn't find an existing array, maybe make a new one */
289 mdfd = create_mddev(match ? match->devname : NULL,
290 name_to_use, autof, trustworthy, chosen_name);
291
292 if (mdfd < 0)
293 goto out;
294
295 sysfs_init(&info, mdfd, 0);
296
297 if (set_array_info(mdfd, st, &info) != 0) {
298 fprintf(stderr, Name ": failed to set array info for %s: %s\n",
299 chosen_name, strerror(errno));
300 rv = 2;
301 goto out;
302 }
303
304 dinfo = info;
305 dinfo.disk.major = major(stb.st_rdev);
306 dinfo.disk.minor = minor(stb.st_rdev);
307 if (add_disk(mdfd, st, &info, &dinfo) != 0) {
308 fprintf(stderr, Name ": failed to add %s to %s: %s.\n",
309 devname, chosen_name, strerror(errno));
310 ioctl(mdfd, STOP_ARRAY, 0);
311 rv = 2;
312 goto out;
313 }
314 sra = sysfs_read(mdfd, fd2devnum(mdfd), GET_DEVS);
315 if (!sra || !sra->devs || sra->devs->disk.raid_disk >= 0) {
316 /* It really should be 'none' - must be old buggy
317 * kernel, and mdadm -I may not be able to complete.
318 * So reject it.
319 */
320 ioctl(mdfd, STOP_ARRAY, NULL);
321 fprintf(stderr, Name
322 ": You have an old buggy kernel which cannot support\n"
323 " --incremental reliably. Aborting.\n");
324 sysfs_free(sra);
325 rv = 2;
326 goto out;
327 }
328 info.array.working_disks = 1;
329 sysfs_free(sra);
330 /* 6/ Make sure /var/run/mdadm.map contains this array. */
331 map_update(&map, fd2devnum(mdfd),
332 info.text_version,
333 info.uuid, chosen_name);
334 } else {
335 /* 5b/ if it does */
336 /* - check one drive in array to make sure metadata is a reasonably */
337 /* close match. Reject if not (e.g. different type) */
338 /* - add the device */
339 char dn[20];
340 int dfd2;
341 int err;
342 struct mdinfo *sra;
343 struct supertype *st2;
344 struct mdinfo info2, *d;
345
346 if (mp->path)
347 strcpy(chosen_name, mp->path);
348 else
349 strcpy(chosen_name, devnum2devname(mp->devnum));
350
351 /* It is generally not OK to add non-spare drives to a
352 * running array as they are probably missing because
353 * they failed. However if runstop is 1, then the
354 * array was possibly started early and our best bet is
355 * to add this anyway.
356 * Also if action policy is re-add or better we allow
357 * re-add
358 */
359 if ((info.disk.state & (1<<MD_DISK_SYNC)) != 0
360 && ! policy_action_allows(policy, st->ss->name,
361 act_re_add)
362 && runstop < 1) {
363 int active = 0;
364
365 if (st->ss->external) {
366 char *devname = devnum2devname(fd2devnum(mdfd));
367
368 active = devname && is_container_active(devname);
369 free(devname);
370 } else if (ioctl(mdfd, GET_ARRAY_INFO, &ainf) == 0)
371 active = 1;
372 if (active) {
373 fprintf(stderr, Name
374 ": not adding %s to active array (without --run) %s\n",
375 devname, chosen_name);
376 rv = 2;
377 goto out;
378 }
379 }
380 sra = sysfs_read(mdfd, fd2devnum(mdfd), (GET_DEVS | GET_STATE));
381 if (!sra) {
382 rv = 2;
383 goto out;
384 }
385 if (sra->devs) {
386 sprintf(dn, "%d:%d", sra->devs->disk.major,
387 sra->devs->disk.minor);
388 dfd2 = dev_open(dn, O_RDONLY);
389 st2 = dup_super(st);
390 if (st2->ss->load_super(st2, dfd2, NULL) ||
391 st->ss->compare_super(st, st2) != 0) {
392 fprintf(stderr, Name
393 ": metadata mismatch between %s and "
394 "chosen array %s\n",
395 devname, chosen_name);
396 close(dfd2);
397 rv = 2;
398 goto out;
399 }
400 close(dfd2);
401 memset(&info2, 0, sizeof(info2));
402 st2->ss->getinfo_super(st2, &info2, NULL);
403 st2->ss->free_super(st2);
404 if (info.array.level != info2.array.level ||
405 memcmp(info.uuid, info2.uuid, 16) != 0 ||
406 info.array.raid_disks != info2.array.raid_disks) {
407 fprintf(stderr, Name
408 ": unexpected difference between %s and %s.\n",
409 chosen_name, devname);
410 rv = 2;
411 goto out;
412 }
413 }
414 info2.disk.major = major(stb.st_rdev);
415 info2.disk.minor = minor(stb.st_rdev);
416 /* add disk needs to know about containers */
417 if (st->ss->external)
418 sra->array.level = LEVEL_CONTAINER;
419 err = add_disk(mdfd, st, sra, &info2);
420 if (err < 0 && errno == EBUSY) {
421 /* could be another device present with the same
422 * disk.number. Find and reject any such
423 */
424 find_reject(mdfd, st, sra, info.disk.number,
425 info.events, verbose, chosen_name);
426 err = add_disk(mdfd, st, sra, &info2);
427 }
428 if (err < 0) {
429 fprintf(stderr, Name ": failed to add %s to %s: %s.\n",
430 devname, chosen_name, strerror(errno));
431 rv = 2;
432 goto out;
433 }
434 info.array.working_disks = 0;
435 for (d = sra->devs; d; d=d->next)
436 info.array.working_disks ++;
437
438 }
439
440 /* 7/ Is there enough devices to possibly start the array? */
441 /* 7a/ if not, finish with success. */
442 if (info.array.level == LEVEL_CONTAINER) {
443 /* Try to assemble within the container */
444 map_unlock(&map);
445 sysfs_uevent(&info, "change");
446 if (verbose >= 0)
447 fprintf(stderr, Name
448 ": container %s now has %d devices\n",
449 chosen_name, info.array.working_disks);
450 wait_for(chosen_name, mdfd);
451 close(mdfd);
452 rv = Incremental(chosen_name, verbose, runstop,
453 NULL, homehost, require_homehost, autof);
454 if (rv == 1)
455 /* Don't fail the whole -I if a subarray didn't
456 * have enough devices to start yet
457 */
458 rv = 0;
459 return rv;
460 }
461 avail = NULL;
462 active_disks = count_active(st, mdfd, &avail, &info);
463 if (enough(info.array.level, info.array.raid_disks,
464 info.array.layout, info.array.state & 1,
465 avail, active_disks) == 0) {
466 free(avail);
467 if (verbose >= 0)
468 fprintf(stderr, Name
469 ": %s attached to %s, not enough to start (%d).\n",
470 devname, chosen_name, active_disks);
471 map_unlock(&map);
472 rv = 0;
473 goto out;
474 }
475 free(avail);
476
477 /* 7b/ if yes, */
478 /* - if number of OK devices match expected, or -R and there */
479 /* are enough, */
480 /* + add any bitmap file */
481 /* + start the array (auto-readonly). */
482
483 if (ioctl(mdfd, GET_ARRAY_INFO, &ainf) == 0) {
484 if (verbose >= 0)
485 fprintf(stderr, Name
486 ": %s attached to %s which is already active.\n",
487 devname, chosen_name);
488 map_unlock(&map);
489 rv = 0;
490 goto out;
491 }
492
493 map_unlock(&map);
494 if (runstop > 0 || active_disks >= info.array.working_disks) {
495 struct mdinfo *sra, *dsk;
496 /* Let's try to start it */
497 if (match && match->bitmap_file) {
498 int bmfd = open(match->bitmap_file, O_RDWR);
499 if (bmfd < 0) {
500 fprintf(stderr, Name
501 ": Could not open bitmap file %s.\n",
502 match->bitmap_file);
503 goto out;
504 }
505 if (ioctl(mdfd, SET_BITMAP_FILE, bmfd) != 0) {
506 close(bmfd);
507 fprintf(stderr, Name
508 ": Failed to set bitmapfile for %s.\n",
509 chosen_name);
510 goto out;
511 }
512 close(bmfd);
513 }
514 /* GET_* needed so add_disk works below */
515 sra = sysfs_read(mdfd, fd2devnum(mdfd),
516 GET_DEVS|GET_OFFSET|GET_SIZE|GET_STATE);
517 if ((sra == NULL || active_disks >= info.array.working_disks)
518 && trustworthy != FOREIGN)
519 rv = ioctl(mdfd, RUN_ARRAY, NULL);
520 else
521 rv = sysfs_set_str(sra, NULL,
522 "array_state", "read-auto");
523 if (rv == 0) {
524 if (verbose >= 0)
525 fprintf(stderr, Name
526 ": %s attached to %s, which has been started.\n",
527 devname, chosen_name);
528 rv = 0;
529 wait_for(chosen_name, mdfd);
530 /* We just started the array, so some devices
531 * might have been evicted from the array
532 * because their event counts were too old.
533 * If the action=re-add policy is in-force for
534 * those devices we should re-add them now.
535 */
536 for (dsk = sra->devs; dsk ; dsk = dsk->next) {
537 if (disk_action_allows(dsk, st->ss->name, act_re_add) &&
538 add_disk(mdfd, st, sra, dsk) == 0)
539 fprintf(stderr, Name
540 ": %s re-added to %s\n",
541 dsk->sys_name, chosen_name);
542 }
543 } else {
544 fprintf(stderr, Name
545 ": %s attached to %s, but failed to start: %s.\n",
546 devname, chosen_name, strerror(errno));
547 rv = 1;
548 }
549 } else {
550 if (verbose >= 0)
551 fprintf(stderr, Name
552 ": %s attached to %s, not enough to start safely.\n",
553 devname, chosen_name);
554 rv = 0;
555 }
556 out:
557 if (dfd >= 0)
558 close(dfd);
559 if (mdfd >= 0)
560 close(mdfd);
561 if (policy)
562 dev_policy_free(policy);
563 return rv;
564 }
565
566 static struct mddev_ident *search_mdstat(struct supertype *st,
567 struct mdinfo *info,
568 char *devname,
569 int verbose, int *rvp)
570 {
571 struct mddev_ident *array_list, *match;
572 array_list = conf_get_ident(NULL);
573 match = NULL;
574 for (; array_list; array_list = array_list->next) {
575 if (array_list->uuid_set &&
576 same_uuid(array_list->uuid, info->uuid, st->ss->swapuuid)
577 == 0) {
578 if (verbose >= 2 && array_list->devname)
579 fprintf(stderr, Name
580 ": UUID differs from %s.\n",
581 array_list->devname);
582 continue;
583 }
584 if (array_list->name[0] &&
585 strcasecmp(array_list->name, info->name) != 0) {
586 if (verbose >= 2 && array_list->devname)
587 fprintf(stderr, Name
588 ": Name differs from %s.\n",
589 array_list->devname);
590 continue;
591 }
592 if (array_list->devices &&
593 !match_oneof(array_list->devices, devname)) {
594 if (verbose >= 2 && array_list->devname)
595 fprintf(stderr, Name
596 ": Not a listed device for %s.\n",
597 array_list->devname);
598 continue;
599 }
600 if (array_list->super_minor != UnSet &&
601 array_list->super_minor != info->array.md_minor) {
602 if (verbose >= 2 && array_list->devname)
603 fprintf(stderr, Name
604 ": Different super-minor to %s.\n",
605 array_list->devname);
606 continue;
607 }
608 if (!array_list->uuid_set &&
609 !array_list->name[0] &&
610 !array_list->devices &&
611 array_list->super_minor == UnSet) {
612 if (verbose >= 2 && array_list->devname)
613 fprintf(stderr, Name
614 ": %s doesn't have any identifying information.\n",
615 array_list->devname);
616 continue;
617 }
618 /* FIXME, should I check raid_disks and level too?? */
619
620 if (match) {
621 if (verbose >= 0) {
622 if (match->devname && array_list->devname)
623 fprintf(stderr, Name
624 ": we match both %s and %s - cannot decide which to use.\n",
625 match->devname, array_list->devname);
626 else
627 fprintf(stderr, Name
628 ": multiple lines in mdadm.conf match\n");
629 }
630 *rvp = 2;
631 match = NULL;
632 break;
633 }
634 match = array_list;
635 }
636 return match;
637 }
638
639 static void find_reject(int mdfd, struct supertype *st, struct mdinfo *sra,
640 int number, __u64 events, int verbose,
641 char *array_name)
642 {
643 /* Find a device attached to this array with a disk.number of number
644 * and events less than the passed events, and remove the device.
645 */
646 struct mdinfo *d;
647 mdu_array_info_t ra;
648
649 if (ioctl(mdfd, GET_ARRAY_INFO, &ra) == 0)
650 return; /* not safe to remove from active arrays
651 * without thinking more */
652
653 for (d = sra->devs; d ; d = d->next) {
654 char dn[10];
655 int dfd;
656 struct mdinfo info;
657 sprintf(dn, "%d:%d", d->disk.major, d->disk.minor);
658 dfd = dev_open(dn, O_RDONLY);
659 if (dfd < 0)
660 continue;
661 if (st->ss->load_super(st, dfd, NULL)) {
662 close(dfd);
663 continue;
664 }
665 st->ss->getinfo_super(st, &info, NULL);
666 st->ss->free_super(st);
667 close(dfd);
668
669 if (info.disk.number != number ||
670 info.events >= events)
671 continue;
672
673 if (d->disk.raid_disk > -1)
674 sysfs_set_str(sra, d, "slot", "none");
675 if (sysfs_set_str(sra, d, "state", "remove") == 0)
676 if (verbose >= 0)
677 fprintf(stderr, Name
678 ": removing old device %s from %s\n",
679 d->sys_name+4, array_name);
680 }
681 }
682
683 static int count_active(struct supertype *st, int mdfd, char **availp,
684 struct mdinfo *bestinfo)
685 {
686 /* count how many devices in sra think they are active */
687 struct mdinfo *d;
688 int cnt = 0, cnt1 = 0;
689 __u64 max_events = 0;
690 struct mdinfo *sra = sysfs_read(mdfd, -1, GET_DEVS | GET_STATE);
691 char *avail = NULL;
692
693 if (!sra)
694 return 0;
695
696 for (d = sra->devs ; d ; d = d->next) {
697 char dn[30];
698 int dfd;
699 int ok;
700 struct mdinfo info;
701
702 sprintf(dn, "%d:%d", d->disk.major, d->disk.minor);
703 dfd = dev_open(dn, O_RDONLY);
704 if (dfd < 0)
705 continue;
706 ok = st->ss->load_super(st, dfd, NULL);
707 close(dfd);
708 if (ok != 0)
709 continue;
710 st->ss->getinfo_super(st, &info, NULL);
711 if (!avail) {
712 avail = malloc(info.array.raid_disks);
713 if (!avail) {
714 fprintf(stderr, Name ": out of memory.\n");
715 exit(1);
716 }
717 memset(avail, 0, info.array.raid_disks);
718 *availp = avail;
719 }
720
721 if (info.disk.state & (1<<MD_DISK_SYNC))
722 {
723 if (cnt == 0) {
724 cnt++;
725 max_events = info.events;
726 avail[info.disk.raid_disk] = 2;
727 st->ss->getinfo_super(st, bestinfo, NULL);
728 } else if (info.events == max_events) {
729 cnt++;
730 avail[info.disk.raid_disk] = 2;
731 } else if (info.events == max_events-1) {
732 cnt1++;
733 avail[info.disk.raid_disk] = 1;
734 } else if (info.events < max_events - 1)
735 ;
736 else if (info.events == max_events+1) {
737 int i;
738 cnt1 = cnt;
739 cnt = 1;
740 max_events = info.events;
741 for (i=0; i<info.array.raid_disks; i++)
742 if (avail[i])
743 avail[i]--;
744 avail[info.disk.raid_disk] = 2;
745 st->ss->getinfo_super(st, bestinfo, NULL);
746 } else { /* info.events much bigger */
747 cnt = 1; cnt1 = 0;
748 memset(avail, 0, info.disk.raid_disk);
749 max_events = info.events;
750 avail[info.disk.raid_disk] = 2;
751 st->ss->getinfo_super(st, bestinfo, NULL);
752 }
753 }
754 st->ss->free_super(st);
755 }
756 return cnt + cnt1;
757 }
758
759 static int array_try_spare(char *devname, int *dfdp, struct dev_policy *pol,
760 struct map_ent *target, int bare,
761 struct supertype *st, int verbose)
762 {
763 /* This device doesn't have any md metadata
764 * The device policy allows 'spare' and if !bare, it allows spare-same-slot.
765 * If 'st' is not set, then we only know that some metadata allows this,
766 * others possibly don't.
767 * So look for a container or array to attach the device to.
768 * Prefer 'target' if that is set and the array is found.
769 *
770 * If st is set, then only arrays of that type are considered
771 * Return 0 on success, or some exit code on failure, probably 1.
772 */
773 int rv = -1;
774 struct stat stb;
775 struct map_ent *mp, *map = NULL;
776 struct mdinfo *chosen = NULL;
777 int dfd = *dfdp;
778
779 if (fstat(dfd, &stb) != 0)
780 return 1;
781
782 /*
783 * Now we need to find a suitable array to add this to.
784 * We only accept arrays that:
785 * - match 'st'
786 * - are in the same domains as the device
787 * - are of an size for which the device will be useful
788 * and we choose the one that is the most degraded
789 */
790
791 if (map_lock(&map)) {
792 fprintf(stderr, Name ": failed to get exclusive lock on "
793 "mapfile\n");
794 return 1;
795 }
796 for (mp = map ; mp ; mp = mp->next) {
797 struct supertype *st2;
798 struct domainlist *dl = NULL;
799 struct mdinfo *sra;
800 unsigned long long devsize;
801
802 if (is_subarray(mp->metadata))
803 continue;
804 if (st) {
805 st2 = st->ss->match_metadata_desc(mp->metadata);
806 if (!st2 ||
807 (st->minor_version >= 0 &&
808 st->minor_version != st2->minor_version)) {
809 if (verbose > 1)
810 fprintf(stderr, Name ": not adding %s to %s as metadata type doesn't match\n",
811 devname, mp->path);
812 free(st2);
813 continue;
814 }
815 free(st2);
816 }
817 sra = sysfs_read(-1, mp->devnum,
818 GET_DEVS|GET_OFFSET|GET_SIZE|GET_STATE|
819 GET_DEGRADED|GET_COMPONENT|GET_VERSION);
820 if (!sra) {
821 /* Probably a container - no degraded info */
822 sra = sysfs_read(-1, mp->devnum,
823 GET_DEVS|GET_OFFSET|GET_SIZE|GET_STATE|
824 GET_COMPONENT|GET_VERSION);
825 if (sra)
826 sra->array.failed_disks = 0;
827 }
828 if (!sra)
829 continue;
830 if (st == NULL) {
831 int i;
832 st2 = NULL;
833 for(i=0; !st2 && superlist[i]; i++)
834 st2 = superlist[i]->match_metadata_desc(
835 sra->text_version);
836 if (!st2) {
837 if (verbose > 1)
838 fprintf(stderr, Name ": not adding %s to %s"
839 " as metadata not recognised.\n",
840 devname, mp->path);
841 goto next;
842 }
843 /* Need to double check the 'act_spare' permissions applies
844 * to this metadata.
845 */
846 if (!policy_action_allows(pol, st2->ss->name, act_spare))
847 goto next;
848 if (!bare && !policy_action_allows(pol, st2->ss->name,
849 act_spare_same_slot))
850 goto next;
851 } else
852 st2 = st;
853 get_dev_size(dfd, NULL, &devsize);
854 if (st2->ss->avail_size(st2, devsize) < sra->component_size) {
855 if (verbose > 1)
856 fprintf(stderr, Name ": not adding %s to %s as it is too small\n",
857 devname, mp->path);
858 goto next;
859 }
860 dl = domain_from_array(sra, st2->ss->name);
861 if (!domain_test(dl, pol, st2->ss->name)) {
862 /* domain test fails */
863 if (verbose > 1)
864 fprintf(stderr, Name ": not adding %s to %s as it is not in a compatible domain\n",
865 devname, mp->path);
866
867 goto next;
868 }
869 /* test against target.
870 * If 'target' is set and 'bare' is false, we only accept
871 * arrays/containers that match 'target'.
872 * If 'target' is set and 'bare' is true, we prefer the
873 * array which matches 'target'.
874 */
875 if (target) {
876 if (strcmp(target->metadata, mp->metadata) == 0 &&
877 memcmp(target->uuid, mp->uuid,
878 sizeof(target->uuid)) == 0) {
879 /* This is our target!! */
880 if (chosen)
881 sysfs_free(chosen);
882 chosen = sra;
883 sra = NULL;
884 /* skip to end so we don't check any more */
885 while (mp->next)
886 mp = mp->next;
887 goto next;
888 }
889 /* not our target */
890 if (!bare)
891 goto next;
892 }
893
894 /* all tests passed, OK to add to this array */
895 if (!chosen) {
896 chosen = sra;
897 sra = NULL;
898 } else if (chosen->array.failed_disks < sra->array.failed_disks) {
899 sysfs_free(chosen);
900 chosen = sra;
901 sra = NULL;
902 }
903 next:
904 if (sra)
905 sysfs_free(sra);
906 if (st != st2)
907 free(st2);
908 if (dl)
909 domain_free(dl);
910 }
911 if (chosen) {
912 /* add current device to chosen array as a spare */
913 int mdfd = open_dev(devname2devnum(chosen->sys_name));
914 if (mdfd >= 0) {
915 struct mddev_dev devlist;
916 char devname[20];
917 devlist.next = NULL;
918 devlist.used = 0;
919 devlist.re_add = 0;
920 devlist.writemostly = 0;
921 devlist.devname = devname;
922 sprintf(devname, "%d:%d", major(stb.st_rdev),
923 minor(stb.st_rdev));
924 devlist.disposition = 'a';
925 close(dfd);
926 *dfdp = -1;
927 rv = Manage_subdevs(chosen->sys_name, mdfd, &devlist,
928 -1, 0);
929 close(mdfd);
930 }
931 if (verbose > 0) {
932 if (rv == 0)
933 fprintf(stderr, Name ": added %s as spare for %s\n",
934 devname, chosen->sys_name);
935 else
936 fprintf(stderr, Name ": failed to add %s as spare for %s\n",
937 devname, chosen->sys_name);
938 }
939 sysfs_free(chosen);
940 }
941 return rv ? 0 : 1;
942 }
943
944 static int partition_try_spare(char *devname, int *dfdp, struct dev_policy *pol,
945 struct supertype *st, int verbose)
946 {
947 /* we know that at least one partition virtual-metadata is
948 * allowed to incorporate spares like this device. We need to
949 * find a suitable device to copy partition information from.
950 *
951 * Getting a list of all disk (not partition) devices is
952 * slightly non-trivial. We could look at /sys/block, but
953 * that is theoretically due to be removed. Maybe best to use
954 * /dev/disk/by-path/?* and ignore names ending '-partNN' as
955 * we depend on this directory of 'path' info. But that fails
956 * to find loop devices and probably others. Maybe don't
957 * worry about that, they aren't the real target.
958 *
959 * So: check things in /dev/disk/by-path to see if they are in
960 * a compatible domain, then load the partition table and see
961 * if it is OK for the new device, and choose the largest
962 * partition table that fits.
963 */
964 DIR *dir;
965 struct dirent *de;
966 char *chosen = NULL;
967 unsigned long long chosen_size;
968 struct supertype *chosen_st = NULL;
969 int fd;
970
971 dir = opendir("/dev/disk/by-path");
972 if (!dir)
973 return 1;
974 while ((de = readdir(dir)) != NULL) {
975 char *ep;
976 struct dev_policy *pol2 = NULL;
977 struct domainlist *domlist = NULL;
978 int fd = -1;
979 struct mdinfo info;
980 struct supertype *st2 = NULL;
981 char *devname = NULL;
982 unsigned long long devsectors;
983
984 if (de->d_ino == 0 ||
985 de->d_name[0] == '.' ||
986 (de->d_type != DT_LNK && de->d_type != DT_UNKNOWN))
987 goto next;
988
989 ep = de->d_name + strlen(de->d_name);
990 while (ep > de->d_name &&
991 isdigit(ep[-1]))
992 ep--;
993 if (ep > de->d_name + 5 &&
994 strncmp(ep-5, "-part", 5) == 0)
995 /* This is a partition - skip it */
996 goto next;
997
998 pol2 = path_policy(de->d_name, type_disk);
999
1000 domain_merge(&domlist, pol2, st ? st->ss->name : NULL);
1001 if (domain_test(domlist, pol, st ? st->ss->name : NULL) == 0)
1002 /* new device is incompatible with this device. */
1003 goto next;
1004
1005 domain_free(domlist);
1006 domlist = NULL;
1007
1008 asprintf(&devname, "/dev/disk/by-path/%s", de->d_name);
1009 fd = open(devname, O_RDONLY);
1010 if (fd < 0)
1011 goto next;
1012 if (get_dev_size(fd, devname, &devsectors) == 0)
1013 goto next;
1014 devsectors >>= 9;
1015
1016 if (st)
1017 st2 = dup_super(st);
1018 else
1019 st2 = guess_super_type(fd, guess_partitions);
1020 if (st2 == NULL ||
1021 st2->ss->load_super(st2, fd, NULL) < 0)
1022 goto next;
1023
1024 if (!st) {
1025 /* Check domain policy again, this time referring to metadata */
1026 domain_merge(&domlist, pol2, st2->ss->name);
1027 if (domain_test(domlist, pol, st2->ss->name) == 0)
1028 /* Incompatible devices for this metadata type */
1029 goto next;
1030 if (!policy_action_allows(pol, st2->ss->name, act_spare))
1031 /* Some partition types allow sparing, but not
1032 * this one.
1033 */
1034 goto next;
1035 }
1036
1037 st2->ss->getinfo_super(st2, &info, NULL);
1038 if (info.component_size > devsectors)
1039 /* This partitioning doesn't fit in the device */
1040 goto next;
1041
1042 /* This is an acceptable device to copy partition
1043 * metadata from. We could just stop here, but I
1044 * think I want to keep looking incase a larger
1045 * metadata which makes better use of the device can
1046 * be found.
1047 */
1048 if (chosen == NULL ||
1049 chosen_size < info.component_size) {
1050 chosen_size = info.component_size;
1051 free(chosen);
1052 chosen = devname;
1053 devname = NULL;
1054 if (chosen_st) {
1055 chosen_st->ss->free_super(chosen_st);
1056 free(chosen_st);
1057 }
1058 chosen_st = st2;
1059 st2 = NULL;
1060 }
1061
1062 next:
1063 free(devname);
1064 domain_free(domlist);
1065 dev_policy_free(pol2);
1066 if (st2)
1067 st2->ss->free_super(st2);
1068 free(st2);
1069
1070 if (fd >= 0)
1071 close(fd);
1072 }
1073
1074 if (!chosen)
1075 return 1;
1076
1077 /* 'chosen' is the best device we can find. Let's write its
1078 * metadata to devname dfd is read-only so don't use that
1079 */
1080 fd = open(devname, O_RDWR);
1081 if (fd >= 0) {
1082 chosen_st->ss->store_super(chosen_st, fd);
1083 close(fd);
1084 }
1085 free(chosen);
1086 chosen_st->ss->free_super(chosen_st);
1087 free(chosen_st);
1088 return 0;
1089 }
1090
1091 static int is_bare(int dfd)
1092 {
1093 unsigned long long size = 0;
1094 char bufpad[4096 + 4096];
1095 char *buf = (char*)(((long)bufpad + 4096) & ~4095);
1096
1097 if (lseek(dfd, 0, SEEK_SET) != 0 ||
1098 read(dfd, buf, 4096) != 4096)
1099 return 0;
1100
1101 if (buf[0] != '\0' && buf[0] != '\x5a' && buf[0] != '\xff')
1102 return 0;
1103 if (memcmp(buf, buf+1, 4095) != 0)
1104 return 0;
1105
1106 /* OK, first 4K appear blank, try the end. */
1107 get_dev_size(dfd, NULL, &size);
1108 if (lseek(dfd, size-4096, SEEK_SET) < 0 ||
1109 read(dfd, buf, 4096) != 4096)
1110 return 0;
1111
1112 if (buf[0] != '\0' && buf[0] != '\x5a' && buf[0] != '\xff')
1113 return 0;
1114 if (memcmp(buf, buf+1, 4095) != 0)
1115 return 0;
1116
1117 return 1;
1118 }
1119
1120 /* adding a spare to a regular array is quite different from adding one to
1121 * a set-of-partitions virtual array.
1122 * This function determines which is worth trying and tries as appropriate.
1123 * Arrays are given priority over partitions.
1124 */
1125 static int try_spare(char *devname, int *dfdp, struct dev_policy *pol,
1126 struct map_ent *target,
1127 struct supertype *st, int verbose)
1128 {
1129 int i;
1130 int rv;
1131 int arrays_ok = 0;
1132 int partitions_ok = 0;
1133 int dfd = *dfdp;
1134 int bare;
1135
1136 /* Can only add a spare if device has at least one domain */
1137 if (pol_find(pol, pol_domain) == NULL)
1138 return 1;
1139 /* And only if some action allows spares */
1140 if (!policy_action_allows(pol, st?st->ss->name:NULL, act_spare))
1141 return 1;
1142
1143 /* Now check if the device is bare.
1144 * bare devices can always be added as a spare
1145 * non-bare devices can only be added if spare-same-slot is permitted,
1146 * and this device is replacing a previous device - in which case 'target'
1147 * will be set.
1148 */
1149 if (!is_bare(dfd)) {
1150 /* Must have a target and allow same_slot */
1151 /* Later - may allow force_spare without target */
1152 if (!target ||
1153 !policy_action_allows(pol, st?st->ss->name:NULL,
1154 act_spare_same_slot)) {
1155 if (verbose > 1)
1156 fprintf(stderr, Name ": %s is not bare, so not "
1157 "considering as a spare\n",
1158 devname);
1159 return 1;
1160 }
1161 bare = 0;
1162 } else
1163 bare = 1;
1164
1165 /* It might be OK to add this device to an array - need to see
1166 * what arrays might be candidates.
1167 */
1168 if (st) {
1169 /* just try try 'array' or 'partition' based on this metadata */
1170 if (st->ss->add_to_super)
1171 return array_try_spare(devname, dfdp, pol, target, bare,
1172 st, verbose);
1173 else
1174 return partition_try_spare(devname, dfdp, pol,
1175 st, verbose);
1176 }
1177 /* No metadata was specified or found so options are open.
1178 * Check for whether any array metadata, or any partition metadata
1179 * might allow adding the spare. This check is just help to avoid
1180 * a more costly scan of all arrays when we can be sure that will
1181 * fail.
1182 */
1183 for (i = 0; (!arrays_ok || !partitions_ok) && superlist[i] ; i++) {
1184 if (superlist[i]->add_to_super && !arrays_ok &&
1185 policy_action_allows(pol, superlist[i]->name, act_spare))
1186 arrays_ok = 1;
1187 if (superlist[i]->add_to_super == NULL && !partitions_ok &&
1188 policy_action_allows(pol, superlist[i]->name, act_spare))
1189 partitions_ok = 1;
1190 }
1191 rv = 1;
1192 if (arrays_ok)
1193 rv = array_try_spare(devname, dfdp, pol, target, bare,
1194 st, verbose);
1195 if (rv != 0 && partitions_ok)
1196 rv = partition_try_spare(devname, dfdp, pol, st, verbose);
1197 return rv;
1198 }
1199
1200 int IncrementalScan(int verbose)
1201 {
1202 /* look at every device listed in the 'map' file.
1203 * If one is found that is not running then:
1204 * look in mdadm.conf for bitmap file.
1205 * if one exists, but array has none, add it.
1206 * try to start array in auto-readonly mode
1207 */
1208 struct map_ent *mapl = NULL;
1209 struct map_ent *me;
1210 struct mddev_ident *devs, *mddev;
1211 int rv = 0;
1212
1213 map_read(&mapl);
1214 devs = conf_get_ident(NULL);
1215
1216 for (me = mapl ; me ; me = me->next) {
1217 mdu_array_info_t array;
1218 mdu_bitmap_file_t bmf;
1219 struct mdinfo *sra;
1220 int mdfd = open_dev(me->devnum);
1221
1222 if (mdfd < 0)
1223 continue;
1224 if (ioctl(mdfd, GET_ARRAY_INFO, &array) == 0 ||
1225 errno != ENODEV) {
1226 close(mdfd);
1227 continue;
1228 }
1229 /* Ok, we can try this one. Maybe it needs a bitmap */
1230 for (mddev = devs ; mddev ; mddev = mddev->next)
1231 if (mddev->devname && me->path
1232 && devname_matches(mddev->devname, me->path))
1233 break;
1234 if (mddev && mddev->bitmap_file) {
1235 /*
1236 * Note: early kernels will wrongly fail this, so it
1237 * is a hint only
1238 */
1239 int added = -1;
1240 if (ioctl(mdfd, GET_ARRAY_INFO, &bmf) < 0) {
1241 int bmfd = open(mddev->bitmap_file, O_RDWR);
1242 if (bmfd >= 0) {
1243 added = ioctl(mdfd, SET_BITMAP_FILE,
1244 bmfd);
1245 close(bmfd);
1246 }
1247 }
1248 if (verbose >= 0) {
1249 if (added == 0)
1250 fprintf(stderr, Name
1251 ": Added bitmap %s to %s\n",
1252 mddev->bitmap_file, me->path);
1253 else if (errno != EEXIST)
1254 fprintf(stderr, Name
1255 ": Failed to add bitmap to %s: %s\n",
1256 me->path, strerror(errno));
1257 }
1258 }
1259 sra = sysfs_read(mdfd, 0, 0);
1260 if (sra) {
1261 if (sysfs_set_str(sra, NULL,
1262 "array_state", "read-auto") == 0) {
1263 if (verbose >= 0)
1264 fprintf(stderr, Name
1265 ": started array %s\n",
1266 me->path ?: devnum2devname(me->devnum));
1267 } else {
1268 fprintf(stderr, Name
1269 ": failed to start array %s: %s\n",
1270 me->path ?: devnum2devname(me->devnum),
1271 strerror(errno));
1272 rv = 1;
1273 }
1274 }
1275 }
1276 return rv;
1277 }
1278
1279 static char *container2devname(char *devname)
1280 {
1281 char *mdname = NULL;
1282
1283 if (devname[0] == '/') {
1284 int fd = open(devname, O_RDONLY);
1285 if (fd >= 0) {
1286 mdname = devnum2devname(fd2devnum(fd));
1287 close(fd);
1288 }
1289 } else {
1290 int uuid[4];
1291 struct map_ent *mp, *map = NULL;
1292
1293 if (!parse_uuid(devname, uuid))
1294 return mdname;
1295 mp = map_by_uuid(&map, uuid);
1296 if (mp)
1297 mdname = devnum2devname(mp->devnum);
1298 map_free(map);
1299 }
1300
1301 return mdname;
1302 }
1303
1304 static int Incremental_container(struct supertype *st, char *devname,
1305 char *homehost, int verbose,
1306 int runstop, int autof)
1307 {
1308 /* Collect the contents of this container and for each
1309 * array, choose a device name and assemble the array.
1310 */
1311
1312 struct mdinfo *list;
1313 struct mdinfo *ra;
1314 struct map_ent *map = NULL;
1315 struct mdinfo info;
1316 int trustworthy;
1317 struct mddev_ident *match;
1318 int rv = 0;
1319
1320 memset(&info, 0, sizeof(info));
1321 st->ss->getinfo_super(st, &info, NULL);
1322
1323 if ((runstop > 0 && info.container_enough >= 0) ||
1324 info.container_enough > 0)
1325 /* pass */;
1326 else {
1327 if (verbose)
1328 fprintf(stderr, Name ": not enough devices to start the container\n");
1329 return 0;
1330 }
1331
1332 match = search_mdstat(st, &info, devname, verbose, &rv);
1333 if (match == NULL && rv == 2)
1334 return rv;
1335
1336 /* Need to compute 'trustworthy' */
1337 if (match)
1338 trustworthy = LOCAL;
1339 else if (st->ss->match_home(st, homehost) == 1)
1340 trustworthy = LOCAL;
1341 else if (st->ss->match_home(st, "any") == 1)
1342 trustworthy = LOCAL;
1343 else
1344 trustworthy = FOREIGN;
1345
1346 list = st->ss->container_content(st, NULL);
1347 if (map_lock(&map))
1348 fprintf(stderr, Name ": failed to get exclusive lock on "
1349 "mapfile\n");
1350
1351 for (ra = list ; ra ; ra = ra->next) {
1352 int mdfd;
1353 char chosen_name[1024];
1354 struct map_ent *mp;
1355 struct mddev_ident *match = NULL;
1356
1357 mp = map_by_uuid(&map, ra->uuid);
1358
1359 if (mp) {
1360 mdfd = open_dev(mp->devnum);
1361 if (mp->path)
1362 strcpy(chosen_name, mp->path);
1363 else
1364 strcpy(chosen_name, devnum2devname(mp->devnum));
1365 } else {
1366
1367 /* Check in mdadm.conf for container == devname and
1368 * member == ra->text_version after second slash.
1369 */
1370 char *sub = strchr(ra->text_version+1, '/');
1371 struct mddev_ident *array_list;
1372 if (sub) {
1373 sub++;
1374 array_list = conf_get_ident(NULL);
1375 } else
1376 array_list = NULL;
1377 for(; array_list ; array_list = array_list->next) {
1378 char *dn;
1379 if (array_list->member == NULL ||
1380 array_list->container == NULL)
1381 continue;
1382 if (strcmp(array_list->member, sub) != 0)
1383 continue;
1384 if (array_list->uuid_set &&
1385 !same_uuid(ra->uuid, array_list->uuid, st->ss->swapuuid))
1386 continue;
1387 dn = container2devname(array_list->container);
1388 if (dn == NULL)
1389 continue;
1390 if (strncmp(dn, ra->text_version+1,
1391 strlen(dn)) != 0 ||
1392 ra->text_version[strlen(dn)+1] != '/') {
1393 free(dn);
1394 continue;
1395 }
1396 free(dn);
1397 /* we have a match */
1398 match = array_list;
1399 if (verbose>0)
1400 fprintf(stderr, Name ": match found for member %s\n",
1401 array_list->member);
1402 break;
1403 }
1404
1405 if (match && match->devname &&
1406 strcasecmp(match->devname, "<ignore>") == 0) {
1407 if (verbose > 0)
1408 fprintf(stderr, Name ": array %s/%s is "
1409 "explicitly ignored by mdadm.conf\n",
1410 match->container, match->member);
1411 return 2;
1412 }
1413 if (match)
1414 trustworthy = LOCAL;
1415
1416 mdfd = create_mddev(match ? match->devname : NULL,
1417 ra->name,
1418 autof,
1419 trustworthy,
1420 chosen_name);
1421 }
1422
1423 if (mdfd < 0) {
1424 fprintf(stderr, Name ": failed to open %s: %s.\n",
1425 chosen_name, strerror(errno));
1426 return 2;
1427 }
1428
1429 assemble_container_content(st, mdfd, ra, runstop,
1430 chosen_name, verbose);
1431 }
1432 map_unlock(&map);
1433 return 0;
1434 }
1435
1436 /*
1437 * IncrementalRemove - Attempt to see if the passed in device belongs to any
1438 * raid arrays, and if so first fail (if needed) and then remove the device.
1439 *
1440 * @devname - The device we want to remove
1441 * @id_path - name as found in /dev/disk/by-path for this device
1442 *
1443 * Note: the device name must be a kernel name like "sda", so
1444 * that we can find it in /proc/mdstat
1445 */
1446 int IncrementalRemove(char *devname, char *id_path, int verbose)
1447 {
1448 int mdfd;
1449 int rv;
1450 struct mdstat_ent *ent;
1451 struct mddev_dev devlist;
1452
1453 if (!id_path)
1454 dprintf(Name ": incremental removal without --path <id_path> "
1455 "lacks the possibility to re-add new device in this "
1456 "port\n");
1457
1458 if (strchr(devname, '/')) {
1459 fprintf(stderr, Name ": incremental removal requires a "
1460 "kernel device name, not a file: %s\n", devname);
1461 return 1;
1462 }
1463 ent = mdstat_by_component(devname);
1464 if (!ent) {
1465 fprintf(stderr, Name ": %s does not appear to be a component "
1466 "of any array\n", devname);
1467 return 1;
1468 }
1469 mdfd = open_dev(ent->devnum);
1470 if (mdfd < 0) {
1471 fprintf(stderr, Name ": Cannot open array %s!!\n", ent->dev);
1472 free_mdstat(ent);
1473 return 1;
1474 }
1475
1476 if (id_path) {
1477 struct map_ent *map = NULL, *me;
1478 me = map_by_devnum(&map, ent->devnum);
1479 if (me)
1480 policy_save_path(id_path, me);
1481 map_free(map);
1482 }
1483
1484 memset(&devlist, 0, sizeof(devlist));
1485 devlist.devname = devname;
1486 devlist.disposition = 'f';
1487 /* for a container, we must fail each member array */
1488 if (ent->metadata_version &&
1489 strncmp(ent->metadata_version, "external:", 9) == 0) {
1490 struct mdstat_ent *mdstat = mdstat_read(0, 0);
1491 struct mdstat_ent *memb;
1492 for (memb = mdstat ; memb ; memb = memb->next)
1493 if (is_container_member(memb, ent->dev)) {
1494 int subfd = open_dev(memb->devnum);
1495 if (subfd >= 0) {
1496 Manage_subdevs(memb->dev, subfd,
1497 &devlist, verbose, 0);
1498 close(subfd);
1499 }
1500 }
1501 free_mdstat(mdstat);
1502 } else
1503 Manage_subdevs(ent->dev, mdfd, &devlist, verbose, 0);
1504 devlist.disposition = 'r';
1505 rv = Manage_subdevs(ent->dev, mdfd, &devlist, verbose, 0);
1506 close(mdfd);
1507 free_mdstat(ent);
1508 return rv;
1509 }