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