]> git.ipfire.org Git - thirdparty/mdadm.git/blame - Manage.c
Fix default size calculations that were recently broken.
[thirdparty/mdadm.git] / Manage.c
CommitLineData
64c4757e 1/*
9a9dab36 2 * mdadm - manage Linux "md" devices aka RAID arrays.
64c4757e 3 *
e736b623 4 * Copyright (C) 2001-2009 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
e9dd1598
N
54 /* If this is an externally-manage array, we need to modify the
55 * metadata_version so that mdmon doesn't undo our change.
56 */
57 mdi = sysfs_read(fd, -1, GET_LEVEL|GET_VERSION);
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
682c7051
NB
105 if (readonly>0) {
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
4ccad7b1
N
130static void remove_devices(int devnum, char *path)
131{
b1702f48
N
132 /*
133 * Remove names at 'path' - possibly with
134 * partition suffixes - which link to the 'standard'
135 * name for devnum. These were probably created
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
4ccad7b1
N
149 if (devnum >= 0)
150 sprintf(base, "/dev/md%d", devnum);
151 else
152 sprintf(base, "/dev/md_d%d", -1-devnum);
153 be = base + strlen(base);
b1702f48 154
503975b9 155 path2 = xmalloc(strlen(path)+20);
b1702f48
N
156 strcpy(path2, path);
157 pe = path2 + strlen(path2);
4ccad7b1
N
158
159 for (part = 0; part < 16; part++) {
160 if (part) {
161 sprintf(be, "p%d", part);
b1702f48
N
162
163 if (isdigit(pe[-1]))
164 sprintf(pe, "p%d", part);
165 else
166 sprintf(pe, "%d", part);
4ccad7b1 167 }
b1702f48 168 n = readlink(path2, link, sizeof(link));
d9ca03e9 169 if (n > 0 && (int)strlen(base) == n &&
b1702f48
N
170 strncmp(link, base, n) == 0)
171 unlink(path2);
4ccad7b1 172 }
0eb26465 173 free(path2);
4ccad7b1
N
174}
175
176
ba728be7
N
177int Manage_runstop(char *devname, int fd, int runstop,
178 int verbose, int will_retry)
64c4757e 179{
682c7051 180 /* Run or stop the array. array must already be configured
ba728be7
N
181 * 'Run' requires >= 0.90.0
182 * 'will_retry' is only relevant for 'stop', and means
183 * that error messages are not wanted.
682c7051 184 */
682c7051 185 mdu_param_t param; /* unused */
bccd8153 186 int rv = 0;
82b27616 187
ba728be7
N
188 if (will_retry && verbose == 0)
189 verbose = -1;
190
82b27616
NB
191 if (runstop == -1 && md_get_version(fd) < 9000) {
192 if (ioctl(fd, STOP_MD, 0)) {
e7b84f9d
N
193 pr_err("stopping device %s "
194 "failed: %s\n",
195 devname, strerror(errno));
82b27616
NB
196 return 1;
197 }
198 }
aba69144 199
682c7051 200 if (md_get_version(fd) < 9000) {
e7b84f9d 201 pr_err("need md driver version 0.90.0 or later\n");
682c7051
NB
202 return 1;
203 }
ba728be7 204
682c7051
NB
205 if (runstop>0) {
206 if (ioctl(fd, RUN_ARRAY, &param)) {
ba728be7
N
207 if (verbose >= 0)
208 pr_err("failed to run array %s: %s\n",
209 devname, strerror(errno));
682c7051
NB
210 return 1;
211 }
ba728be7 212 if (verbose >= 0)
e7b84f9d 213 pr_err("started %s\n", devname);
682c7051 214 } else if (runstop < 0){
8382f19b
NB
215 struct map_ent *map = NULL;
216 struct stat stb;
daf7a3ce 217 struct mdinfo *mdi;
4ccad7b1 218 int devnum;
eb0af526
N
219 int err;
220 int count;
daf7a3ce
NB
221 /* If this is an mdmon managed array, just write 'inactive'
222 * to the array state and let mdmon clear up.
223 */
4ccad7b1 224 devnum = fd2devnum(fd);
eb0af526
N
225 /* Get EXCL access first. If this fails, then attempting
226 * to stop is probably a bad idea.
227 */
228 close(fd);
229 fd = open(devname, O_RDONLY|O_EXCL);
230 if (fd < 0 || fd2devnum(fd) != devnum) {
231 if (fd >= 0)
232 close(fd);
ba728be7
N
233 if (verbose >= 0)
234 pr_err("Cannot get exclusive access to %s:"
235 "Perhaps a running "
236 "process, mounted filesystem "
237 "or active volume group?\n",
238 devname);
eb0af526
N
239 return 1;
240 }
daf7a3ce
NB
241 mdi = sysfs_read(fd, -1, GET_LEVEL|GET_VERSION);
242 if (mdi &&
243 mdi->array.level > 0 &&
3c558363 244 is_subarray(mdi->text_version)) {
1ae42d9d 245 int err;
daf7a3ce
NB
246 /* This is mdmon managed. */
247 close(fd);
1ae42d9d
KW
248
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
eb0af526
N
269 fd = open_dev_excl(devnum);
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);
293 for (m=mds; m; m=m->next)
294 if (m->metadata_version &&
295 strncmp(m->metadata_version, "external:", 9)==0 &&
296 is_subarray(m->metadata_version+9) &&
297 devname2devnum(m->metadata_version+10) == devnum) {
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
4ccad7b1
N
340
341 if (devnum != NoMdDev &&
342 (stat("/dev/.udev", &stb) != 0 ||
343 check_env("MDADM_NO_UDEV"))) {
344 struct map_ent *mp = map_by_devnum(&map, devnum);
345 remove_devices(devnum, mp ? mp->path : NULL);
346 }
347
348
ba728be7 349 if (verbose >= 0)
e7b84f9d 350 pr_err("stopped %s\n", devname);
4eb26970
DW
351 map_lock(&map);
352 map_remove(&map, devnum);
353 map_unlock(&map);
bccd8153
JS
354 out:
355 if (mdi)
356 sysfs_free(mdi);
682c7051 357 }
bccd8153 358 return rv;
64c4757e
NB
359}
360
dd0781e5
NB
361int Manage_resize(char *devname, int fd, long long size, int raid_disks)
362{
363 mdu_array_info_t info;
364 if (ioctl(fd, GET_ARRAY_INFO, &info) != 0) {
e7b84f9d 365 pr_err("Cannot get array information for %s: %s\n",
dd0781e5
NB
366 devname, strerror(errno));
367 return 1;
368 }
369 if (size >= 0)
370 info.size = size;
371 if (raid_disks > 0)
372 info.raid_disks = raid_disks;
373 if (ioctl(fd, SET_ARRAY_INFO, &info) != 0) {
e7b84f9d 374 pr_err("Cannot set device size/shape for %s: %s\n",
dd0781e5
NB
375 devname, strerror(errno));
376 return 1;
377 }
378 return 0;
b5e64645 379}
dd0781e5 380
1d997643
N
381static void add_faulty(struct mddev_dev *dv, int fd, char disp)
382{
383 mdu_array_info_t array;
384 mdu_disk_info_t disk;
385 int remaining_disks;
386 int i;
387
388 if (ioctl(fd, GET_ARRAY_INFO, &array) != 0)
389 return;
390
391 remaining_disks = array.nr_disks;
392 for (i = 0; i < MAX_DISKS && remaining_disks > 0; i++) {
393 struct mddev_dev *new;
394 char buf[40];
395 disk.number = i;
396 if (ioctl(fd, GET_DISK_INFO, &disk) != 0)
397 continue;
398 if (disk.major == 0 && disk.minor == 0)
399 continue;
400 remaining_disks--;
401 if ((disk.state & 1) == 0) /* not faulty */
402 continue;
403 sprintf(buf, "%d:%d", disk.major, disk.minor);
404 new = xmalloc(sizeof(*new));
405 new->devname = xstrdup(buf);
406 new->disposition = disp;
407 new->next = dv->next;
408 dv->next = new;
409 dv = new;
410 }
411}
412
413static void add_detached(struct mddev_dev *dv, int fd, char disp)
414{
415 mdu_array_info_t array;
416 mdu_disk_info_t disk;
417 int remaining_disks;
418 int i;
419
420 if (ioctl(fd, GET_ARRAY_INFO, &array) != 0)
421 return;
422
423 remaining_disks = array.nr_disks;
424 for (i = 0; i < MAX_DISKS && remaining_disks > 0; i++) {
425 struct mddev_dev *new;
426 char buf[40];
427 int sfd;
428 disk.number = i;
429 if (ioctl(fd, GET_DISK_INFO, &disk) != 0)
430 continue;
431 if (disk.major == 0 && disk.minor == 0)
432 continue;
433 remaining_disks--;
434 if (disp == 'f' && (disk.state & 1) != 0) /* already faulty */
435 continue;
436 sprintf(buf, "%d:%d", disk.major, disk.minor);
437 sfd = dev_open(buf, O_RDONLY);
438 if (sfd >= 0) {
439 /* Not detached */
440 close(sfd);
441 continue;
442 }
443 if (errno != ENXIO)
444 /* Probably not detached */
445 continue;
446 new = xmalloc(sizeof(*new));
447 new->devname = xstrdup(buf);
448 new->disposition = disp;
449 new->next = dv->next;
450 dv->next = new;
451 dv = new;
452 }
453}
454
64c4757e 455int Manage_subdevs(char *devname, int fd,
833bb0f8 456 struct mddev_dev *devlist, int verbose, int test,
11b391ec 457 char *update, int force)
cd29a5c8 458{
682c7051
NB
459 /* do something to each dev.
460 * devmode can be
461 * 'a' - add the device
462 * try HOT_ADD_DISK
463 * If that fails EINVAL, try ADD_NEW_DISK
464 * 'r' - remove the device HOT_REMOVE_DISK
b80da661
NB
465 * device can be 'faulty' or 'detached' in which case all
466 * matching devices are removed.
682c7051 467 * 'f' - set the device faulty SET_DISK_FAULTY
b80da661
NB
468 * device can be 'detached' in which case any device that
469 * is inaccessible will be marked faulty.
98d27e39
N
470 * For 'f' and 'r', the device can also be a kernel-internal
471 * name such as 'sdb'.
682c7051
NB
472 */
473 mdu_array_info_t array;
474 mdu_disk_info_t disc;
7a3be72f 475 unsigned long long array_size;
1d997643 476 struct mddev_dev *dv;
682c7051 477 struct stat stb;
1d997643 478 int j;
cfad27a9 479 int tfd = -1;
3da92f27 480 struct supertype *st, *tst;
4725bc31 481 char *subarray = NULL;
fe80f49b
NB
482 int duuid[4];
483 int ouuid[4];
f94d52f4 484 int lfd = -1;
98d27e39 485 int sysfd = -1;
7d2e6486 486 int count = 0; /* number of actions taken */
9f584691
N
487 struct mdinfo info;
488 int frozen = 0;
682c7051
NB
489
490 if (ioctl(fd, GET_ARRAY_INFO, &array)) {
e7b84f9d 491 pr_err("cannot get array info for %s\n",
682c7051 492 devname);
bcbb3112 493 goto abort;
682c7051 494 }
9f584691 495 sysfs_init(&info, fd, 0);
3da92f27 496
7a3be72f
NB
497 /* array.size is only 32 bit and may be truncated.
498 * So read from sysfs if possible, and record number of sectors
499 */
500
501 array_size = get_component_size(fd);
502 if (array_size <= 0)
503 array_size = array.size * 2;
504
4725bc31 505 tst = super_by_fd(fd, &subarray);
3da92f27 506 if (!tst) {
e7b84f9d 507 pr_err("unsupport array - version %d.%d\n",
3da92f27 508 array.major_version, array.minor_version);
bcbb3112 509 goto abort;
3da92f27
NB
510 }
511
b3b4e8a7 512 stb.st_rdev = 0;
1d997643 513 for (dv = devlist, j=0 ; dv; dv = dv->next) {
4a39c6f2 514 unsigned long long ldsize;
f94d52f4 515 int err;
0a999759 516 int array_failed;
4a39c6f2 517
1d997643
N
518 if (strcmp(dv->devname, "failed") == 0 ||
519 strcmp(dv->devname, "faulty") == 0) {
b80da661 520 if (dv->disposition != 'r') {
e7b84f9d 521 pr_err("%s only meaningful "
b80da661
NB
522 "with -r, not -%c\n",
523 dv->devname, dv->disposition);
bcbb3112 524 goto abort;
b80da661 525 }
1d997643
N
526 add_faulty(dv, fd, 'r');
527 continue;
528 }
529 if (strcmp(dv->devname, "detached") == 0) {
b80da661 530 if (dv->disposition != 'r' && dv->disposition != 'f') {
e7b84f9d 531 pr_err("%s only meaningful "
b80da661
NB
532 "with -r of -f, not -%c\n",
533 dv->devname, dv->disposition);
bcbb3112 534 goto abort;
b80da661 535 }
1d997643
N
536 add_detached(dv, fd, dv->disposition);
537 continue;
538 }
539
540 if (strcmp(dv->devname, "missing") == 0) {
541 struct mddev_dev *add_devlist = NULL;
542 struct mddev_dev **dp;
c8e1a230 543 if (dv->disposition != 'A') {
e7b84f9d 544 pr_err("'missing' only meaningful "
a4e13010 545 "with --re-add\n");
bcbb3112 546 goto abort;
a4e13010 547 }
1d997643 548 add_devlist = conf_get_devs();
a4e13010 549 if (add_devlist == NULL) {
e7b84f9d 550 pr_err("no devices to scan for missing members.");
a4e13010
N
551 continue;
552 }
1d997643
N
553 for (dp = &add_devlist; *dp; dp = & (*dp)->next)
554 /* 'M' is like 'A' without errors */
555 (*dp)->disposition = 'M';
556 *dp = dv->next;
557 dv->next = add_devlist;
558 continue;
559 }
560
561 if (strchr(dv->devname, '/') == NULL &&
93601c43 562 strchr(dv->devname, ':') == NULL &&
98d27e39
N
563 strlen(dv->devname) < 50) {
564 /* Assume this is a kernel-internal name like 'sda1' */
565 int found = 0;
566 char dname[55];
567 if (dv->disposition != 'r' && dv->disposition != 'f') {
e7b84f9d 568 pr_err("%s only meaningful "
cfad27a9 569 "with -r or -f, not -%c\n",
98d27e39 570 dv->devname, dv->disposition);
bcbb3112 571 goto abort;
98d27e39
N
572 }
573
574 sprintf(dname, "dev-%s", dv->devname);
575 sysfd = sysfs_open(fd2devnum(fd), dname, "block/dev");
576 if (sysfd >= 0) {
577 char dn[20];
578 int mj,mn;
579 if (sysfs_fd_get_str(sysfd, dn, 20) > 0 &&
580 sscanf(dn, "%d:%d", &mj,&mn) == 2) {
581 stb.st_rdev = makedev(mj,mn);
582 found = 1;
583 }
584 close(sysfd);
585 sysfd = -1;
586 }
587 if (!found) {
588 sysfd = sysfs_open(fd2devnum(fd), dname, "state");
589 if (sysfd < 0) {
e7b84f9d 590 pr_err("%s does not appear "
98d27e39
N
591 "to be a component of %s\n",
592 dv->devname, devname);
bcbb3112 593 goto abort;
98d27e39
N
594 }
595 }
b80da661
NB
596 } else {
597 j = 0;
598
c7b47447 599 tfd = dev_open(dv->devname, O_RDONLY);
5a9de8db
N
600 if (tfd < 0 && dv->disposition == 'r' &&
601 lstat(dv->devname, &stb) == 0)
602 /* Be happy, the lstat worked, that is
603 * enough for --remove
604 */
605 ;
606 else {
607 if (tfd < 0 || fstat(tfd, &stb) != 0) {
5a9de8db
N
608 if (tfd >= 0)
609 close(tfd);
1d997643
N
610 if (dv->disposition == 'M')
611 /* non-fatal */
612 continue;
613 pr_err("cannot find %s: %s\n",
614 dv->devname, strerror(errno));
bcbb3112 615 goto abort;
5a9de8db
N
616 }
617 close(tfd);
cfad27a9 618 tfd = -1;
b80da661
NB
619 }
620 if ((stb.st_mode & S_IFMT) != S_IFBLK) {
1d997643
N
621 if (dv->disposition == 'M')
622 /* non-fatal. Also improbable */
623 continue;
e7b84f9d 624 pr_err("%s is not a "
b80da661
NB
625 "block device.\n",
626 dv->devname);
bcbb3112 627 goto abort;
b80da661 628 }
682c7051 629 }
cd29a5c8 630 switch(dv->disposition){
682c7051 631 default:
e7b84f9d 632 pr_err("internal error - devmode[%s]=%d\n",
c913b90e 633 dv->devname, dv->disposition);
bcbb3112 634 goto abort;
682c7051 635 case 'a':
c8e1a230 636 case 'A':
1d997643 637 case 'M':
4a39c6f2 638 /* add the device */
4725bc31 639 if (subarray) {
e7b84f9d 640 pr_err("Cannot add disks to a"
f7dd881f
DW
641 " \'member\' array, perform this"
642 " operation on the parent container\n");
bcbb3112 643 goto abort;
f94d52f4 644 }
f277ce36 645 /* Make sure it isn't in use (in 2.6 or later) */
1d997643 646 tfd = dev_open(dv->devname, O_RDONLY|O_EXCL);
0fbf459d 647 if (tfd < 0) {
1d997643
N
648 if (dv->disposition == 'M')
649 continue;
e7b84f9d 650 pr_err("Cannot open %s: %s\n",
d7eaf49f 651 dv->devname, strerror(errno));
bcbb3112 652 goto abort;
d7eaf49f 653 }
9f584691
N
654 if (!frozen) {
655 if (sysfs_freeze_array(&info) == 1)
656 frozen = 1;
657 else
658 frozen = -1;
659 }
3da92f27 660
1686dc25 661 st = dup_super(tst);
3da92f27 662
fe80f49b 663 if (array.not_persistent==0)
3da92f27
NB
664 st->ss->load_super(st, tfd, NULL);
665
1d997643 666 if (!get_dev_size(tfd, dv->devname, &ldsize)) {
093d9187 667 st->ss->free_super(st);
4a39c6f2 668 close(tfd);
cfad27a9 669 tfd = -1;
1d997643
N
670 if (dv->disposition == 'M')
671 continue;
672 else
673 goto abort;
4a39c6f2 674 }
f94d52f4 675
11b391ec
N
676 if (tst->ss->validate_geometry(
677 tst, array.level, array.layout,
678 array.raid_disks, NULL,
679 ldsize >> 9, NULL, NULL, 0) == 0) {
680 if (!force) {
e7b84f9d
N
681 pr_err("%s is larger than %s can "
682 "effectively use.\n"
683 " Add --force is you "
684 "really want to add this device.\n",
1d997643 685 dv->devname, devname);
093d9187 686 st->ss->free_super(st);
11b391ec 687 close(tfd);
bcbb3112 688 goto abort;
11b391ec 689 }
e7b84f9d
N
690 pr_err("%s is larger than %s can "
691 "effectively use.\n"
692 " Adding anyway as --force "
693 "was given.\n",
1d997643 694 dv->devname, devname);
11b391ec 695 }
f94d52f4
NB
696 if (!tst->ss->external &&
697 array.major_version == 0 &&
60d9a174 698 md_get_version(fd)%100 < 2) {
a4e13010 699 close(tfd);
093d9187 700 st->ss->free_super(st);
cfad27a9 701 tfd = -1;
892debc8
NB
702 if (ioctl(fd, HOT_ADD_DISK,
703 (unsigned long)stb.st_rdev)==0) {
dab6685f 704 if (verbose >= 0)
e7b84f9d 705 pr_err("hot added %s\n",
1d997643 706 dv->devname);
892debc8
NB
707 continue;
708 }
709
e7b84f9d 710 pr_err("hot add failed for %s: %s\n",
1d997643 711 dv->devname, strerror(errno));
bcbb3112 712 goto abort;
cd29a5c8 713 }
892debc8 714
43dad3d6 715 if (array.not_persistent == 0 || tst->ss->external) {
4a39c6f2 716
fe80f49b 717 /* need to find a sample superblock to copy, and
43dad3d6
DW
718 * a spare slot to use.
719 * For 'external' array (well, container based),
720 * We can just load the metadata for the array.
fe80f49b 721 */
a4e13010
N
722 if (tst->sb)
723 /* already loaded */;
724 else if (tst->ss->external) {
0fb69d1d 725 tst->ss->load_container(tst, fd, NULL);
43dad3d6 726 } else for (j = 0; j < tst->max_devs; j++) {
fe80f49b
NB
727 char *dev;
728 int dfd;
729 disc.number = j;
730 if (ioctl(fd, GET_DISK_INFO, &disc))
731 continue;
732 if (disc.major==0 && disc.minor==0)
733 continue;
734 if ((disc.state & 4)==0) continue; /* sync */
735 /* Looks like a good device to try */
16c6fa80 736 dev = map_dev(disc.major, disc.minor, 1);
fe80f49b 737 if (!dev) continue;
16c6fa80 738 dfd = dev_open(dev, O_RDONLY);
fe80f49b 739 if (dfd < 0) continue;
3da92f27
NB
740 if (tst->ss->load_super(tst, dfd,
741 NULL)) {
fe80f49b
NB
742 close(dfd);
743 continue;
744 }
892debc8 745 close(dfd);
fe80f49b
NB
746 break;
747 }
43dad3d6 748 /* FIXME this is a bad test to be using */
1d997643 749 if (!tst->sb && dv->disposition != 'a') {
c69ffac0
N
750 /* we are re-adding a device to a
751 * completely dead array - have to depend
752 * on kernel to check
753 */
754 } else if (!tst->sb) {
a4e13010 755 close(tfd);
093d9187 756 st->ss->free_super(st);
e7b84f9d 757 pr_err("cannot load array metadata from %s\n", devname);
bcbb3112 758 goto abort;
fe80f49b 759 }
2a528478
N
760
761 /* Make sure device is large enough */
762 if (tst->ss->avail_size(tst, ldsize/512) <
763 array_size) {
a4e13010 764 close(tfd);
cfad27a9 765 tfd = -1;
093d9187 766 st->ss->free_super(st);
1d997643 767 if (dv->disposition == 'M')
a4e13010 768 continue;
e7b84f9d 769 pr_err("%s not large enough to join array\n",
2a528478 770 dv->devname);
bcbb3112 771 goto abort;
2a528478
N
772 }
773
fe80f49b
NB
774 /* Possibly this device was recently part of the array
775 * and was temporarily removed, and is now being re-added.
776 * If so, we can simply re-add it.
777 */
7eae7080 778
873eec46 779 if (st->sb) {
8453e704 780 struct mdinfo mdi;
a5d85af7 781 st->ss->getinfo_super(st, &mdi, NULL);
3da92f27 782 st->ss->uuid_from_super(st, ouuid);
c69ffac0
N
783 if (tst->sb)
784 tst->ss->uuid_from_super(tst, duuid);
785 else
786 /* Assume uuid matches: kernel will check */
787 memcpy(duuid, ouuid, sizeof(ouuid));
8453e704
N
788 if ((mdi.disk.state & (1<<MD_DISK_ACTIVE)) &&
789 !(mdi.disk.state & (1<<MD_DISK_FAULTY)) &&
790 memcmp(duuid, ouuid, sizeof(ouuid))==0) {
791 /* look like it is worth a try. Need to
792 * make sure kernel will accept it though.
fe80f49b 793 */
873eec46
N
794 /* re-add doesn't work for version-1 superblocks
795 * before 2.6.18 :-(
796 */
797 if (array.major_version == 1 &&
798 get_linux_version() <= 2006018)
799 goto skip_re_add;
8453e704
N
800 disc.number = mdi.disk.number;
801 if (ioctl(fd, GET_DISK_INFO, &disc) != 0
802 || disc.major != 0 || disc.minor != 0
c69ffac0 803 )
8453e704 804 goto skip_re_add;
fe80f49b
NB
805 disc.major = major(stb.st_rdev);
806 disc.minor = minor(stb.st_rdev);
807 disc.number = mdi.disk.number;
808 disc.raid_disk = mdi.disk.raid_disk;
809 disc.state = mdi.disk.state;
b3d31955 810 if (dv->writemostly == 1)
4d20d744 811 disc.state |= 1 << MD_DISK_WRITEMOSTLY;
b3d31955
N
812 if (dv->writemostly == 2)
813 disc.state &= ~(1 << MD_DISK_WRITEMOSTLY);
a4e13010
N
814 remove_partitions(tfd);
815 close(tfd);
816 tfd = -1;
16715c01 817 if (update || dv->writemostly > 0) {
833bb0f8
N
818 int rv = -1;
819 tfd = dev_open(dv->devname, O_RDWR);
16715c01 820 if (tfd < 0) {
e7b84f9d 821 pr_err("failed to open %s for"
16715c01 822 " superblock update during re-add\n", dv->devname);
093d9187 823 st->ss->free_super(st);
bcbb3112 824 goto abort;
16715c01 825 }
833bb0f8 826
16715c01
DL
827 if (dv->writemostly == 1)
828 rv = st->ss->update_super(
829 st, NULL, "writemostly",
830 devname, verbose, 0, NULL);
831 if (dv->writemostly == 2)
832 rv = st->ss->update_super(
833 st, NULL, "readwrite",
834 devname, verbose, 0, NULL);
835 if (update)
833bb0f8
N
836 rv = st->ss->update_super(
837 st, NULL, update,
838 devname, verbose, 0, NULL);
839 if (rv == 0)
c0f8269d 840 rv = st->ss->store_super(st, tfd);
833bb0f8
N
841 close(tfd);
842 tfd = -1;
843 if (rv != 0) {
e7b84f9d
N
844 pr_err("failed to update"
845 " superblock during re-add\n");
093d9187 846 st->ss->free_super(st);
bcbb3112 847 goto abort;
833bb0f8
N
848 }
849 }
5c64fcb5
N
850 /* don't even try if disk is marked as faulty */
851 errno = 0;
8453e704 852 if (ioctl(fd, ADD_NEW_DISK, &disc) == 0) {
fe80f49b 853 if (verbose >= 0)
1d997643 854 pr_err("re-added %s\n", dv->devname);
7d2e6486 855 count++;
093d9187 856 st->ss->free_super(st);
308e1801 857 continue;
fe80f49b 858 }
c9f39c1b 859 if (errno == ENOMEM || errno == EROFS) {
e7b84f9d 860 pr_err("add new device failed for %s: %s\n",
1d997643 861 dv->devname, strerror(errno));
093d9187 862 st->ss->free_super(st);
1d997643 863 if (dv->disposition == 'M')
a4e13010 864 continue;
bcbb3112 865 goto abort;
c9f39c1b 866 }
fe80f49b 867 }
0a999759 868 skip_re_add:
1cc7f4fe 869 st->ss->free_super(st);
892debc8 870 }
1d997643 871 if (dv->disposition == 'M') {
a4e13010 872 if (verbose > 0)
e7b84f9d 873 pr_err("--re-add for %s to %s is not possible\n",
1d997643 874 dv->devname, devname);
cfad27a9 875 if (tfd >= 0) {
a4e13010 876 close(tfd);
cfad27a9
DL
877 tfd = -1;
878 }
a4e13010
N
879 continue;
880 }
c8e1a230 881 if (dv->disposition == 'A') {
a4e13010
N
882 if (tfd >= 0)
883 close(tfd);
e7b84f9d
N
884 pr_err("--re-add for %s to %s is not possible\n",
885 dv->devname, devname);
bcbb3112 886 goto abort;
751fd6c0 887 }
0a999759 888 if (array.active_disks < array.raid_disks) {
503975b9 889 char *avail = xcalloc(array.raid_disks, 1);
0a999759
N
890 int d;
891 int found = 0;
892
893 for (d = 0; d < MAX_DISKS && found < array.active_disks; d++) {
894 disc.number = d;
895 if (ioctl(fd, GET_DISK_INFO, &disc))
896 continue;
897 if (disc.major == 0 && disc.minor == 0)
898 continue;
899 if (!(disc.state & (1<<MD_DISK_SYNC)))
900 continue;
901 avail[disc.raid_disk] = 1;
902 found++;
903 }
904 array_failed = !enough(array.level, array.raid_disks,
905 array.layout, 1, avail);
906 } else
907 array_failed = 0;
908 if (array_failed) {
e7b84f9d 909 pr_err("%s has failed so using --add cannot work and might destroy\n",
0a999759 910 devname);
e7b84f9d 911 pr_err("data on %s. You should stop the array and re-assemble it.\n",
8453e704
N
912 dv->devname);
913 if (tfd >= 0)
914 close(tfd);
bcbb3112 915 goto abort;
8453e704 916 }
4a39c6f2
NB
917 } else {
918 /* non-persistent. Must ensure that new drive
919 * is at least array.size big.
920 */
7a3be72f 921 if (ldsize/512 < array_size) {
e7b84f9d 922 pr_err("%s not large enough to join array\n",
4a39c6f2 923 dv->devname);
cfad27a9
DL
924 if (tfd >= 0)
925 close(tfd);
bcbb3112 926 goto abort;
4a39c6f2 927 }
892debc8 928 }
a4e13010
N
929 /* committed to really trying this device now*/
930 if (tfd >= 0) {
931 remove_partitions(tfd);
932 close(tfd);
cfad27a9 933 tfd = -1;
a4e13010 934 }
7eae7080
NB
935 /* in 2.6.17 and earlier, version-1 superblocks won't
936 * use the number we write, but will choose a free number.
937 * we must choose the same free number, which requires
938 * starting at 'raid_disks' and counting up
939 */
3da92f27 940 for (j = array.raid_disks; j< tst->max_devs; j++) {
aa88f531 941 disc.number = j;
682c7051
NB
942 if (ioctl(fd, GET_DISK_INFO, &disc))
943 break;
944 if (disc.major==0 && disc.minor==0)
945 break;
946 if (disc.state & 8) /* removed */
947 break;
948 }
0df46c2a
NB
949 disc.major = major(stb.st_rdev);
950 disc.minor = minor(stb.st_rdev);
892debc8
NB
951 disc.number =j;
952 disc.state = 0;
02c39ab1 953 if (array.not_persistent==0) {
111d01fc 954 int dfd;
b3d31955 955 if (dv->writemostly == 1)
fe80f49b 956 disc.state |= 1 << MD_DISK_WRITEMOSTLY;
3b435195 957 dfd = dev_open(dv->devname, O_RDWR | O_EXCL|O_DIRECT);
f20c3968
DW
958 if (tst->ss->add_to_super(tst, &disc, dfd,
959 dv->devname)) {
f20c3968 960 close(dfd);
bcbb3112 961 goto abort;
f20c3968 962 }
1cc7f4fe
N
963 if (tst->ss->write_init_super(tst)) {
964 close(dfd);
bcbb3112 965 goto abort;
1cc7f4fe 966 }
c8e1a230 967 } else if (dv->disposition == 'A') {
fe80f49b
NB
968 /* this had better be raid1.
969 * As we are "--re-add"ing we must find a spare slot
970 * to fill.
971 */
503975b9 972 char *used = xcalloc(array.raid_disks, 1);
3da92f27 973 for (j=0; j< tst->max_devs; j++) {
fe80f49b
NB
974 mdu_disk_info_t disc2;
975 disc2.number = j;
976 if (ioctl(fd, GET_DISK_INFO, &disc2))
977 continue;
978 if (disc2.major==0 && disc2.minor==0)
979 continue;
980 if (disc2.state & 8) /* removed */
981 continue;
982 if (disc2.raid_disk < 0)
983 continue;
984 if (disc2.raid_disk > array.raid_disks)
985 continue;
986 used[disc2.raid_disk] = 1;
987 }
988 for (j=0 ; j<array.raid_disks; j++)
989 if (!used[j]) {
990 disc.raid_disk = j;
991 disc.state |= (1<<MD_DISK_SYNC);
992 break;
993 }
0eb26465 994 free(used);
fe80f49b 995 }
b3d31955 996 if (dv->writemostly == 1)
d8def61c 997 disc.state |= (1 << MD_DISK_WRITEMOSTLY);
43dad3d6 998 if (tst->ss->external) {
73cb8d43
AK
999 /* add a disk
1000 * to an external metadata container */
43dad3d6
DW
1001 struct mdinfo new_mdi;
1002 struct mdinfo *sra;
1003 int container_fd;
1004 int devnum = fd2devnum(fd);
02c39ab1 1005 int dfd;
43dad3d6
DW
1006
1007 container_fd = open_dev_excl(devnum);
1008 if (container_fd < 0) {
e7b84f9d
N
1009 pr_err("add failed for %s:"
1010 " could not get exclusive access to container\n",
1011 dv->devname);
562e70e4 1012 tst->ss->free_super(tst);
bcbb3112 1013 goto abort;
43dad3d6
DW
1014 }
1015
02c39ab1 1016 dfd = dev_open(dv->devname, O_RDWR | O_EXCL|O_DIRECT);
d6221e66
N
1017 if (mdmon_running(tst->container_dev))
1018 tst->update_tail = &tst->updates;
02c39ab1
N
1019 if (tst->ss->add_to_super(tst, &disc, dfd,
1020 dv->devname)) {
1021 close(dfd);
1022 close(container_fd);
bcbb3112 1023 goto abort;
02c39ab1 1024 }
c0f8269d
AK
1025 if (tst->update_tail)
1026 flush_metadata_updates(tst);
d6221e66 1027 else
c0f8269d 1028 tst->ss->sync_metadata(tst);
02c39ab1 1029
43dad3d6
DW
1030 sra = sysfs_read(container_fd, -1, 0);
1031 if (!sra) {
e7b84f9d 1032 pr_err("add failed for %s: sysfs_read failed\n",
43dad3d6
DW
1033 dv->devname);
1034 close(container_fd);
562e70e4 1035 tst->ss->free_super(tst);
bcbb3112 1036 goto abort;
43dad3d6
DW
1037 }
1038 sra->array.level = LEVEL_CONTAINER;
1039 /* Need to set data_offset and component_size */
a5d85af7 1040 tst->ss->getinfo_super(tst, &new_mdi, NULL);
43dad3d6
DW
1041 new_mdi.disk.major = disc.major;
1042 new_mdi.disk.minor = disc.minor;
d23534e4 1043 new_mdi.recovery_start = 0;
1cc7f4fe
N
1044 /* Make sure fds are closed as they are O_EXCL which
1045 * would block add_disk */
1046 tst->ss->free_super(tst);
462906cd 1047 if (sysfs_add_disk(sra, &new_mdi, 0) != 0) {
e7b84f9d 1048 pr_err("add new device to external metadata"
43dad3d6
DW
1049 " failed for %s\n", dv->devname);
1050 close(container_fd);
73cb8d43 1051 sysfs_free(sra);
bcbb3112 1052 goto abort;
43dad3d6 1053 }
983fff45 1054 ping_monitor_by_id(devnum);
43dad3d6
DW
1055 sysfs_free(sra);
1056 close(container_fd);
562e70e4
N
1057 } else {
1058 tst->ss->free_super(tst);
1059 if (ioctl(fd, ADD_NEW_DISK, &disc)) {
e7b84f9d 1060 pr_err("add new device failed for %s as %d: %s\n",
562e70e4 1061 dv->devname, j, strerror(errno));
bcbb3112 1062 goto abort;
562e70e4 1063 }
682c7051 1064 }
dab6685f 1065 if (verbose >= 0)
e7b84f9d 1066 pr_err("added %s\n", dv->devname);
682c7051
NB
1067 break;
1068
1069 case 'r':
1070 /* hot remove */
4725bc31 1071 if (subarray) {
e7b84f9d 1072 pr_err("Cannot remove disks from a"
f7dd881f
DW
1073 " \'member\' array, perform this"
1074 " operation on the parent container\n");
98d27e39
N
1075 if (sysfd >= 0)
1076 close(sysfd);
bcbb3112 1077 goto abort;
f94d52f4
NB
1078 }
1079 if (tst->ss->external) {
1080 /* To remove a device from a container, we must
1081 * check that it isn't in use in an array.
1082 * This involves looking in the 'holders'
1083 * directory - there must be just one entry,
1084 * the container.
1085 * To ensure that it doesn't get used as a
1086 * hold spare while we are checking, we
1087 * get an O_EXCL open on the container
1088 */
1089 int dnum = fd2devnum(fd);
1090 lfd = open_dev_excl(dnum);
1091 if (lfd < 0) {
e7b84f9d
N
1092 pr_err("Cannot get exclusive access "
1093 " to container - odd\n");
98d27e39
N
1094 if (sysfd >= 0)
1095 close(sysfd);
bcbb3112 1096 goto abort;
f94d52f4 1097 }
85f9b5f7
DW
1098 /* in the detached case it is not possible to
1099 * check if we are the unique holder, so just
1100 * rely on the 'detached' checks
1101 */
1102 if (strcmp(dv->devname, "detached") == 0 ||
98d27e39 1103 sysfd >= 0 ||
85f9b5f7
DW
1104 sysfs_unique_holder(dnum, stb.st_rdev))
1105 /* pass */;
1106 else {
e7b84f9d 1107 pr_err("%s is %s, cannot remove.\n",
1d997643 1108 dv->devname,
e7b84f9d
N
1109 errno == EEXIST ? "still in use":
1110 "not a member");
f94d52f4 1111 close(lfd);
bcbb3112 1112 goto abort;
f94d52f4
NB
1113 }
1114 }
82b27616 1115 /* FIXME check that it is a current member */
98d27e39
N
1116 if (sysfd >= 0) {
1117 /* device has been removed and we don't know
1118 * the major:minor number
1119 */
1120 int n = write(sysfd, "remove", 6);
1121 if (n != 6)
f94d52f4 1122 err = -1;
98d27e39
N
1123 else
1124 err = 0;
1125 close(sysfd);
1126 sysfd = -1;
1127 } else {
1128 err = ioctl(fd, HOT_REMOVE_DISK, (unsigned long)stb.st_rdev);
1129 if (err && errno == ENODEV) {
1130 /* Old kernels rejected this if no personality
1131 * registered */
1132 struct mdinfo *sra = sysfs_read(fd, 0, GET_DEVS);
1133 struct mdinfo *dv = NULL;
1134 if (sra)
1135 dv = sra->devs;
1136 for ( ; dv ; dv=dv->next)
f21e18ca
N
1137 if (dv->disk.major == (int)major(stb.st_rdev) &&
1138 dv->disk.minor == (int)minor(stb.st_rdev))
98d27e39
N
1139 break;
1140 if (dv)
1141 err = sysfs_set_str(sra, dv,
1142 "state", "remove");
1143 else
1144 err = -1;
1145 if (sra)
1146 sysfs_free(sra);
1147 }
f94d52f4
NB
1148 }
1149 if (err) {
e7b84f9d 1150 pr_err("hot remove failed "
1d997643 1151 "for %s: %s\n", dv->devname,
e7b84f9d 1152 strerror(errno));
f94d52f4
NB
1153 if (lfd >= 0)
1154 close(lfd);
bcbb3112 1155 goto abort;
682c7051 1156 }
313a4a82
DW
1157 if (tst->ss->external) {
1158 /*
1159 * Before dropping our exclusive open we make an
1160 * attempt at preventing mdmon from seeing an
1161 * 'add' event before reconciling this 'remove'
1162 * event.
1163 */
1164 char *name = devnum2devname(fd2devnum(fd));
1165
1166 if (!name) {
e7b84f9d 1167 pr_err("unable to get container name\n");
bcbb3112 1168 goto abort;
313a4a82
DW
1169 }
1170
1171 ping_manager(name);
1172 free(name);
1173 }
98d27e39
N
1174 if (lfd >= 0)
1175 close(lfd);
7d2e6486 1176 count++;
dab6685f 1177 if (verbose >= 0)
e7b84f9d 1178 pr_err("hot removed %s from %s\n",
1d997643 1179 dv->devname, devname);
682c7051
NB
1180 break;
1181
1182 case 'f': /* set faulty */
1183 /* FIXME check current member */
98d27e39
N
1184 if ((sysfd >= 0 && write(sysfd, "faulty", 6) != 6) ||
1185 (sysfd < 0 && ioctl(fd, SET_DISK_FAULTY,
1186 (unsigned long) stb.st_rdev))) {
e7b84f9d 1187 pr_err("set device faulty failed for %s: %s\n",
1d997643 1188 dv->devname, strerror(errno));
98d27e39
N
1189 if (sysfd >= 0)
1190 close(sysfd);
bcbb3112 1191 goto abort;
682c7051 1192 }
98d27e39
N
1193 if (sysfd >= 0)
1194 close(sysfd);
1195 sysfd = -1;
7d2e6486 1196 count++;
dab6685f 1197 if (verbose >= 0)
e7b84f9d 1198 pr_err("set %s faulty in %s\n",
1d997643 1199 dv->devname, devname);
682c7051
NB
1200 break;
1201 }
1202 }
9f584691
N
1203 if (frozen > 0)
1204 sysfs_set_str(&info, NULL, "sync_action","idle");
7d2e6486
N
1205 if (test && count == 0)
1206 return 2;
682c7051 1207 return 0;
bcbb3112
N
1208
1209abort:
9f584691
N
1210 if (frozen > 0)
1211 sysfs_set_str(&info, NULL, "sync_action","idle");
bcbb3112 1212 return 1;
64c4757e 1213}
1f48664b
NB
1214
1215int autodetect(void)
1216{
1217 /* Open any md device, and issue the RAID_AUTORUN ioctl */
1218 int rv = 1;
1219 int fd = dev_open("9:0", O_RDONLY);
1220 if (fd >= 0) {
1221 if (ioctl(fd, RAID_AUTORUN, 0) == 0)
1222 rv = 0;
1223 close(fd);
1224 }
1225 return rv;
1226}
aa534678 1227
ba728be7 1228int Update_subarray(char *dev, char *subarray, char *update, struct mddev_ident *ident, int verbose)
aa534678
DW
1229{
1230 struct supertype supertype, *st = &supertype;
1231 int fd, rv = 2;
1232
1233 memset(st, 0, sizeof(*st));
aa534678 1234
ba728be7 1235 fd = open_subarray(dev, subarray, st, verbose < 0);
aa534678
DW
1236 if (fd < 0)
1237 return 2;
1238
1239 if (!st->ss->update_subarray) {
ba728be7 1240 if (verbose >= 0)
e7b84f9d
N
1241 pr_err("Operation not supported for %s metadata\n",
1242 st->ss->name);
aa534678
DW
1243 goto free_super;
1244 }
1245
1246 if (mdmon_running(st->devnum))
1247 st->update_tail = &st->updates;
1248
a951a4f7 1249 rv = st->ss->update_subarray(st, subarray, update, ident);
aa534678
DW
1250
1251 if (rv) {
ba728be7 1252 if (verbose >= 0)
e7b84f9d 1253 pr_err("Failed to update %s of subarray-%s in %s\n",
aa534678
DW
1254 update, subarray, dev);
1255 } else if (st->update_tail)
1256 flush_metadata_updates(st);
1257 else
1258 st->ss->sync_metadata(st);
1259
ba728be7 1260 if (rv == 0 && strcmp(update, "name") == 0 && verbose >= 0)
e7b84f9d
N
1261 pr_err("Updated subarray-%s name from %s, UUIDs may have changed\n",
1262 subarray, dev);
aa534678
DW
1263
1264 free_super:
1265 st->ss->free_super(st);
1266 close(fd);
1267
1268 return rv;
1269}
d52bb542
AC
1270
1271/* Move spare from one array to another
1272 * If adding to destination array fails
1273 * add back to original array
1274 * Returns 1 on success, 0 on failure */
1275int move_spare(char *from_devname, char *to_devname, dev_t devid)
1276{
1277 struct mddev_dev devlist;
1278 char devname[20];
1279
1280 /* try to remove and add */
1281 int fd1 = open(to_devname, O_RDONLY);
1282 int fd2 = open(from_devname, O_RDONLY);
1283
1284 if (fd1 < 0 || fd2 < 0) {
1285 if (fd1>=0) close(fd1);
1286 if (fd2>=0) close(fd2);
1287 return 0;
1288 }
1289
1290 devlist.next = NULL;
1291 devlist.used = 0;
d52bb542
AC
1292 devlist.writemostly = 0;
1293 devlist.devname = devname;
1294 sprintf(devname, "%d:%d", major(devid), minor(devid));
1295
1296 devlist.disposition = 'r';
11b391ec 1297 if (Manage_subdevs(from_devname, fd2, &devlist, -1, 0, NULL, 0) == 0) {
d52bb542 1298 devlist.disposition = 'a';
11b391ec 1299 if (Manage_subdevs(to_devname, fd1, &devlist, -1, 0, NULL, 0) == 0) {
d52bb542
AC
1300 /* make sure manager is aware of changes */
1301 ping_manager(to_devname);
1302 ping_manager(from_devname);
1303 close(fd1);
1304 close(fd2);
1305 return 1;
1306 }
11b391ec 1307 else Manage_subdevs(from_devname, fd2, &devlist, -1, 0, NULL, 0);
d52bb542
AC
1308 }
1309 close(fd1);
1310 close(fd2);
1311 return 0;
1312}
435d4ebb 1313#endif