]> git.ipfire.org Git - thirdparty/mdadm.git/blame - Manage.c
DDF: compare_super_ddf: merge local info of other superblock
[thirdparty/mdadm.git] / Manage.c
CommitLineData
64c4757e 1/*
9a9dab36 2 * mdadm - manage Linux "md" devices aka RAID arrays.
64c4757e 3 *
7bd04da9 4 * Copyright (C) 2001-2012 Neil Brown <neilb@suse.de>
64c4757e
NB
5 *
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 * Author: Neil Brown
e736b623 22 * Email: <neilb@suse.de>
64c4757e
NB
23 */
24
9a9dab36 25#include "mdadm.h"
682c7051
NB
26#include "md_u.h"
27#include "md_p.h"
4ccad7b1 28#include <ctype.h>
64c4757e 29
82b27616
NB
30#define REGISTER_DEV _IO (MD_MAJOR, 1)
31#define START_MD _IO (MD_MAJOR, 2)
32#define STOP_MD _IO (MD_MAJOR, 3)
33
64c4757e
NB
34int Manage_ro(char *devname, int fd, int readonly)
35{
682c7051
NB
36 /* switch to readonly or rw
37 *
38 * requires >= 0.90.0
39 * first check that array is runing
40 * use RESTART_ARRAY_RW or STOP_ARRAY_RO
41 *
42 */
43 mdu_array_info_t array;
0e600426 44#ifndef MDASSEMBLE
e9dd1598 45 struct mdinfo *mdi;
0e600426 46#endif
b73e45ae 47 int rv = 0;
aba69144 48
682c7051 49 if (md_get_version(fd) < 9000) {
e7b84f9d 50 pr_err("need md driver version 0.90.0 or later\n");
682c7051
NB
51 return 1;
52 }
0e600426 53#ifndef MDASSEMBLE
7bd04da9 54 /* If this is an externally-managed array, we need to modify the
e9dd1598
N
55 * metadata_version so that mdmon doesn't undo our change.
56 */
4dd2df09 57 mdi = sysfs_read(fd, NULL, GET_LEVEL|GET_VERSION);
e9dd1598
N
58 if (mdi &&
59 mdi->array.major_version == -1 &&
e9dd1598
N
60 is_subarray(mdi->text_version)) {
61 char vers[64];
62 strcpy(vers, "external:");
63 strcat(vers, mdi->text_version);
64 if (readonly > 0) {
65 int rv;
66 /* We set readonly ourselves. */
67 vers[9] = '-';
68 sysfs_set_str(mdi, NULL, "metadata_version", vers);
69
70 close(fd);
71 rv = sysfs_set_str(mdi, NULL, "array_state", "readonly");
72
73 if (rv < 0) {
e7b84f9d 74 pr_err("failed to set readonly for %s: %s\n",
e9dd1598
N
75 devname, strerror(errno));
76
77 vers[9] = mdi->text_version[0];
78 sysfs_set_str(mdi, NULL, "metadata_version", vers);
b73e45ae
JS
79 rv = 1;
80 goto out;
e9dd1598
N
81 }
82 } else {
83 char *cp;
84 /* We cannot set read/write - must signal mdmon */
85 vers[9] = '/';
86 sysfs_set_str(mdi, NULL, "metadata_version", vers);
87
88 cp = strchr(vers+10, '/');
1471b8b1 89 if (cp)
e9dd1598
N
90 *cp = 0;
91 ping_monitor(vers+10);
9ea5a252
DW
92 if (mdi->array.level <= 0)
93 sysfs_set_str(mdi, NULL, "array_state", "active");
e9dd1598 94 }
b73e45ae 95 goto out;
e9dd1598 96 }
0e600426 97#endif
682c7051 98 if (ioctl(fd, GET_ARRAY_INFO, &array)) {
e7b84f9d 99 pr_err("%s does not appear to be active.\n",
682c7051 100 devname);
b73e45ae
JS
101 rv = 1;
102 goto out;
682c7051 103 }
aba69144 104
7bd04da9 105 if (readonly > 0) {
682c7051 106 if (ioctl(fd, STOP_ARRAY_RO, NULL)) {
e7b84f9d 107 pr_err("failed to set readonly for %s: %s\n",
682c7051 108 devname, strerror(errno));
b73e45ae
JS
109 rv = 1;
110 goto out;
682c7051
NB
111 }
112 } else if (readonly < 0) {
113 if (ioctl(fd, RESTART_ARRAY_RW, NULL)) {
e7b84f9d 114 pr_err("failed to set writable for %s: %s\n",
682c7051 115 devname, strerror(errno));
b73e45ae
JS
116 rv = 1;
117 goto out;
682c7051
NB
118 }
119 }
b73e45ae
JS
120out:
121#ifndef MDASSEMBLE
122 if (mdi)
123 sysfs_free(mdi);
124#endif
125 return rv;
64c4757e
NB
126}
127
435d4ebb
LB
128#ifndef MDASSEMBLE
129
4dd2df09 130static void remove_devices(char *devnm, char *path)
4ccad7b1 131{
7bd04da9 132 /*
b1702f48
N
133 * Remove names at 'path' - possibly with
134 * partition suffixes - which link to the 'standard'
4dd2df09 135 * name for devnm. These were probably created
b1702f48 136 * by mdadm when the array was assembled.
4ccad7b1
N
137 */
138 char base[40];
139 char *path2;
140 char link[1024];
141 int n;
142 int part;
143 char *be;
144 char *pe;
145
b1702f48
N
146 if (!path)
147 return;
148
4dd2df09 149 sprintf(base, "/dev/%s", devnm);
4ccad7b1 150 be = base + strlen(base);
b1702f48 151
503975b9 152 path2 = xmalloc(strlen(path)+20);
b1702f48
N
153 strcpy(path2, path);
154 pe = path2 + strlen(path2);
7bd04da9 155
4ccad7b1
N
156 for (part = 0; part < 16; part++) {
157 if (part) {
158 sprintf(be, "p%d", part);
b1702f48
N
159
160 if (isdigit(pe[-1]))
161 sprintf(pe, "p%d", part);
162 else
163 sprintf(pe, "%d", part);
4ccad7b1 164 }
b1702f48 165 n = readlink(path2, link, sizeof(link));
d9ca03e9 166 if (n > 0 && (int)strlen(base) == n &&
b1702f48
N
167 strncmp(link, base, n) == 0)
168 unlink(path2);
4ccad7b1 169 }
0eb26465 170 free(path2);
4ccad7b1 171}
4ccad7b1 172
ba728be7
N
173int Manage_runstop(char *devname, int fd, int runstop,
174 int verbose, int will_retry)
64c4757e 175{
7bd04da9 176 /* Run or stop the array. Array must already be configured
ba728be7
N
177 * 'Run' requires >= 0.90.0
178 * 'will_retry' is only relevant for 'stop', and means
179 * that error messages are not wanted.
682c7051 180 */
682c7051 181 mdu_param_t param; /* unused */
bccd8153 182 int rv = 0;
82b27616 183
ba728be7
N
184 if (will_retry && verbose == 0)
185 verbose = -1;
186
82b27616 187 if (runstop == -1 && md_get_version(fd) < 9000) {
7bd04da9
N
188 if (ioctl(fd, STOP_MD, 0) == 0)
189 return 0;
190 pr_err("stopping device %s "
191 "failed: %s\n",
192 devname, strerror(errno));
193 return 1;
82b27616 194 }
aba69144 195
682c7051 196 if (md_get_version(fd) < 9000) {
e7b84f9d 197 pr_err("need md driver version 0.90.0 or later\n");
682c7051
NB
198 return 1;
199 }
ba728be7 200
7bd04da9 201 if (runstop > 0) {
682c7051 202 if (ioctl(fd, RUN_ARRAY, &param)) {
ba728be7
N
203 if (verbose >= 0)
204 pr_err("failed to run array %s: %s\n",
205 devname, strerror(errno));
682c7051
NB
206 return 1;
207 }
ba728be7 208 if (verbose >= 0)
e7b84f9d 209 pr_err("started %s\n", devname);
682c7051 210 } else if (runstop < 0){
8382f19b
NB
211 struct map_ent *map = NULL;
212 struct stat stb;
daf7a3ce 213 struct mdinfo *mdi;
4dd2df09 214 char devnm[32];
eb0af526
N
215 int err;
216 int count;
daf7a3ce
NB
217 /* If this is an mdmon managed array, just write 'inactive'
218 * to the array state and let mdmon clear up.
219 */
4dd2df09 220 strcpy(devnm, fd2devnm(fd));
eb0af526
N
221 /* Get EXCL access first. If this fails, then attempting
222 * to stop is probably a bad idea.
223 */
224 close(fd);
225 fd = open(devname, O_RDONLY|O_EXCL);
4dd2df09 226 if (fd < 0 || strcmp(fd2devnm(fd), devnm) != 0) {
eb0af526
N
227 if (fd >= 0)
228 close(fd);
ba728be7
N
229 if (verbose >= 0)
230 pr_err("Cannot get exclusive access to %s:"
231 "Perhaps a running "
232 "process, mounted filesystem "
233 "or active volume group?\n",
234 devname);
eb0af526
N
235 return 1;
236 }
4dd2df09 237 mdi = sysfs_read(fd, NULL, GET_LEVEL|GET_VERSION);
daf7a3ce
NB
238 if (mdi &&
239 mdi->array.level > 0 &&
3c558363 240 is_subarray(mdi->text_version)) {
1ae42d9d 241 int err;
daf7a3ce
NB
242 /* This is mdmon managed. */
243 close(fd);
1ae42d9d 244
7bd04da9
N
245 /* As we have an O_EXCL open, any use of the device
246 * which blocks STOP_ARRAY is probably a transient use,
247 * so it is reasonable to retry for a while - 5 seconds.
248 */
1ae42d9d
KW
249 count = 25;
250 while (count &&
251 (err = sysfs_set_str(mdi, NULL,
252 "array_state",
253 "inactive")) < 0
254 && errno == EBUSY) {
255 usleep(200000);
256 count--;
257 }
ba728be7
N
258 if (err) {
259 if (verbose >= 0)
260 pr_err("failed to stop array %s: %s\n",
261 devname, strerror(errno));
bccd8153
JS
262 rv = 1;
263 goto out;
daf7a3ce
NB
264 }
265
266 /* Give monitor a chance to act */
c94709e8 267 ping_monitor(mdi->text_version);
daf7a3ce 268
4dd2df09 269 fd = open_dev_excl(devnm);
eb0af526 270 if (fd < 0) {
ba728be7
N
271 if (verbose >= 0)
272 pr_err("failed to completely stop %s"
273 ": Device is busy\n",
274 devname);
bccd8153
JS
275 rv = 1;
276 goto out;
eb0af526 277 }
ada6c239
N
278 } else if (mdi &&
279 mdi->array.major_version == -1 &&
280 mdi->array.minor_version == -2 &&
3c558363 281 !is_subarray(mdi->text_version)) {
430ea469 282 struct mdstat_ent *mds, *m;
ada6c239
N
283 /* container, possibly mdmon-managed.
284 * Make sure mdmon isn't opening it, which
285 * would interfere with the 'stop'
286 */
287 ping_monitor(mdi->sys_name);
430ea469
N
288
289 /* now check that there are no existing arrays
290 * which are members of this array
291 */
292 mds = mdstat_read(0, 0);
7bd04da9 293 for (m = mds; m; m = m->next)
430ea469
N
294 if (m->metadata_version &&
295 strncmp(m->metadata_version, "external:", 9)==0 &&
4dd2df09
N
296 metadata_container_matches(m->metadata_version+9,
297 devnm)) {
ba728be7 298 if (verbose >= 0)
e7b84f9d
N
299 pr_err("Cannot stop container %s: "
300 "member %s still active\n",
301 devname, m->dev);
430ea469 302 free_mdstat(mds);
bccd8153
JS
303 rv = 1;
304 goto out;
430ea469 305 }
daf7a3ce 306 }
daf7a3ce 307
eb0af526
N
308 /* As we have an O_EXCL open, any use of the device
309 * which blocks STOP_ARRAY is probably a transient use,
310 * so it is reasonable to retry for a while - 5 seconds.
311 */
fb0d4b9c 312 count = 25; err = 0;
eb0af526
N
313 while (count && fd >= 0
314 && (err = ioctl(fd, STOP_ARRAY, NULL)) < 0
315 && errno == EBUSY) {
316 usleep(200000);
317 count --;
318 }
319 if (fd >= 0 && err) {
ba728be7 320 if (verbose >= 0) {
e7b84f9d
N
321 pr_err("failed to stop array %s: %s\n",
322 devname, strerror(errno));
d927f3c4
NB
323 if (errno == EBUSY)
324 fprintf(stderr, "Perhaps a running "
325 "process, mounted filesystem "
326 "or active volume group?\n");
327 }
bccd8153
JS
328 rv = 1;
329 goto out;
682c7051 330 }
97590376 331 /* prior to 2.6.28, KOBJ_CHANGE was not sent when an md array
d49410d3
N
332 * was stopped, so We'll do it here just to be sure. Drop any
333 * partitions as well...
97590376 334 */
d49410d3
N
335 if (fd >= 0)
336 ioctl(fd, BLKRRPART, 0);
97590376
N
337 if (mdi)
338 sysfs_uevent(mdi, "change");
daf7a3ce 339
4dd2df09 340 if (devnm[0] &&
4ccad7b1
N
341 (stat("/dev/.udev", &stb) != 0 ||
342 check_env("MDADM_NO_UDEV"))) {
4dd2df09
N
343 struct map_ent *mp = map_by_devnm(&map, devnm);
344 remove_devices(devnm, mp ? mp->path : NULL);
4ccad7b1
N
345 }
346
ba728be7 347 if (verbose >= 0)
e7b84f9d 348 pr_err("stopped %s\n", devname);
4eb26970 349 map_lock(&map);
4dd2df09 350 map_remove(&map, devnm);
4eb26970 351 map_unlock(&map);
bccd8153
JS
352 out:
353 if (mdi)
354 sysfs_free(mdi);
682c7051 355 }
bccd8153 356 return rv;
64c4757e
NB
357}
358
1d997643
N
359static void add_faulty(struct mddev_dev *dv, int fd, char disp)
360{
361 mdu_array_info_t array;
362 mdu_disk_info_t disk;
363 int remaining_disks;
364 int i;
365
366 if (ioctl(fd, GET_ARRAY_INFO, &array) != 0)
367 return;
368
369 remaining_disks = array.nr_disks;
370 for (i = 0; i < MAX_DISKS && remaining_disks > 0; i++) {
371 struct mddev_dev *new;
372 char buf[40];
373 disk.number = i;
374 if (ioctl(fd, GET_DISK_INFO, &disk) != 0)
375 continue;
376 if (disk.major == 0 && disk.minor == 0)
377 continue;
378 remaining_disks--;
379 if ((disk.state & 1) == 0) /* not faulty */
380 continue;
381 sprintf(buf, "%d:%d", disk.major, disk.minor);
382 new = xmalloc(sizeof(*new));
383 new->devname = xstrdup(buf);
384 new->disposition = disp;
385 new->next = dv->next;
386 dv->next = new;
387 dv = new;
388 }
389}
390
391static void add_detached(struct mddev_dev *dv, int fd, char disp)
392{
393 mdu_array_info_t array;
394 mdu_disk_info_t disk;
395 int remaining_disks;
396 int i;
397
398 if (ioctl(fd, GET_ARRAY_INFO, &array) != 0)
399 return;
400
401 remaining_disks = array.nr_disks;
402 for (i = 0; i < MAX_DISKS && remaining_disks > 0; i++) {
403 struct mddev_dev *new;
404 char buf[40];
405 int sfd;
406 disk.number = i;
407 if (ioctl(fd, GET_DISK_INFO, &disk) != 0)
408 continue;
409 if (disk.major == 0 && disk.minor == 0)
410 continue;
411 remaining_disks--;
412 if (disp == 'f' && (disk.state & 1) != 0) /* already faulty */
413 continue;
414 sprintf(buf, "%d:%d", disk.major, disk.minor);
415 sfd = dev_open(buf, O_RDONLY);
416 if (sfd >= 0) {
417 /* Not detached */
418 close(sfd);
419 continue;
420 }
421 if (errno != ENXIO)
422 /* Probably not detached */
423 continue;
424 new = xmalloc(sizeof(*new));
425 new->devname = xstrdup(buf);
426 new->disposition = disp;
427 new->next = dv->next;
428 dv->next = new;
429 dv = new;
430 }
431}
432
abe94694
N
433int attempt_re_add(int fd, int tfd, struct mddev_dev *dv,
434 struct supertype *dev_st, struct supertype *tst,
435 unsigned long rdev,
436 char *update, char *devname, int verbose,
437 mdu_array_info_t *array)
438{
439 struct mdinfo mdi;
440 int duuid[4];
441 int ouuid[4];
442
443 dev_st->ss->getinfo_super(dev_st, &mdi, NULL);
444 dev_st->ss->uuid_from_super(dev_st, ouuid);
445 if (tst->sb)
446 tst->ss->uuid_from_super(tst, duuid);
447 else
448 /* Assume uuid matches: kernel will check */
449 memcpy(duuid, ouuid, sizeof(ouuid));
450 if ((mdi.disk.state & (1<<MD_DISK_ACTIVE)) &&
451 !(mdi.disk.state & (1<<MD_DISK_FAULTY)) &&
452 memcmp(duuid, ouuid, sizeof(ouuid))==0) {
453 /* Looks like it is worth a
454 * try. Need to make sure
455 * kernel will accept it
456 * though.
457 */
458 mdu_disk_info_t disc;
459 /* re-add doesn't work for version-1 superblocks
460 * before 2.6.18 :-(
461 */
462 if (array->major_version == 1 &&
463 get_linux_version() <= 2006018)
464 goto skip_re_add;
465 disc.number = mdi.disk.number;
466 if (ioctl(fd, GET_DISK_INFO, &disc) != 0
467 || disc.major != 0 || disc.minor != 0
468 )
469 goto skip_re_add;
470 disc.major = major(rdev);
471 disc.minor = minor(rdev);
472 disc.number = mdi.disk.number;
473 disc.raid_disk = mdi.disk.raid_disk;
474 disc.state = mdi.disk.state;
475 if (dv->writemostly == 1)
476 disc.state |= 1 << MD_DISK_WRITEMOSTLY;
477 if (dv->writemostly == 2)
478 disc.state &= ~(1 << MD_DISK_WRITEMOSTLY);
479 remove_partitions(tfd);
480 if (update || dv->writemostly > 0) {
481 int rv = -1;
482 tfd = dev_open(dv->devname, O_RDWR);
483 if (tfd < 0) {
484 pr_err("failed to open %s for"
485 " superblock update during re-add\n", dv->devname);
486 return -1;
487 }
488
489 if (dv->writemostly == 1)
490 rv = dev_st->ss->update_super(
491 dev_st, NULL, "writemostly",
492 devname, verbose, 0, NULL);
493 if (dv->writemostly == 2)
494 rv = dev_st->ss->update_super(
495 dev_st, NULL, "readwrite",
496 devname, verbose, 0, NULL);
497 if (update)
498 rv = dev_st->ss->update_super(
499 dev_st, NULL, update,
500 devname, verbose, 0, NULL);
501 if (rv == 0)
502 rv = dev_st->ss->store_super(dev_st, tfd);
503 close(tfd);
504 if (rv != 0) {
505 pr_err("failed to update"
506 " superblock during re-add\n");
507 return -1;
508 }
509 }
510 /* don't even try if disk is marked as faulty */
511 errno = 0;
512 if (ioctl(fd, ADD_NEW_DISK, &disc) == 0) {
513 if (verbose >= 0)
514 pr_err("re-added %s\n", dv->devname);
515 return 1;
516 }
517 if (errno == ENOMEM || errno == EROFS) {
518 pr_err("add new device failed for %s: %s\n",
519 dv->devname, strerror(errno));
520 if (dv->disposition == 'M')
521 return 0;
522 return -1;
523 }
524 }
525skip_re_add:
526 return 0;
527}
528
38aeaf3a
N
529int Manage_add(int fd, int tfd, struct mddev_dev *dv,
530 struct supertype *tst, mdu_array_info_t *array,
531 int force, int verbose, char *devname,
532 char *update, unsigned long rdev, unsigned long long array_size)
533{
534 unsigned long long ldsize;
6d43efb5 535 struct supertype *dev_st = NULL;
38aeaf3a
N
536 int j;
537 mdu_disk_info_t disc;
538
539 if (!get_dev_size(tfd, dv->devname, &ldsize)) {
540 if (dv->disposition == 'M')
541 return 0;
542 else
543 return -1;
544 }
545
546 if (tst->ss->validate_geometry(
547 tst, array->level, array->layout,
548 array->raid_disks, NULL,
af4348dd 549 ldsize >> 9, INVALID_SECTORS, NULL, NULL, 0) == 0) {
38aeaf3a
N
550 if (!force) {
551 pr_err("%s is larger than %s can "
552 "effectively use.\n"
553 " Add --force is you "
554 "really want to add this device.\n",
555 dv->devname, devname);
556 return -1;
557 }
558 pr_err("%s is larger than %s can "
559 "effectively use.\n"
560 " Adding anyway as --force "
561 "was given.\n",
562 dv->devname, devname);
563 }
564 if (!tst->ss->external &&
565 array->major_version == 0 &&
566 md_get_version(fd)%100 < 2) {
567 if (ioctl(fd, HOT_ADD_DISK, rdev)==0) {
568 if (verbose >= 0)
569 pr_err("hot added %s\n",
570 dv->devname);
571 return 1;
572 }
573
574 pr_err("hot add failed for %s: %s\n",
575 dv->devname, strerror(errno));
576 return -1;
577 }
578
579 if (array->not_persistent == 0 || tst->ss->external) {
580
581 /* need to find a sample superblock to copy, and
582 * a spare slot to use.
583 * For 'external' array (well, container based),
584 * We can just load the metadata for the array->
585 */
586 int array_failed;
587 if (tst->sb)
588 /* already loaded */;
589 else if (tst->ss->external) {
590 tst->ss->load_container(tst, fd, NULL);
591 } else for (j = 0; j < tst->max_devs; j++) {
592 char *dev;
593 int dfd;
594 disc.number = j;
595 if (ioctl(fd, GET_DISK_INFO, &disc))
596 continue;
597 if (disc.major==0 && disc.minor==0)
598 continue;
599 if ((disc.state & 4)==0) /* sync */
600 continue;
601 /* Looks like a good device to try */
602 dev = map_dev(disc.major, disc.minor, 1);
603 if (!dev)
604 continue;
605 dfd = dev_open(dev, O_RDONLY);
606 if (dfd < 0)
607 continue;
608 if (tst->ss->load_super(tst, dfd,
609 NULL)) {
610 close(dfd);
611 continue;
612 }
613 close(dfd);
614 break;
615 }
616 /* FIXME this is a bad test to be using */
617 if (!tst->sb && dv->disposition != 'a') {
618 /* we are re-adding a device to a
619 * completely dead array - have to depend
620 * on kernel to check
621 */
622 } else if (!tst->sb) {
623 pr_err("cannot load array metadata from %s\n", devname);
624 return -1;
625 }
626
627 /* Make sure device is large enough */
387fcd59 628 if (tst->ss->avail_size(tst, ldsize/512, INVALID_SECTORS) <
38aeaf3a
N
629 array_size) {
630 if (dv->disposition == 'M')
631 return 0;
632 pr_err("%s not large enough to join array\n",
633 dv->devname);
634 return -1;
635 }
636
637 /* Possibly this device was recently part of
638 * the array and was temporarily removed, and
639 * is now being re-added. If so, we can
640 * simply re-add it.
641 */
642
643 if (array->not_persistent==0) {
644 dev_st = dup_super(tst);
645 dev_st->ss->load_super(dev_st, tfd, NULL);
646 }
647 if (dev_st && dev_st->sb) {
648 int rv = attempt_re_add(fd, tfd, dv,
649 dev_st, tst,
650 rdev,
651 update, devname,
652 verbose,
653 array);
654 dev_st->ss->free_super(dev_st);
655 if (rv)
656 return rv;
657 }
658 if (dv->disposition == 'M') {
659 if (verbose > 0)
660 pr_err("--re-add for %s to %s is not possible\n",
661 dv->devname, devname);
662 return 0;
663 }
664 if (dv->disposition == 'A') {
665 pr_err("--re-add for %s to %s is not possible\n",
666 dv->devname, devname);
667 return -1;
668 }
669 if (array->active_disks < array->raid_disks) {
670 char *avail = xcalloc(array->raid_disks, 1);
671 int d;
672 int found = 0;
673
674 for (d = 0; d < MAX_DISKS && found < array->active_disks; d++) {
675 disc.number = d;
676 if (ioctl(fd, GET_DISK_INFO, &disc))
677 continue;
678 if (disc.major == 0 && disc.minor == 0)
679 continue;
680 if (!(disc.state & (1<<MD_DISK_SYNC)))
681 continue;
682 avail[disc.raid_disk] = 1;
683 found++;
684 }
685 array_failed = !enough(array->level, array->raid_disks,
686 array->layout, 1, avail);
687 } else
688 array_failed = 0;
689 if (array_failed) {
690 pr_err("%s has failed so using --add cannot work and might destroy\n",
691 devname);
692 pr_err("data on %s. You should stop the array and re-assemble it.\n",
693 dv->devname);
694 return -1;
695 }
696 } else {
697 /* non-persistent. Must ensure that new drive
698 * is at least array->size big.
699 */
700 if (ldsize/512 < array_size) {
701 pr_err("%s not large enough to join array\n",
702 dv->devname);
703 return -1;
704 }
705 }
706 /* committed to really trying this device now*/
707 remove_partitions(tfd);
708
709 /* in 2.6.17 and earlier, version-1 superblocks won't
710 * use the number we write, but will choose a free number.
711 * we must choose the same free number, which requires
712 * starting at 'raid_disks' and counting up
713 */
714 for (j = array->raid_disks; j < tst->max_devs; j++) {
715 disc.number = j;
716 if (ioctl(fd, GET_DISK_INFO, &disc))
717 break;
718 if (disc.major==0 && disc.minor==0)
719 break;
720 if (disc.state & 8) /* removed */
721 break;
722 }
723 disc.major = major(rdev);
724 disc.minor = minor(rdev);
725 disc.number =j;
726 disc.state = 0;
727 if (array->not_persistent==0) {
728 int dfd;
729 if (dv->writemostly == 1)
730 disc.state |= 1 << MD_DISK_WRITEMOSTLY;
731 dfd = dev_open(dv->devname, O_RDWR | O_EXCL|O_DIRECT);
732 if (tst->ss->add_to_super(tst, &disc, dfd,
72ca9bcf 733 dv->devname, INVALID_SECTORS))
38aeaf3a
N
734 return -1;
735 if (tst->ss->write_init_super(tst))
736 return -1;
737 } else if (dv->disposition == 'A') {
738 /* this had better be raid1.
739 * As we are "--re-add"ing we must find a spare slot
740 * to fill.
741 */
742 char *used = xcalloc(array->raid_disks, 1);
743 for (j = 0; j < tst->max_devs; j++) {
744 mdu_disk_info_t disc2;
745 disc2.number = j;
746 if (ioctl(fd, GET_DISK_INFO, &disc2))
747 continue;
748 if (disc2.major==0 && disc2.minor==0)
749 continue;
750 if (disc2.state & 8) /* removed */
751 continue;
752 if (disc2.raid_disk < 0)
753 continue;
754 if (disc2.raid_disk > array->raid_disks)
755 continue;
756 used[disc2.raid_disk] = 1;
757 }
758 for (j = 0 ; j < array->raid_disks; j++)
759 if (!used[j]) {
760 disc.raid_disk = j;
761 disc.state |= (1<<MD_DISK_SYNC);
762 break;
763 }
764 free(used);
765 }
766 if (dv->writemostly == 1)
767 disc.state |= (1 << MD_DISK_WRITEMOSTLY);
768 if (tst->ss->external) {
769 /* add a disk
770 * to an external metadata container */
771 struct mdinfo new_mdi;
772 struct mdinfo *sra;
773 int container_fd;
4dd2df09 774 char devnm[32];
38aeaf3a
N
775 int dfd;
776
4dd2df09
N
777 strcpy(devnm, fd2devnm(fd));
778
779 container_fd = open_dev_excl(devnm);
38aeaf3a
N
780 if (container_fd < 0) {
781 pr_err("add failed for %s:"
782 " could not get exclusive access to container\n",
783 dv->devname);
784 tst->ss->free_super(tst);
785 return -1;
786 }
787
9cf9a1de 788 Kill(dv->devname, NULL, 0, -1, 0);
38aeaf3a 789 dfd = dev_open(dv->devname, O_RDWR | O_EXCL|O_DIRECT);
4dd2df09 790 if (mdmon_running(tst->container_devnm))
38aeaf3a
N
791 tst->update_tail = &tst->updates;
792 if (tst->ss->add_to_super(tst, &disc, dfd,
72ca9bcf 793 dv->devname, INVALID_SECTORS)) {
38aeaf3a
N
794 close(dfd);
795 close(container_fd);
796 return -1;
797 }
798 if (tst->update_tail)
799 flush_metadata_updates(tst);
800 else
801 tst->ss->sync_metadata(tst);
802
4dd2df09 803 sra = sysfs_read(container_fd, NULL, 0);
38aeaf3a
N
804 if (!sra) {
805 pr_err("add failed for %s: sysfs_read failed\n",
806 dv->devname);
807 close(container_fd);
808 tst->ss->free_super(tst);
809 return -1;
810 }
811 sra->array.level = LEVEL_CONTAINER;
812 /* Need to set data_offset and component_size */
813 tst->ss->getinfo_super(tst, &new_mdi, NULL);
814 new_mdi.disk.major = disc.major;
815 new_mdi.disk.minor = disc.minor;
816 new_mdi.recovery_start = 0;
817 /* Make sure fds are closed as they are O_EXCL which
818 * would block add_disk */
819 tst->ss->free_super(tst);
820 if (sysfs_add_disk(sra, &new_mdi, 0) != 0) {
821 pr_err("add new device to external metadata"
822 " failed for %s\n", dv->devname);
823 close(container_fd);
824 sysfs_free(sra);
825 return -1;
826 }
4dd2df09 827 ping_monitor(devnm);
38aeaf3a
N
828 sysfs_free(sra);
829 close(container_fd);
830 } else {
831 tst->ss->free_super(tst);
832 if (ioctl(fd, ADD_NEW_DISK, &disc)) {
833 pr_err("add new device failed for %s as %d: %s\n",
834 dv->devname, j, strerror(errno));
835 return -1;
836 }
837 }
838 if (verbose >= 0)
839 pr_err("added %s\n", dv->devname);
840 return 1;
841}
842
d070235d
N
843int Manage_remove(struct supertype *tst, int fd, struct mddev_dev *dv,
844 int sysfd, unsigned long rdev, int verbose, char *devname)
845{
846 int lfd = -1;
847 int err;
848
849 if (tst->ss->external) {
850 /* To remove a device from a container, we must
851 * check that it isn't in use in an array.
852 * This involves looking in the 'holders'
853 * directory - there must be just one entry,
854 * the container.
855 * To ensure that it doesn't get used as a
856 * hot spare while we are checking, we
857 * get an O_EXCL open on the container
858 */
aab15415 859 int ret;
4dd2df09
N
860 char devnm[32];
861 strcpy(devnm, fd2devnm(fd));
862 lfd = open_dev_excl(devnm);
d070235d
N
863 if (lfd < 0) {
864 pr_err("Cannot get exclusive access "
865 " to container - odd\n");
866 return -1;
867 }
aab15415
N
868 /* We may not be able to check on holders in
869 * sysfs, either because we don't have the dev num
870 * (rdev == 0) or because the device has been detached
871 * and the 'holders' directory no longer exists
872 * (ret == -1). In that case, assume it is OK to
873 * remove.
d070235d 874 */
aab15415
N
875 if (rdev == 0)
876 ret = -1;
877 else
4dd2df09 878 ret = sysfs_unique_holder(devnm, rdev);
aab15415
N
879 if (ret == 0) {
880 pr_err("%s is not a member, cannot remove.\n",
881 dv->devname);
882 close(lfd);
883 return -1;
884 }
885 if (ret >= 2) {
886 pr_err("%s is still in use, cannot remove.\n",
887 dv->devname);
d070235d
N
888 close(lfd);
889 return -1;
890 }
891 }
892 /* FIXME check that it is a current member */
893 if (sysfd >= 0) {
894 /* device has been removed and we don't know
895 * the major:minor number
896 */
897 int n = write(sysfd, "remove", 6);
898 if (n != 6)
899 err = -1;
900 else
901 err = 0;
902 } else {
903 err = ioctl(fd, HOT_REMOVE_DISK, rdev);
904 if (err && errno == ENODEV) {
905 /* Old kernels rejected this if no personality
906 * is registered */
4dd2df09 907 struct mdinfo *sra = sysfs_read(fd, NULL, GET_DEVS);
d070235d
N
908 struct mdinfo *dv = NULL;
909 if (sra)
910 dv = sra->devs;
911 for ( ; dv ; dv=dv->next)
912 if (dv->disk.major == (int)major(rdev) &&
913 dv->disk.minor == (int)minor(rdev))
914 break;
915 if (dv)
916 err = sysfs_set_str(sra, dv,
917 "state", "remove");
918 else
919 err = -1;
920 if (sra)
921 sysfs_free(sra);
922 }
923 }
924 if (err) {
925 pr_err("hot remove failed "
926 "for %s: %s\n", dv->devname,
927 strerror(errno));
928 if (lfd >= 0)
929 close(lfd);
930 return -1;
931 }
932 if (tst->ss->external) {
933 /*
934 * Before dropping our exclusive open we make an
935 * attempt at preventing mdmon from seeing an
936 * 'add' event before reconciling this 'remove'
937 * event.
938 */
4dd2df09 939 char *devnm = fd2devnm(fd);
d070235d 940
4dd2df09 941 if (!devnm) {
d070235d
N
942 pr_err("unable to get container name\n");
943 return -1;
944 }
945
4dd2df09 946 ping_manager(devnm);
d070235d
N
947 }
948 if (lfd >= 0)
949 close(lfd);
950 if (verbose >= 0)
951 pr_err("hot removed %s from %s\n",
952 dv->devname, devname);
953 return 1;
954}
955
70c55e36
N
956int Manage_replace(struct supertype *tst, int fd, struct mddev_dev *dv,
957 unsigned long rdev, int verbose, char *devname)
958{
959 struct mdinfo *mdi, *di;
960 if (tst->ss->external) {
961 pr_err("--replace only supported for native metadata (0.90 or 1.x)\n");
962 return -1;
963 }
964 /* Need to find the device in sysfs and add 'want_replacement' to the
965 * status.
966 */
4dd2df09 967 mdi = sysfs_read(fd, NULL, GET_DEVS);
70c55e36
N
968 if (!mdi || !mdi->devs) {
969 pr_err("Cannot find status of %s to enable replacement - strange\n",
970 devname);
971 return -1;
972 }
973 for (di = mdi->devs; di; di = di->next)
974 if (di->disk.major == (int)major(rdev) &&
975 di->disk.minor == (int)minor(rdev))
976 break;
977 if (di) {
978 int rv;
979 if (di->disk.raid_disk < 0) {
980 pr_err("%s is not active and so cannot be replaced.\n",
981 dv->devname);
982 sysfs_free(mdi);
983 return -1;
984 }
985 rv = sysfs_set_str(mdi, di,
986 "state", "want_replacement");
987 if (rv) {
988 sysfs_free(mdi);
989 pr_err("Failed to request replacement for %s\n",
990 dv->devname);
991 return -1;
992 }
993 if (verbose >= 0)
994 pr_err("Marked %s (device %d in %s) for replacement\n",
995 dv->devname, di->disk.raid_disk, devname);
996 /* If there is a matching 'with', we need to tell it which
997 * raid disk
998 */
999 while (dv && dv->disposition != 'W')
1000 dv = dv->next;
1001 if (dv) {
1002 dv->disposition = 'w';
1003 dv->used = di->disk.raid_disk;
1004 }
1005 return 1;
1006 }
1007 sysfs_free(mdi);
1008 pr_err("%s not found in %s so cannot --replace it\n",
1009 dv->devname, devname);
1010 return -1;
1011}
1012
1013int Manage_with(struct supertype *tst, int fd, struct mddev_dev *dv,
1014 unsigned long rdev, int verbose, char *devname)
1015{
1016 struct mdinfo *mdi, *di;
1017 /* try to set 'slot' for 'rdev' in 'fd' to 'dv->used' */
4dd2df09 1018 mdi = sysfs_read(fd, NULL, GET_DEVS|GET_STATE);
70c55e36
N
1019 if (!mdi || !mdi->devs) {
1020 pr_err("Cannot find status of %s to enable replacement - strange\n",
1021 devname);
1022 return -1;
1023 }
1024 for (di = mdi->devs; di; di = di->next)
1025 if (di->disk.major == (int)major(rdev) &&
1026 di->disk.minor == (int)minor(rdev))
1027 break;
1028 if (di) {
1029 int rv;
1030 if (di->disk.state & (1<<MD_DISK_FAULTY)) {
1031 pr_err("%s is faulty and cannot be a replacement\n",
1032 dv->devname);
1033 sysfs_free(mdi);
1034 return -1;
1035 }
1036 if (di->disk.raid_disk >= 0) {
1037 pr_err("%s is active and cannot be a replacement\n",
1038 dv->devname);
1039 sysfs_free(mdi);
1040 return -1;
1041 }
1042 rv = sysfs_set_num(mdi, di,
1043 "slot", dv->used);
1044 if (rv) {
1045 sysfs_free(mdi);
1046 pr_err("Failed to %s as preferred replacement.\n",
1047 dv->devname);
1048 return -1;
1049 }
1050 if (verbose >= 0)
1051 pr_err("Marked %s in %s as replacement for device %d\n",
1052 dv->devname, devname, dv->used);
1053 return 1;
1054 }
1055 sysfs_free(mdi);
1056 pr_err("%s not found in %s so cannot make it preferred replacement\n",
1057 dv->devname, devname);
1058 return -1;
1059}
1060
64c4757e 1061int Manage_subdevs(char *devname, int fd,
833bb0f8 1062 struct mddev_dev *devlist, int verbose, int test,
11b391ec 1063 char *update, int force)
cd29a5c8 1064{
7bd04da9 1065 /* Do something to each dev.
682c7051
NB
1066 * devmode can be
1067 * 'a' - add the device
1068 * try HOT_ADD_DISK
1069 * If that fails EINVAL, try ADD_NEW_DISK
7bd04da9
N
1070 * 'A' - re-add the device
1071 * 'r' - remove the device: HOT_REMOVE_DISK
b80da661
NB
1072 * device can be 'faulty' or 'detached' in which case all
1073 * matching devices are removed.
682c7051 1074 * 'f' - set the device faulty SET_DISK_FAULTY
b80da661
NB
1075 * device can be 'detached' in which case any device that
1076 * is inaccessible will be marked faulty.
70c55e36
N
1077 * 'R' - mark this device as wanting replacement.
1078 * 'W' - this device is added if necessary and activated as
1079 * a replacement for a previous 'R' device.
1080 * -----
1081 * 'w' - 'W' will be changed to 'w' when it is paired with
1082 * a 'R' device. If a 'W' is found while walking the list
1083 * it must be unpaired, and is an error.
1084 * 'M' - this is created by a 'missing' target. It is a slight
1085 * variant on 'A'
262e3b7f
N
1086 * 'F' - Another variant of 'A', where the device was faulty
1087 * so must be removed from the array first.
70c55e36 1088 *
98d27e39
N
1089 * For 'f' and 'r', the device can also be a kernel-internal
1090 * name such as 'sdb'.
682c7051
NB
1091 */
1092 mdu_array_info_t array;
7a3be72f 1093 unsigned long long array_size;
1d997643 1094 struct mddev_dev *dv;
682c7051 1095 struct stat stb;
cfad27a9 1096 int tfd = -1;
38aeaf3a 1097 struct supertype *tst;
4725bc31 1098 char *subarray = NULL;
98d27e39 1099 int sysfd = -1;
7d2e6486 1100 int count = 0; /* number of actions taken */
9f584691
N
1101 struct mdinfo info;
1102 int frozen = 0;
682c7051
NB
1103
1104 if (ioctl(fd, GET_ARRAY_INFO, &array)) {
7bd04da9 1105 pr_err("Cannot get array info for %s\n",
682c7051 1106 devname);
bcbb3112 1107 goto abort;
682c7051 1108 }
4dd2df09 1109 sysfs_init(&info, fd, NULL);
3da92f27 1110
7bd04da9 1111 /* array.size is only 32 bits and may be truncated.
7a3be72f
NB
1112 * So read from sysfs if possible, and record number of sectors
1113 */
1114
1115 array_size = get_component_size(fd);
1116 if (array_size <= 0)
1117 array_size = array.size * 2;
1118
4725bc31 1119 tst = super_by_fd(fd, &subarray);
3da92f27 1120 if (!tst) {
e7b84f9d 1121 pr_err("unsupport array - version %d.%d\n",
3da92f27 1122 array.major_version, array.minor_version);
bcbb3112 1123 goto abort;
3da92f27
NB
1124 }
1125
b3b4e8a7 1126 stb.st_rdev = 0;
38aeaf3a 1127 for (dv = devlist; dv; dv = dv->next) {
38aeaf3a 1128 int rv;
4a39c6f2 1129
1d997643
N
1130 if (strcmp(dv->devname, "failed") == 0 ||
1131 strcmp(dv->devname, "faulty") == 0) {
262e3b7f
N
1132 if (dv->disposition != 'A'
1133 && dv->disposition != 'r') {
e7b84f9d 1134 pr_err("%s only meaningful "
262e3b7f 1135 "with -r or --re-add, not -%c\n",
b80da661 1136 dv->devname, dv->disposition);
bcbb3112 1137 goto abort;
b80da661 1138 }
262e3b7f
N
1139 add_faulty(dv, fd, (dv->disposition == 'A'
1140 ? 'F' : 'r'));
1d997643
N
1141 continue;
1142 }
1143 if (strcmp(dv->devname, "detached") == 0) {
b80da661 1144 if (dv->disposition != 'r' && dv->disposition != 'f') {
e7b84f9d 1145 pr_err("%s only meaningful "
b80da661
NB
1146 "with -r of -f, not -%c\n",
1147 dv->devname, dv->disposition);
bcbb3112 1148 goto abort;
b80da661 1149 }
1d997643
N
1150 add_detached(dv, fd, dv->disposition);
1151 continue;
1152 }
1153
1154 if (strcmp(dv->devname, "missing") == 0) {
1155 struct mddev_dev *add_devlist = NULL;
1156 struct mddev_dev **dp;
c8e1a230 1157 if (dv->disposition != 'A') {
e7b84f9d 1158 pr_err("'missing' only meaningful "
aab15415 1159 "with --re-add\n");
bcbb3112 1160 goto abort;
a4e13010 1161 }
1d997643 1162 add_devlist = conf_get_devs();
a4e13010 1163 if (add_devlist == NULL) {
e7b84f9d 1164 pr_err("no devices to scan for missing members.");
a4e13010
N
1165 continue;
1166 }
1d997643 1167 for (dp = &add_devlist; *dp; dp = & (*dp)->next)
7bd04da9 1168 /* 'M' (for 'missing') is like 'A' without errors */
1d997643
N
1169 (*dp)->disposition = 'M';
1170 *dp = dv->next;
1171 dv->next = add_devlist;
1172 continue;
1173 }
1174
1175 if (strchr(dv->devname, '/') == NULL &&
aab15415
N
1176 strchr(dv->devname, ':') == NULL &&
1177 strlen(dv->devname) < 50) {
98d27e39
N
1178 /* Assume this is a kernel-internal name like 'sda1' */
1179 int found = 0;
1180 char dname[55];
1181 if (dv->disposition != 'r' && dv->disposition != 'f') {
e7b84f9d 1182 pr_err("%s only meaningful "
cfad27a9 1183 "with -r or -f, not -%c\n",
98d27e39 1184 dv->devname, dv->disposition);
bcbb3112 1185 goto abort;
98d27e39
N
1186 }
1187
1188 sprintf(dname, "dev-%s", dv->devname);
4dd2df09 1189 sysfd = sysfs_open(fd2devnm(fd), dname, "block/dev");
98d27e39
N
1190 if (sysfd >= 0) {
1191 char dn[20];
1192 int mj,mn;
1193 if (sysfs_fd_get_str(sysfd, dn, 20) > 0 &&
1194 sscanf(dn, "%d:%d", &mj,&mn) == 2) {
1195 stb.st_rdev = makedev(mj,mn);
1196 found = 1;
1197 }
1198 close(sysfd);
1199 sysfd = -1;
1200 }
1201 if (!found) {
4dd2df09 1202 sysfd = sysfs_open(fd2devnm(fd), dname, "state");
98d27e39 1203 if (sysfd < 0) {
e7b84f9d 1204 pr_err("%s does not appear "
98d27e39
N
1205 "to be a component of %s\n",
1206 dv->devname, devname);
bcbb3112 1207 goto abort;
98d27e39
N
1208 }
1209 }
b80da661 1210 } else {
c7b47447 1211 tfd = dev_open(dv->devname, O_RDONLY);
5fe7f5f7
N
1212 if (tfd >= 0)
1213 fstat(tfd, &stb);
5a9de8db 1214 else {
5fe7f5f7
N
1215 int open_err = errno;
1216 if (stat(dv->devname, &stb) != 0) {
1217 pr_err("Cannot find %s: %s\n",
1218 dv->devname, strerror(errno));
1219 goto abort;
1220 }
1221 if ((stb.st_mode & S_IFMT) != S_IFBLK) {
1222 if (dv->disposition == 'M')
1223 /* non-fatal. Also improbable */
1224 continue;
1225 pr_err("%s is not a block device.\n",
1226 dv->devname);
1227 goto abort;
1228 }
1229 if (dv->disposition == 'r')
1230 /* Be happy, the stat worked, that is
1231 * enough for --remove
1232 */
1233 ;
1234 else {
1d997643
N
1235 if (dv->disposition == 'M')
1236 /* non-fatal */
1237 continue;
839f27a3 1238 pr_err("Cannot open %s: %s\n",
5fe7f5f7 1239 dv->devname, strerror(open_err));
bcbb3112 1240 goto abort;
5a9de8db 1241 }
b80da661 1242 }
682c7051 1243 }
cd29a5c8 1244 switch(dv->disposition){
682c7051 1245 default:
e7b84f9d 1246 pr_err("internal error - devmode[%s]=%d\n",
c913b90e 1247 dv->devname, dv->disposition);
bcbb3112 1248 goto abort;
682c7051 1249 case 'a':
c8e1a230 1250 case 'A':
262e3b7f
N
1251 case 'M': /* --re-add missing */
1252 case 'F': /* --re-add faulty */
4a39c6f2 1253 /* add the device */
4725bc31 1254 if (subarray) {
e7b84f9d 1255 pr_err("Cannot add disks to a"
f7dd881f
DW
1256 " \'member\' array, perform this"
1257 " operation on the parent container\n");
bcbb3112 1258 goto abort;
f94d52f4 1259 }
262e3b7f
N
1260 if (dv->disposition == 'F')
1261 /* Need to remove first */
1262 ioctl(fd, HOT_REMOVE_DISK,
1263 (unsigned long)stb.st_rdev);
f277ce36 1264 /* Make sure it isn't in use (in 2.6 or later) */
1d997643 1265 tfd = dev_open(dv->devname, O_RDONLY|O_EXCL);
38aeaf3a
N
1266 if (tfd >= 0) {
1267 /* We know no-one else is using it. We'll
1268 * need non-exclusive access to add it, so
1269 * do that now.
1270 */
1271 close(tfd);
1272 tfd = dev_open(dv->devname, O_RDONLY);
1273 }
0fbf459d 1274 if (tfd < 0) {
1d997643
N
1275 if (dv->disposition == 'M')
1276 continue;
e7b84f9d 1277 pr_err("Cannot open %s: %s\n",
d7eaf49f 1278 dv->devname, strerror(errno));
bcbb3112 1279 goto abort;
d7eaf49f 1280 }
9f584691
N
1281 if (!frozen) {
1282 if (sysfs_freeze_array(&info) == 1)
1283 frozen = 1;
1284 else
1285 frozen = -1;
1286 }
38aeaf3a
N
1287 rv = Manage_add(fd, tfd, dv, tst, &array,
1288 force, verbose, devname, update,
1289 stb.st_rdev, array_size);
1290 close(tfd);
1291 tfd = -1;
1292 if (rv < 0)
bcbb3112 1293 goto abort;
38aeaf3a
N
1294 if (rv > 0)
1295 count++;
682c7051
NB
1296 break;
1297
1298 case 'r':
1299 /* hot remove */
4725bc31 1300 if (subarray) {
e7b84f9d 1301 pr_err("Cannot remove disks from a"
f7dd881f
DW
1302 " \'member\' array, perform this"
1303 " operation on the parent container\n");
d070235d
N
1304 rv = -1;
1305 } else
1306 rv = Manage_remove(tst, fd, dv, sysfd,
1307 stb.st_rdev, verbose,
1308 devname);
1309 if (sysfd >= 0)
98d27e39 1310 close(sysfd);
d070235d
N
1311 sysfd = -1;
1312 if (rv < 0)
bcbb3112 1313 goto abort;
d070235d
N
1314 if (rv > 0)
1315 count++;
682c7051
NB
1316 break;
1317
1318 case 'f': /* set faulty */
1319 /* FIXME check current member */
98d27e39
N
1320 if ((sysfd >= 0 && write(sysfd, "faulty", 6) != 6) ||
1321 (sysfd < 0 && ioctl(fd, SET_DISK_FAULTY,
1322 (unsigned long) stb.st_rdev))) {
e7b84f9d 1323 pr_err("set device faulty failed for %s: %s\n",
1d997643 1324 dv->devname, strerror(errno));
98d27e39
N
1325 if (sysfd >= 0)
1326 close(sysfd);
bcbb3112 1327 goto abort;
682c7051 1328 }
98d27e39
N
1329 if (sysfd >= 0)
1330 close(sysfd);
1331 sysfd = -1;
7d2e6486 1332 count++;
dab6685f 1333 if (verbose >= 0)
e7b84f9d 1334 pr_err("set %s faulty in %s\n",
1d997643 1335 dv->devname, devname);
682c7051 1336 break;
70c55e36
N
1337 case 'R': /* Mark as replaceable */
1338 if (subarray) {
1339 pr_err("Cannot replace disks in a"
1340 " \'member\' array, perform this"
1341 " operation on the parent container\n");
1342 rv = -1;
1343 } else {
1344 if (!frozen) {
1345 if (sysfs_freeze_array(&info) == 1)
1346 frozen = 1;
1347 else
1348 frozen = -1;
1349 }
1350 rv = Manage_replace(tst, fd, dv,
1351 stb.st_rdev, verbose,
1352 devname);
1353 }
1354 if (rv < 0)
1355 goto abort;
1356 if (rv > 0)
1357 count++;
1358 break;
1359 case 'W': /* --with device that doesn't match */
1360 pr_err("No matching --replace device for --with %s\n",
1361 dv->devname);
1362 goto abort;
1363 case 'w': /* --with device which was matched */
1364 rv = Manage_with(tst, fd, dv,
1365 stb.st_rdev, verbose, devname);
1366 if (rv < 0)
1367 goto abort;
1368 break;
682c7051
NB
1369 }
1370 }
9f584691
N
1371 if (frozen > 0)
1372 sysfs_set_str(&info, NULL, "sync_action","idle");
7d2e6486
N
1373 if (test && count == 0)
1374 return 2;
682c7051 1375 return 0;
bcbb3112
N
1376
1377abort:
9f584691
N
1378 if (frozen > 0)
1379 sysfs_set_str(&info, NULL, "sync_action","idle");
bcbb3112 1380 return 1;
64c4757e 1381}
1f48664b
NB
1382
1383int autodetect(void)
1384{
1385 /* Open any md device, and issue the RAID_AUTORUN ioctl */
1386 int rv = 1;
1387 int fd = dev_open("9:0", O_RDONLY);
1388 if (fd >= 0) {
1389 if (ioctl(fd, RAID_AUTORUN, 0) == 0)
1390 rv = 0;
1391 close(fd);
1392 }
1393 return rv;
1394}
aa534678 1395
ba728be7 1396int Update_subarray(char *dev, char *subarray, char *update, struct mddev_ident *ident, int verbose)
aa534678
DW
1397{
1398 struct supertype supertype, *st = &supertype;
1399 int fd, rv = 2;
1400
1401 memset(st, 0, sizeof(*st));
aa534678 1402
ba728be7 1403 fd = open_subarray(dev, subarray, st, verbose < 0);
aa534678
DW
1404 if (fd < 0)
1405 return 2;
1406
1407 if (!st->ss->update_subarray) {
ba728be7 1408 if (verbose >= 0)
e7b84f9d
N
1409 pr_err("Operation not supported for %s metadata\n",
1410 st->ss->name);
aa534678
DW
1411 goto free_super;
1412 }
1413
4dd2df09 1414 if (mdmon_running(st->devnm))
aa534678
DW
1415 st->update_tail = &st->updates;
1416
a951a4f7 1417 rv = st->ss->update_subarray(st, subarray, update, ident);
aa534678
DW
1418
1419 if (rv) {
ba728be7 1420 if (verbose >= 0)
e7b84f9d 1421 pr_err("Failed to update %s of subarray-%s in %s\n",
aa534678
DW
1422 update, subarray, dev);
1423 } else if (st->update_tail)
1424 flush_metadata_updates(st);
1425 else
1426 st->ss->sync_metadata(st);
1427
ba728be7 1428 if (rv == 0 && strcmp(update, "name") == 0 && verbose >= 0)
e7b84f9d
N
1429 pr_err("Updated subarray-%s name from %s, UUIDs may have changed\n",
1430 subarray, dev);
aa534678
DW
1431
1432 free_super:
1433 st->ss->free_super(st);
1434 close(fd);
1435
1436 return rv;
1437}
d52bb542 1438
7bd04da9
N
1439/* Move spare from one array to another If adding to destination array fails
1440 * add back to original array.
d52bb542
AC
1441 * Returns 1 on success, 0 on failure */
1442int move_spare(char *from_devname, char *to_devname, dev_t devid)
1443{
1444 struct mddev_dev devlist;
1445 char devname[20];
1446
1447 /* try to remove and add */
1448 int fd1 = open(to_devname, O_RDONLY);
1449 int fd2 = open(from_devname, O_RDONLY);
1450
1451 if (fd1 < 0 || fd2 < 0) {
1452 if (fd1>=0) close(fd1);
1453 if (fd2>=0) close(fd2);
1454 return 0;
1455 }
1456
1457 devlist.next = NULL;
1458 devlist.used = 0;
d52bb542
AC
1459 devlist.writemostly = 0;
1460 devlist.devname = devname;
1461 sprintf(devname, "%d:%d", major(devid), minor(devid));
1462
1463 devlist.disposition = 'r';
11b391ec 1464 if (Manage_subdevs(from_devname, fd2, &devlist, -1, 0, NULL, 0) == 0) {
d52bb542 1465 devlist.disposition = 'a';
11b391ec 1466 if (Manage_subdevs(to_devname, fd1, &devlist, -1, 0, NULL, 0) == 0) {
d52bb542
AC
1467 /* make sure manager is aware of changes */
1468 ping_manager(to_devname);
1469 ping_manager(from_devname);
1470 close(fd1);
1471 close(fd2);
1472 return 1;
1473 }
11b391ec 1474 else Manage_subdevs(from_devname, fd2, &devlist, -1, 0, NULL, 0);
d52bb542
AC
1475 }
1476 close(fd1);
1477 close(fd2);
1478 return 0;
1479}
435d4ebb 1480#endif