]> git.ipfire.org Git - thirdparty/mdadm.git/blame - Manage.c
Fix memory leak in file Manage
[thirdparty/mdadm.git] / Manage.c
CommitLineData
64c4757e 1/*
9a9dab36 2 * mdadm - manage Linux "md" devices aka RAID arrays.
64c4757e 3 *
6f02172d 4 * Copyright (C) 2001-2013 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
NB
29
30int Manage_ro(char *devname, int fd, int readonly)
31{
682c7051
NB
32 /* switch to readonly or rw
33 *
34 * requires >= 0.90.0
35 * first check that array is runing
36 * use RESTART_ARRAY_RW or STOP_ARRAY_RO
37 *
38 */
e9dd1598 39 struct mdinfo *mdi;
b73e45ae 40 int rv = 0;
aba69144 41
7bd04da9 42 /* If this is an externally-managed array, we need to modify the
e9dd1598
N
43 * metadata_version so that mdmon doesn't undo our change.
44 */
4dd2df09 45 mdi = sysfs_read(fd, NULL, GET_LEVEL|GET_VERSION);
e9dd1598
N
46 if (mdi &&
47 mdi->array.major_version == -1 &&
e9dd1598
N
48 is_subarray(mdi->text_version)) {
49 char vers[64];
50 strcpy(vers, "external:");
51 strcat(vers, mdi->text_version);
52 if (readonly > 0) {
53 int rv;
54 /* We set readonly ourselves. */
55 vers[9] = '-';
56 sysfs_set_str(mdi, NULL, "metadata_version", vers);
57
58 close(fd);
59 rv = sysfs_set_str(mdi, NULL, "array_state", "readonly");
60
61 if (rv < 0) {
e7b84f9d 62 pr_err("failed to set readonly for %s: %s\n",
e9dd1598
N
63 devname, strerror(errno));
64
65 vers[9] = mdi->text_version[0];
66 sysfs_set_str(mdi, NULL, "metadata_version", vers);
b73e45ae
JS
67 rv = 1;
68 goto out;
e9dd1598
N
69 }
70 } else {
71 char *cp;
72 /* We cannot set read/write - must signal mdmon */
73 vers[9] = '/';
74 sysfs_set_str(mdi, NULL, "metadata_version", vers);
75
76 cp = strchr(vers+10, '/');
1471b8b1 77 if (cp)
e9dd1598
N
78 *cp = 0;
79 ping_monitor(vers+10);
9ea5a252
DW
80 if (mdi->array.level <= 0)
81 sysfs_set_str(mdi, NULL, "array_state", "active");
e9dd1598 82 }
b73e45ae 83 goto out;
e9dd1598 84 }
32141c17 85
80223cb4
JS
86 if (!md_array_active(fd)) {
87 pr_err("%s does not appear to be active.\n", devname);
b73e45ae
JS
88 rv = 1;
89 goto out;
682c7051 90 }
aba69144 91
7bd04da9 92 if (readonly > 0) {
682c7051 93 if (ioctl(fd, STOP_ARRAY_RO, NULL)) {
e7b84f9d 94 pr_err("failed to set readonly for %s: %s\n",
682c7051 95 devname, strerror(errno));
b73e45ae
JS
96 rv = 1;
97 goto out;
682c7051
NB
98 }
99 } else if (readonly < 0) {
100 if (ioctl(fd, RESTART_ARRAY_RW, NULL)) {
e7b84f9d 101 pr_err("failed to set writable for %s: %s\n",
682c7051 102 devname, strerror(errno));
b73e45ae
JS
103 rv = 1;
104 goto out;
682c7051
NB
105 }
106 }
b73e45ae 107out:
6e8d27e7 108 sysfs_free(mdi);
b73e45ae 109 return rv;
64c4757e
NB
110}
111
4dd2df09 112static void remove_devices(char *devnm, char *path)
4ccad7b1 113{
7bd04da9 114 /*
b1702f48
N
115 * Remove names at 'path' - possibly with
116 * partition suffixes - which link to the 'standard'
4dd2df09 117 * name for devnm. These were probably created
b1702f48 118 * by mdadm when the array was assembled.
4ccad7b1
N
119 */
120 char base[40];
121 char *path2;
122 char link[1024];
123 int n;
124 int part;
125 char *be;
126 char *pe;
127
b1702f48
N
128 if (!path)
129 return;
130
4dd2df09 131 sprintf(base, "/dev/%s", devnm);
4ccad7b1 132 be = base + strlen(base);
b1702f48 133
503975b9 134 path2 = xmalloc(strlen(path)+20);
b1702f48
N
135 strcpy(path2, path);
136 pe = path2 + strlen(path2);
7bd04da9 137
4ccad7b1
N
138 for (part = 0; part < 16; part++) {
139 if (part) {
140 sprintf(be, "p%d", part);
b1702f48
N
141
142 if (isdigit(pe[-1]))
143 sprintf(pe, "p%d", part);
144 else
145 sprintf(pe, "%d", part);
4ccad7b1 146 }
b1702f48 147 n = readlink(path2, link, sizeof(link));
d9ca03e9 148 if (n > 0 && (int)strlen(base) == n &&
b1702f48
N
149 strncmp(link, base, n) == 0)
150 unlink(path2);
4ccad7b1 151 }
0eb26465 152 free(path2);
4ccad7b1 153}
4ccad7b1 154
d5a40416 155int Manage_run(char *devname, int fd, struct context *c)
64c4757e 156{
fe7e0e64
N
157 /* Run the array. Array must already be configured
158 * Requires >= 0.90.0
682c7051 159 */
d3786cdc 160 char nm[32], *nmp;
82b27616 161
d3786cdc
N
162 nmp = fd2devnm(fd);
163 if (!nmp) {
164 pr_err("Cannot find %s in sysfs!!\n", devname);
fe7e0e64
N
165 return 1;
166 }
d3786cdc 167 strcpy(nm, nmp);
d5a40416 168 return IncrementalScan(c, nm);
fe7e0e64
N
169}
170
171int Manage_stop(char *devname, int fd, int verbose, int will_retry)
172{
173 /* Stop the array. Array must already be configured
174 * 'will_retry' means that error messages are not wanted.
175 */
176 int rv = 0;
177 struct map_ent *map = NULL;
178 struct mdinfo *mdi;
179 char devnm[32];
180 char container[32];
181 int err;
182 int count;
2eba8496
N
183 char buf[32];
184 unsigned long long rd1, rd2;
fe7e0e64 185
ba728be7
N
186 if (will_retry && verbose == 0)
187 verbose = -1;
188
fe7e0e64
N
189 strcpy(devnm, fd2devnm(fd));
190 /* Get EXCL access first. If this fails, then attempting
191 * to stop is probably a bad idea.
192 */
2eba8496 193 mdi = sysfs_read(fd, NULL, GET_LEVEL|GET_COMPONENT|GET_VERSION);
fe7e0e64
N
194 if (mdi && is_subarray(mdi->text_version)) {
195 char *sl;
196 strncpy(container, mdi->text_version+1, sizeof(container));
197 container[sizeof(container)-1] = 0;
198 sl = strchr(container, '/');
199 if (sl)
200 *sl = 0;
201 } else
202 container[0] = 0;
203 close(fd);
204 count = 5;
52b6ccad 205 while (((fd = ((devname[0] == '/')
fe7e0e64 206 ?open(devname, O_RDONLY|O_EXCL)
fc54fe7a
JS
207 :open_dev_flags(devnm, O_RDONLY|O_EXCL))) < 0 ||
208 strcmp(fd2devnm(fd), devnm) != 0) && container[0] &&
209 mdmon_running(container) && count) {
932be627
N
210 /* Can't open, so something might be wrong. However it
211 * is a container, so we might be racing with mdmon, so
212 * retry for a bit.
213 */
fe7e0e64
N
214 if (fd >= 0)
215 close(fd);
216 flush_mdmon(container);
217 count--;
682c7051 218 }
fe7e0e64
N
219 if (fd < 0 || strcmp(fd2devnm(fd), devnm) != 0) {
220 if (fd >= 0)
221 close(fd);
ba728be7 222 if (verbose >= 0)
7a862a02 223 pr_err("Cannot get exclusive access to %s:Perhaps a running process, mounted filesystem or active volume group?\n",
fe7e0e64 224 devname);
f6feb3fb 225 sysfs_free(mdi);
fe7e0e64
N
226 return 1;
227 }
932be627
N
228 /* If this is an mdmon managed array, just write 'inactive'
229 * to the array state and let mdmon clear up.
230 */
fe7e0e64
N
231 if (mdi &&
232 mdi->array.level > 0 &&
233 is_subarray(mdi->text_version)) {
eb0af526 234 int err;
fe7e0e64 235 /* This is mdmon managed. */
eb0af526 236 close(fd);
daf7a3ce 237
932be627 238 /* As we had an O_EXCL open, any use of the device
eb0af526
N
239 * which blocks STOP_ARRAY is probably a transient use,
240 * so it is reasonable to retry for a while - 5 seconds.
241 */
fe7e0e64
N
242 count = 25;
243 while (count &&
244 (err = sysfs_set_str(mdi, NULL,
245 "array_state",
fc54fe7a
JS
246 "inactive")) < 0 &&
247 errno == EBUSY) {
239b3cc0 248 sleep_for(0, MSEC_TO_NSEC(200), true);
fe7e0e64 249 count--;
eb0af526 250 }
fe7e0e64
N
251 if (err) {
252 if (verbose >= 0)
e7b84f9d
N
253 pr_err("failed to stop array %s: %s\n",
254 devname, strerror(errno));
bccd8153
JS
255 rv = 1;
256 goto out;
682c7051 257 }
fe7e0e64
N
258
259 /* Give monitor a chance to act */
260 ping_monitor(mdi->text_version);
261
262 fd = open_dev_excl(devnm);
263 if (fd < 0) {
264 if (verbose >= 0)
7a862a02 265 pr_err("failed to completely stop %s: Device is busy\n",
fe7e0e64
N
266 devname);
267 rv = 1;
268 goto out;
269 }
270 } else if (mdi &&
271 mdi->array.major_version == -1 &&
272 mdi->array.minor_version == -2 &&
273 !is_subarray(mdi->text_version)) {
274 struct mdstat_ent *mds, *m;
275 /* container, possibly mdmon-managed.
276 * Make sure mdmon isn't opening it, which
277 * would interfere with the 'stop'
97590376 278 */
fe7e0e64 279 ping_monitor(mdi->sys_name);
daf7a3ce 280
fe7e0e64
N
281 /* now check that there are no existing arrays
282 * which are members of this array
283 */
284 mds = mdstat_read(0, 0);
285 for (m = mds; m; m = m->next)
286 if (m->metadata_version &&
287 strncmp(m->metadata_version, "external:", 9)==0 &&
288 metadata_container_matches(m->metadata_version+9,
289 devnm)) {
290 if (verbose >= 0)
7a862a02 291 pr_err("Cannot stop container %s: member %s still active\n",
9581efb1 292 devname, m->devnm);
fe7e0e64
N
293 free_mdstat(mds);
294 rv = 1;
295 goto out;
296 }
297 }
298
2eba8496
N
299 /* If the array is undergoing a reshape which changes the number
300 * of devices, then it would be nice to stop it at a point where
301 * it has completed a full number of stripes in both old and
302 * new layouts as this will allow the reshape to be reverted.
303 * So if 'sync_action' is "reshape" and 'raid_disks' shows two
304 * different numbers, then
305 * - freeze reshape
306 * - set sync_max to next multiple of both data_disks and
307 * chunk sizes (or next but one)
308 * - unfreeze reshape
309 * - wait on 'sync_completed' for that point to be reached.
310 */
70f1ff42 311 if (mdi && is_level456(mdi->array.level) &&
2eba8496
N
312 sysfs_attribute_available(mdi, NULL, "sync_action") &&
313 sysfs_attribute_available(mdi, NULL, "reshape_direction") &&
314 sysfs_get_str(mdi, NULL, "sync_action", buf, 20) > 0 &&
315 strcmp(buf, "reshape\n") == 0 &&
e3e0d0a8 316 sysfs_get_two(mdi, NULL, "raid_disks", &rd1, &rd2) == 2) {
2eba8496
N
317 unsigned long long position, curr;
318 unsigned long long chunk1, chunk2;
319 unsigned long long rddiv, chunkdiv;
320 unsigned long long sectors;
5509dc44
N
321 unsigned long long sync_max, old_sync_max;
322 unsigned long long completed;
2eba8496
N
323 int backwards = 0;
324 int delay;
325 int scfd;
326
e3e0d0a8
N
327 delay = 40;
328 while (rd1 > rd2 && delay > 0 &&
329 sysfs_get_ll(mdi, NULL, "sync_max", &old_sync_max) == 0) {
330 /* must be in the critical section - wait a bit */
331 delay -= 1;
239b3cc0 332 sleep_for(0, MSEC_TO_NSEC(100), true);
e3e0d0a8
N
333 }
334
335 if (sysfs_set_str(mdi, NULL, "sync_action", "frozen") != 0)
336 goto done;
337 /* Array is frozen */
338
2eba8496
N
339 rd1 -= mdi->array.level == 6 ? 2 : 1;
340 rd2 -= mdi->array.level == 6 ? 2 : 1;
341 sysfs_get_str(mdi, NULL, "reshape_direction", buf, sizeof(buf));
342 if (strncmp(buf, "back", 4) == 0)
343 backwards = 1;
e3e0d0a8
N
344 if (sysfs_get_ll(mdi, NULL, "reshape_position", &position) != 0) {
345 /* reshape must have finished now */
346 sysfs_set_str(mdi, NULL, "sync_action", "idle");
347 goto done;
348 }
2eba8496
N
349 sysfs_get_two(mdi, NULL, "chunk_size", &chunk1, &chunk2);
350 chunk1 /= 512;
351 chunk2 /= 512;
352 rddiv = GCD(rd1, rd2);
353 chunkdiv = GCD(chunk1, chunk2);
354 sectors = (chunk1/chunkdiv) * chunk2 * (rd1/rddiv) * rd2;
355
356 if (backwards) {
357 /* Need to subtract 'reshape_position' from
358 * array size to get equivalent of sync_max.
359 * Size calculation based on raid5_size in kernel.
360 */
361 unsigned long long size = mdi->component_size;
362 size &= ~(chunk1-1);
363 size &= ~(chunk2-1);
364 /* rd1 must be smaller */
932be627
N
365 /* Reshape may have progressed further backwards than
366 * recorded, so target even further back (hence "-1")
367 */
5509dc44 368 position = (position / sectors - 1) * sectors;
932be627
N
369 /* rd1 is always the conversion factor between 'sync'
370 * position and 'reshape' position.
371 * We read 1 "new" stripe worth of data from where-ever,
372 * and when write out that full stripe.
373 */
5509dc44 374 sync_max = size - position/rd1;
2eba8496 375 } else {
932be627
N
376 /* Reshape will very likely be beyond position, and it may
377 * be too late to stop at '+1', so aim for '+2'
378 */
5509dc44
N
379 position = (position / sectors + 2) * sectors;
380 sync_max = position/rd1;
2eba8496 381 }
5509dc44
N
382 if (sysfs_get_ll(mdi, NULL, "sync_max", &old_sync_max) < 0)
383 old_sync_max = mdi->component_size;
384 /* Must not advance sync_max as that could confuse
385 * the reshape monitor */
386 if (sync_max < old_sync_max)
387 sysfs_set_num(mdi, NULL, "sync_max", sync_max);
2eba8496
N
388 sysfs_set_str(mdi, NULL, "sync_action", "idle");
389
390 /* That should have set things going again. Now we
3afaff93 391 * wait a little while (3 second max) for sync_completed
2eba8496 392 * to reach the target.
3afaff93
N
393 * The reshape process can block for 500msec if
394 * the sync speed limit is hit, so we need to wait
395 * a lot longer than that. 1 second is usually
396 * enough. 3 is safe.
2eba8496 397 */
3afaff93 398 delay = 3000;
2eba8496 399 scfd = sysfs_open(mdi->sys_name, NULL, "sync_completed");
3afaff93 400 while (scfd >= 0 && delay > 0 && old_sync_max > 0) {
30ddba7d 401 unsigned long long max_completed;
5509dc44 402 sysfs_get_ll(mdi, NULL, "reshape_position", &curr);
2eba8496 403 sysfs_fd_get_str(scfd, buf, sizeof(buf));
3afaff93
N
404 if (strncmp(buf, "none", 4) == 0) {
405 /* Either reshape has aborted, or hasn't
406 * quite started yet. Wait a bit and
407 * check 'sync_action' to see.
408 */
239b3cc0 409 sleep_for(0, MSEC_TO_NSEC(10), true);
3afaff93
N
410 sysfs_get_str(mdi, NULL, "sync_action", buf, sizeof(buf));
411 if (strncmp(buf, "reshape", 7) != 0)
412 break;
413 }
5509dc44 414
30ddba7d
N
415 if (sysfs_fd_get_two(scfd, &completed,
416 &max_completed) == 2 &&
417 /* 'completed' sometimes reads as max-uulong */
418 completed < max_completed &&
5509dc44
N
419 (completed > sync_max ||
420 (completed == sync_max && curr != position))) {
421 while (completed > sync_max) {
422 sync_max += sectors / rd1;
423 if (backwards)
424 position -= sectors;
425 else
426 position += sectors;
427 }
428 if (sync_max < old_sync_max)
429 sysfs_set_num(mdi, NULL, "sync_max", sync_max);
430 }
431
2eba8496
N
432 if (!backwards && curr >= position)
433 break;
434 if (backwards && curr <= position)
435 break;
436 sysfs_wait(scfd, &delay);
437 }
438 if (scfd >= 0)
439 close(scfd);
440
441 }
e3e0d0a8 442done:
2eba8496 443
fe7e0e64
N
444 /* As we have an O_EXCL open, any use of the device
445 * which blocks STOP_ARRAY is probably a transient use,
446 * so it is reasonable to retry for a while - 5 seconds.
447 */
448 count = 25; err = 0;
fc54fe7a
JS
449 while (count && fd >= 0 &&
450 (err = ioctl(fd, STOP_ARRAY, NULL)) < 0 && errno == EBUSY) {
239b3cc0 451 sleep_for(0, MSEC_TO_NSEC(200), true);
fe7e0e64
N
452 count --;
453 }
454 if (fd >= 0 && err) {
455 if (verbose >= 0) {
456 pr_err("failed to stop array %s: %s\n",
457 devname, strerror(errno));
458 if (errno == EBUSY)
7a862a02 459 cont_err("Perhaps a running process, mounted filesystem or active volume group?\n");
4ccad7b1 460 }
fe7e0e64
N
461 rv = 1;
462 goto out;
463 }
229e66cb 464
fe7e0e64
N
465 if (devnm[0] && use_udev()) {
466 struct map_ent *mp = map_by_devnm(&map, devnm);
467 remove_devices(devnm, mp ? mp->path : NULL);
682c7051 468 }
fe7e0e64
N
469
470 if (verbose >= 0)
471 pr_err("stopped %s\n", devname);
472 map_lock(&map);
473 map_remove(&map, devnm);
474 map_unlock(&map);
475out:
6e8d27e7 476 sysfs_free(mdi);
fe7e0e64 477
bccd8153 478 return rv;
64c4757e
NB
479}
480
5e73b024
N
481static struct mddev_dev *add_one(struct mddev_dev *dv, char *name, char disp)
482{
483 struct mddev_dev *new;
484 new = xmalloc(sizeof(*new));
485 memset(new, 0, sizeof(*new));
486 new->devname = xstrdup(name);
487 new->disposition = disp;
488 new->next = dv->next;
489 dv->next = new;
490 return new;
491}
492
1d997643
N
493static void add_faulty(struct mddev_dev *dv, int fd, char disp)
494{
495 mdu_array_info_t array;
496 mdu_disk_info_t disk;
497 int remaining_disks;
498 int i;
499
9cd39f01 500 if (md_get_array_info(fd, &array) != 0)
1d997643
N
501 return;
502
503 remaining_disks = array.nr_disks;
504 for (i = 0; i < MAX_DISKS && remaining_disks > 0; i++) {
1d997643
N
505 char buf[40];
506 disk.number = i;
d97572f5 507 if (md_get_disk_info(fd, &disk) != 0)
1d997643
N
508 continue;
509 if (disk.major == 0 && disk.minor == 0)
510 continue;
511 remaining_disks--;
512 if ((disk.state & 1) == 0) /* not faulty */
513 continue;
514 sprintf(buf, "%d:%d", disk.major, disk.minor);
5e73b024 515 dv = add_one(dv, buf, disp);
1d997643
N
516 }
517}
518
519static void add_detached(struct mddev_dev *dv, int fd, char disp)
520{
521 mdu_array_info_t array;
522 mdu_disk_info_t disk;
523 int remaining_disks;
524 int i;
525
9cd39f01 526 if (md_get_array_info(fd, &array) != 0)
1d997643
N
527 return;
528
529 remaining_disks = array.nr_disks;
530 for (i = 0; i < MAX_DISKS && remaining_disks > 0; i++) {
1d997643
N
531 char buf[40];
532 int sfd;
533 disk.number = i;
d97572f5 534 if (md_get_disk_info(fd, &disk) != 0)
1d997643
N
535 continue;
536 if (disk.major == 0 && disk.minor == 0)
537 continue;
538 remaining_disks--;
539 if (disp == 'f' && (disk.state & 1) != 0) /* already faulty */
540 continue;
541 sprintf(buf, "%d:%d", disk.major, disk.minor);
542 sfd = dev_open(buf, O_RDONLY);
543 if (sfd >= 0) {
544 /* Not detached */
545 close(sfd);
546 continue;
547 }
548 if (errno != ENXIO)
549 /* Probably not detached */
550 continue;
5e73b024 551 dv = add_one(dv, buf, disp);
1d997643
N
552 }
553}
554
64a78416
N
555static void add_set(struct mddev_dev *dv, int fd, char set_char)
556{
557 mdu_array_info_t array;
558 mdu_disk_info_t disk;
559 int remaining_disks;
560 int copies, set;
561 int i;
562
9cd39f01 563 if (md_get_array_info(fd, &array) != 0)
64a78416
N
564 return;
565 if (array.level != 10)
566 return;
567 copies = ((array.layout & 0xff) *
568 ((array.layout >> 8) & 0xff));
569 if (array.raid_disks % copies)
570 return;
571
572 remaining_disks = array.nr_disks;
573 for (i = 0; i < MAX_DISKS && remaining_disks > 0; i++) {
574 char buf[40];
575 disk.number = i;
d97572f5 576 if (md_get_disk_info(fd, &disk) != 0)
64a78416
N
577 continue;
578 if (disk.major == 0 && disk.minor == 0)
579 continue;
580 remaining_disks--;
581 set = disk.raid_disk % copies;
582 if (set_char != set + 'A')
583 continue;
584 sprintf(buf, "%d:%d", disk.major, disk.minor);
585 dv = add_one(dv, buf, dv->disposition);
586 }
587}
588
abe94694
N
589int attempt_re_add(int fd, int tfd, struct mddev_dev *dv,
590 struct supertype *dev_st, struct supertype *tst,
f2e8393b
MK
591 unsigned long rdev, enum update_opt update,
592 char *devname, int verbose, mdu_array_info_t *array)
abe94694
N
593{
594 struct mdinfo mdi;
595 int duuid[4];
596 int ouuid[4];
597
598 dev_st->ss->getinfo_super(dev_st, &mdi, NULL);
599 dev_st->ss->uuid_from_super(dev_st, ouuid);
600 if (tst->sb)
601 tst->ss->uuid_from_super(tst, duuid);
602 else
603 /* Assume uuid matches: kernel will check */
604 memcpy(duuid, ouuid, sizeof(ouuid));
605 if ((mdi.disk.state & (1<<MD_DISK_ACTIVE)) &&
606 !(mdi.disk.state & (1<<MD_DISK_FAULTY)) &&
607 memcmp(duuid, ouuid, sizeof(ouuid))==0) {
608 /* Looks like it is worth a
609 * try. Need to make sure
610 * kernel will accept it
611 * though.
612 */
613 mdu_disk_info_t disc;
abe94694 614 disc.number = mdi.disk.number;
d97572f5
JS
615 if (md_get_disk_info(fd, &disc) != 0 ||
616 disc.major != 0 || disc.minor != 0)
abe94694
N
617 goto skip_re_add;
618 disc.major = major(rdev);
619 disc.minor = minor(rdev);
620 disc.number = mdi.disk.number;
621 disc.raid_disk = mdi.disk.raid_disk;
622 disc.state = mdi.disk.state;
bff96f73
GJ
623 if (array->state & (1 << MD_SB_CLUSTERED)) {
624 /* extra flags are needed when adding to a cluster as
625 * there are two cases to distinguish
626 */
627 if (dv->disposition == 'c')
628 disc.state |= (1 << MD_DISK_CANDIDATE);
629 else
630 disc.state |= (1 << MD_DISK_CLUSTER_ADD);
631 }
e22fe3ae 632 if (dv->writemostly == FlagSet)
abe94694 633 disc.state |= 1 << MD_DISK_WRITEMOSTLY;
e22fe3ae 634 if (dv->writemostly == FlagClear)
abe94694 635 disc.state &= ~(1 << MD_DISK_WRITEMOSTLY);
e22fe3ae 636 if (dv->failfast == FlagSet)
71574efb 637 disc.state |= 1 << MD_DISK_FAILFAST;
e22fe3ae 638 if (dv->failfast == FlagClear)
71574efb 639 disc.state &= ~(1 << MD_DISK_FAILFAST);
abe94694 640 remove_partitions(tfd);
d7be7d87
JS
641 if (update || dv->writemostly != FlagDefault ||
642 dv->failfast != FlagDefault) {
abe94694
N
643 int rv = -1;
644 tfd = dev_open(dv->devname, O_RDWR);
645 if (tfd < 0) {
7a862a02 646 pr_err("failed to open %s for superblock update during re-add\n", dv->devname);
abe94694
N
647 return -1;
648 }
649
e22fe3ae 650 if (dv->writemostly == FlagSet)
abe94694 651 rv = dev_st->ss->update_super(
03312b52 652 dev_st, NULL, UOPT_SPEC_WRITEMOSTLY,
abe94694 653 devname, verbose, 0, NULL);
e22fe3ae 654 if (dv->writemostly == FlagClear)
abe94694 655 rv = dev_st->ss->update_super(
03312b52 656 dev_st, NULL, UOPT_SPEC_READWRITE,
abe94694 657 devname, verbose, 0, NULL);
e22fe3ae 658 if (dv->failfast == FlagSet)
71574efb 659 rv = dev_st->ss->update_super(
03312b52 660 dev_st, NULL, UOPT_SPEC_FAILFAST,
71574efb 661 devname, verbose, 0, NULL);
e22fe3ae 662 if (dv->failfast == FlagClear)
71574efb 663 rv = dev_st->ss->update_super(
03312b52 664 dev_st, NULL, UOPT_SPEC_NOFAILFAST,
71574efb 665 devname, verbose, 0, NULL);
abe94694
N
666 if (update)
667 rv = dev_st->ss->update_super(
f2e8393b 668 dev_st, NULL, update,
abe94694
N
669 devname, verbose, 0, NULL);
670 if (rv == 0)
671 rv = dev_st->ss->store_super(dev_st, tfd);
672 close(tfd);
673 if (rv != 0) {
7a862a02 674 pr_err("failed to update superblock during re-add\n");
abe94694
N
675 return -1;
676 }
677 }
678 /* don't even try if disk is marked as faulty */
679 errno = 0;
680 if (ioctl(fd, ADD_NEW_DISK, &disc) == 0) {
681 if (verbose >= 0)
682 pr_err("re-added %s\n", dv->devname);
683 return 1;
684 }
685 if (errno == ENOMEM || errno == EROFS) {
686 pr_err("add new device failed for %s: %s\n",
687 dv->devname, strerror(errno));
688 if (dv->disposition == 'M')
689 return 0;
690 return -1;
691 }
692 }
693skip_re_add:
694 return 0;
695}
696
38aeaf3a
N
697int Manage_add(int fd, int tfd, struct mddev_dev *dv,
698 struct supertype *tst, mdu_array_info_t *array,
699 int force, int verbose, char *devname,
f2e8393b
MK
700 enum update_opt update, unsigned long rdev,
701 unsigned long long array_size, int raid_slot)
38aeaf3a
N
702{
703 unsigned long long ldsize;
fbd3e15c 704 struct supertype *dev_st;
38aeaf3a
N
705 int j;
706 mdu_disk_info_t disc;
707
708 if (!get_dev_size(tfd, dv->devname, &ldsize)) {
709 if (dv->disposition == 'M')
710 return 0;
711 else
712 return -1;
713 }
714
632dc30c 715 if (tst->ss == &super0 && ldsize > 4ULL*1024*1024*1024*1024) {
7ccc4cc4 716 /* More than 4TB is wasted on v0.90 */
38aeaf3a 717 if (!force) {
7a862a02
N
718 pr_err("%s is larger than %s can effectively use.\n"
719 " Add --force is you really want to add this device.\n",
38aeaf3a
N
720 dv->devname, devname);
721 return -1;
722 }
7a862a02
N
723 pr_err("%s is larger than %s can effectively use.\n"
724 " Adding anyway as --force was given.\n",
38aeaf3a
N
725 dv->devname, devname);
726 }
38aeaf3a
N
727
728 if (array->not_persistent == 0 || tst->ss->external) {
729
730 /* need to find a sample superblock to copy, and
731 * a spare slot to use.
732 * For 'external' array (well, container based),
733 * We can just load the metadata for the array->
734 */
735 int array_failed;
736 if (tst->sb)
737 /* already loaded */;
738 else if (tst->ss->external) {
739 tst->ss->load_container(tst, fd, NULL);
740 } else for (j = 0; j < tst->max_devs; j++) {
741 char *dev;
742 int dfd;
743 disc.number = j;
d97572f5 744 if (md_get_disk_info(fd, &disc))
38aeaf3a
N
745 continue;
746 if (disc.major==0 && disc.minor==0)
747 continue;
748 if ((disc.state & 4)==0) /* sync */
749 continue;
750 /* Looks like a good device to try */
751 dev = map_dev(disc.major, disc.minor, 1);
752 if (!dev)
753 continue;
754 dfd = dev_open(dev, O_RDONLY);
755 if (dfd < 0)
756 continue;
757 if (tst->ss->load_super(tst, dfd,
758 NULL)) {
759 close(dfd);
760 continue;
761 }
762 close(dfd);
763 break;
764 }
765 /* FIXME this is a bad test to be using */
fc54fe7a
JS
766 if (!tst->sb && (dv->disposition != 'a' &&
767 dv->disposition != 'S')) {
38aeaf3a
N
768 /* we are re-adding a device to a
769 * completely dead array - have to depend
770 * on kernel to check
771 */
772 } else if (!tst->sb) {
773 pr_err("cannot load array metadata from %s\n", devname);
774 return -1;
775 }
776
777 /* Make sure device is large enough */
01290056
SL
778 if (dv->disposition != 'j' && /* skip size check for Journal */
779 tst->sb &&
2609f339 780 tst->ss->avail_size(tst, ldsize/512, INVALID_SECTORS) <
38aeaf3a
N
781 array_size) {
782 if (dv->disposition == 'M')
783 return 0;
784 pr_err("%s not large enough to join array\n",
785 dv->devname);
786 return -1;
787 }
788
789 /* Possibly this device was recently part of
790 * the array and was temporarily removed, and
791 * is now being re-added. If so, we can
792 * simply re-add it.
793 */
794
fbd3e15c 795 if (array->not_persistent == 0) {
38aeaf3a
N
796 dev_st = dup_super(tst);
797 dev_st->ss->load_super(dev_st, tfd, NULL);
fbd3e15c
JS
798 if (dev_st->sb && dv->disposition != 'S') {
799 int rv;
800
801 rv = attempt_re_add(fd, tfd, dv, dev_st, tst,
802 rdev, update, devname,
803 verbose, array);
804 dev_st->ss->free_super(dev_st);
f6feb3fb
GM
805 if (rv) {
806 free(dev_st);
fbd3e15c 807 return rv;
f6feb3fb
GM
808 }
809 }
810 if (dev_st) {
811 dev_st->ss->free_super(dev_st);
812 free(dev_st);
fbd3e15c 813 }
38aeaf3a
N
814 }
815 if (dv->disposition == 'M') {
816 if (verbose > 0)
817 pr_err("--re-add for %s to %s is not possible\n",
818 dv->devname, devname);
819 return 0;
820 }
821 if (dv->disposition == 'A') {
822 pr_err("--re-add for %s to %s is not possible\n",
823 dv->devname, devname);
824 return -1;
825 }
826 if (array->active_disks < array->raid_disks) {
827 char *avail = xcalloc(array->raid_disks, 1);
828 int d;
829 int found = 0;
830
d180d2aa 831 for (d = 0; d < MAX_DISKS && found < array->nr_disks; d++) {
38aeaf3a 832 disc.number = d;
d97572f5 833 if (md_get_disk_info(fd, &disc))
38aeaf3a
N
834 continue;
835 if (disc.major == 0 && disc.minor == 0)
836 continue;
837 if (!(disc.state & (1<<MD_DISK_SYNC)))
838 continue;
839 avail[disc.raid_disk] = 1;
d31d0f52 840 found++;
38aeaf3a
N
841 }
842 array_failed = !enough(array->level, array->raid_disks,
843 array->layout, 1, avail);
6157951f 844 free(avail);
38aeaf3a
N
845 } else
846 array_failed = 0;
847 if (array_failed) {
848 pr_err("%s has failed so using --add cannot work and might destroy\n",
849 devname);
850 pr_err("data on %s. You should stop the array and re-assemble it.\n",
851 dv->devname);
852 return -1;
853 }
854 } else {
855 /* non-persistent. Must ensure that new drive
856 * is at least array->size big.
857 */
858 if (ldsize/512 < array_size) {
859 pr_err("%s not large enough to join array\n",
860 dv->devname);
861 return -1;
862 }
863 }
864 /* committed to really trying this device now*/
865 remove_partitions(tfd);
866
867 /* in 2.6.17 and earlier, version-1 superblocks won't
868 * use the number we write, but will choose a free number.
869 * we must choose the same free number, which requires
870 * starting at 'raid_disks' and counting up
871 */
872 for (j = array->raid_disks; j < tst->max_devs; j++) {
873 disc.number = j;
d97572f5 874 if (md_get_disk_info(fd, &disc))
38aeaf3a
N
875 break;
876 if (disc.major==0 && disc.minor==0)
877 break;
878 if (disc.state & 8) /* removed */
879 break;
880 }
881 disc.major = major(rdev);
882 disc.minor = minor(rdev);
4de90913
GJ
883 if (raid_slot < 0)
884 disc.number = j;
885 else
886 disc.number = raid_slot;
38aeaf3a 887 disc.state = 0;
01290056
SL
888
889 /* only add journal to array that supports journaling */
890 if (dv->disposition == 'j') {
01290056
SL
891 struct mdinfo *mdp;
892
893 mdp = sysfs_read(fd, NULL, GET_ARRAY_STATE);
2a1990c0
JS
894 if (!mdp) {
895 pr_err("%s unable to read array state.\n", devname);
896 return -1;
897 }
01290056 898
5e4ca8bb 899 if (mdp->array_state != ARRAY_READONLY) {
d209181d 900 sysfs_free(mdp);
01290056
SL
901 pr_err("%s is not readonly, cannot add journal.\n", devname);
902 return -1;
903 }
904
d209181d
JS
905 sysfs_free(mdp);
906
38c2e05b 907 disc.raid_disk = 0;
01290056
SL
908 }
909
38aeaf3a
N
910 if (array->not_persistent==0) {
911 int dfd;
01290056
SL
912 if (dv->disposition == 'j')
913 disc.state |= (1 << MD_DISK_JOURNAL) | (1 << MD_DISK_SYNC);
e22fe3ae 914 if (dv->writemostly == FlagSet)
38aeaf3a 915 disc.state |= 1 << MD_DISK_WRITEMOSTLY;
e22fe3ae 916 if (dv->failfast == FlagSet)
71574efb 917 disc.state |= 1 << MD_DISK_FAILFAST;
38aeaf3a
N
918 dfd = dev_open(dv->devname, O_RDWR | O_EXCL|O_DIRECT);
919 if (tst->ss->add_to_super(tst, &disc, dfd,
72ca9bcf 920 dv->devname, INVALID_SECTORS))
38aeaf3a
N
921 return -1;
922 if (tst->ss->write_init_super(tst))
923 return -1;
924 } else if (dv->disposition == 'A') {
925 /* this had better be raid1.
926 * As we are "--re-add"ing we must find a spare slot
927 * to fill.
928 */
929 char *used = xcalloc(array->raid_disks, 1);
930 for (j = 0; j < tst->max_devs; j++) {
931 mdu_disk_info_t disc2;
932 disc2.number = j;
d97572f5 933 if (md_get_disk_info(fd, &disc2))
38aeaf3a
N
934 continue;
935 if (disc2.major==0 && disc2.minor==0)
936 continue;
937 if (disc2.state & 8) /* removed */
938 continue;
939 if (disc2.raid_disk < 0)
940 continue;
941 if (disc2.raid_disk > array->raid_disks)
942 continue;
943 used[disc2.raid_disk] = 1;
944 }
945 for (j = 0 ; j < array->raid_disks; j++)
946 if (!used[j]) {
947 disc.raid_disk = j;
948 disc.state |= (1<<MD_DISK_SYNC);
949 break;
950 }
951 free(used);
952 }
4de90913
GJ
953
954 if (array->state & (1 << MD_SB_CLUSTERED)) {
955 if (dv->disposition == 'c')
956 disc.state |= (1 << MD_DISK_CANDIDATE);
957 else
958 disc.state |= (1 << MD_DISK_CLUSTER_ADD);
959 }
960
e22fe3ae 961 if (dv->writemostly == FlagSet)
38aeaf3a 962 disc.state |= (1 << MD_DISK_WRITEMOSTLY);
e22fe3ae 963 if (dv->failfast == FlagSet)
71574efb 964 disc.state |= (1 << MD_DISK_FAILFAST);
38aeaf3a
N
965 if (tst->ss->external) {
966 /* add a disk
967 * to an external metadata container */
968 struct mdinfo new_mdi;
969 struct mdinfo *sra;
970 int container_fd;
4dd2df09 971 char devnm[32];
38aeaf3a
N
972 int dfd;
973
4dd2df09
N
974 strcpy(devnm, fd2devnm(fd));
975
976 container_fd = open_dev_excl(devnm);
38aeaf3a 977 if (container_fd < 0) {
7a862a02 978 pr_err("add failed for %s: could not get exclusive access to container\n",
38aeaf3a
N
979 dv->devname);
980 tst->ss->free_super(tst);
981 return -1;
982 }
983
1f5d54a0
MT
984 /* Check if metadata handler is able to accept the drive */
985 if (!tst->ss->validate_geometry(tst, LEVEL_CONTAINER, 0, 1, NULL,
986 0, 0, dv->devname, NULL, 0, 1)) {
987 close(container_fd);
988 return -1;
989 }
990
9cf9a1de 991 Kill(dv->devname, NULL, 0, -1, 0);
38aeaf3a 992 dfd = dev_open(dv->devname, O_RDWR | O_EXCL|O_DIRECT);
38aeaf3a 993 if (tst->ss->add_to_super(tst, &disc, dfd,
72ca9bcf 994 dv->devname, INVALID_SECTORS)) {
38aeaf3a
N
995 close(dfd);
996 close(container_fd);
997 return -1;
998 }
12724c01 999 if (!mdmon_running(tst->container_devnm))
38aeaf3a
N
1000 tst->ss->sync_metadata(tst);
1001
4dd2df09 1002 sra = sysfs_read(container_fd, NULL, 0);
38aeaf3a
N
1003 if (!sra) {
1004 pr_err("add failed for %s: sysfs_read failed\n",
1005 dv->devname);
1006 close(container_fd);
1007 tst->ss->free_super(tst);
1008 return -1;
1009 }
1010 sra->array.level = LEVEL_CONTAINER;
1011 /* Need to set data_offset and component_size */
1012 tst->ss->getinfo_super(tst, &new_mdi, NULL);
1013 new_mdi.disk.major = disc.major;
1014 new_mdi.disk.minor = disc.minor;
1015 new_mdi.recovery_start = 0;
1016 /* Make sure fds are closed as they are O_EXCL which
1017 * would block add_disk */
1018 tst->ss->free_super(tst);
1019 if (sysfs_add_disk(sra, &new_mdi, 0) != 0) {
7a862a02 1020 pr_err("add new device to external metadata failed for %s\n", dv->devname);
38aeaf3a
N
1021 close(container_fd);
1022 sysfs_free(sra);
1023 return -1;
1024 }
4dd2df09 1025 ping_monitor(devnm);
38aeaf3a
N
1026 sysfs_free(sra);
1027 close(container_fd);
1028 } else {
1029 tst->ss->free_super(tst);
1030 if (ioctl(fd, ADD_NEW_DISK, &disc)) {
01290056
SL
1031 if (dv->disposition == 'j')
1032 pr_err("Failed to hot add %s as journal, "
1033 "please try restart %s.\n", dv->devname, devname);
1034 else
1035 pr_err("add new device failed for %s as %d: %s\n",
1036 dv->devname, j, strerror(errno));
38aeaf3a
N
1037 return -1;
1038 }
01290056
SL
1039 if (dv->disposition == 'j') {
1040 pr_err("Journal added successfully, making %s read-write\n", devname);
1041 if (Manage_ro(devname, fd, -1))
1042 pr_err("Failed to make %s read-write\n", devname);
1043 }
1044
38aeaf3a
N
1045 }
1046 if (verbose >= 0)
1047 pr_err("added %s\n", dv->devname);
1048 return 1;
1049}
1050
d070235d 1051int Manage_remove(struct supertype *tst, int fd, struct mddev_dev *dv,
1ab9ed2a 1052 int sysfd, unsigned long rdev, int force, int verbose, char *devname)
d070235d
N
1053{
1054 int lfd = -1;
1055 int err;
1056
1057 if (tst->ss->external) {
1058 /* To remove a device from a container, we must
1059 * check that it isn't in use in an array.
1060 * This involves looking in the 'holders'
1061 * directory - there must be just one entry,
1062 * the container.
1063 * To ensure that it doesn't get used as a
1064 * hot spare while we are checking, we
1065 * get an O_EXCL open on the container
1066 */
aab15415 1067 int ret;
4dd2df09
N
1068 char devnm[32];
1069 strcpy(devnm, fd2devnm(fd));
1070 lfd = open_dev_excl(devnm);
d070235d 1071 if (lfd < 0) {
7a862a02 1072 pr_err("Cannot get exclusive access to container - odd\n");
d070235d
N
1073 return -1;
1074 }
aab15415
N
1075 /* We may not be able to check on holders in
1076 * sysfs, either because we don't have the dev num
1077 * (rdev == 0) or because the device has been detached
1078 * and the 'holders' directory no longer exists
1079 * (ret == -1). In that case, assume it is OK to
1080 * remove.
d070235d 1081 */
aab15415
N
1082 if (rdev == 0)
1083 ret = -1;
c922221e
TM
1084 else {
1085 /*
1086 * The drive has already been set to 'faulty', however
1087 * monitor might not have had time to process it and the
1088 * drive might still have an entry in the 'holders'
1089 * directory. Try a few times to avoid a false error
1090 */
1091 int count = 20;
1092
1093 do {
1094 ret = sysfs_unique_holder(devnm, rdev);
1095 if (ret < 2)
1096 break;
239b3cc0 1097 sleep_for(0, MSEC_TO_NSEC(100), true);
c922221e
TM
1098 } while (--count > 0);
1099
1100 if (ret == 0) {
1101 pr_err("%s is not a member, cannot remove.\n",
1102 dv->devname);
1103 close(lfd);
1104 return -1;
1105 }
1106 if (ret >= 2) {
1107 pr_err("%s is still in use, cannot remove.\n",
1108 dv->devname);
1109 close(lfd);
1110 return -1;
1111 }
d070235d
N
1112 }
1113 }
1114 /* FIXME check that it is a current member */
1115 if (sysfd >= 0) {
1116 /* device has been removed and we don't know
1117 * the major:minor number
1118 */
1ab9ed2a 1119 err = sys_hot_remove_disk(sysfd, force);
d070235d 1120 } else {
1ab9ed2a 1121 err = hot_remove_disk(fd, rdev, force);
d070235d
N
1122 if (err && errno == ENODEV) {
1123 /* Old kernels rejected this if no personality
1124 * is registered */
4dd2df09 1125 struct mdinfo *sra = sysfs_read(fd, NULL, GET_DEVS);
d070235d
N
1126 struct mdinfo *dv = NULL;
1127 if (sra)
1128 dv = sra->devs;
1129 for ( ; dv ; dv=dv->next)
1130 if (dv->disk.major == (int)major(rdev) &&
1131 dv->disk.minor == (int)minor(rdev))
1132 break;
1133 if (dv)
1134 err = sysfs_set_str(sra, dv,
1135 "state", "remove");
1136 else
1137 err = -1;
6e8d27e7 1138 sysfs_free(sra);
d070235d
N
1139 }
1140 }
1141 if (err) {
7a862a02 1142 pr_err("hot remove failed for %s: %s\n", dv->devname,
d070235d
N
1143 strerror(errno));
1144 if (lfd >= 0)
1145 close(lfd);
1146 return -1;
1147 }
1148 if (tst->ss->external) {
1149 /*
1150 * Before dropping our exclusive open we make an
1151 * attempt at preventing mdmon from seeing an
1152 * 'add' event before reconciling this 'remove'
1153 * event.
1154 */
4dd2df09 1155 char *devnm = fd2devnm(fd);
d070235d 1156
4dd2df09 1157 if (!devnm) {
d070235d
N
1158 pr_err("unable to get container name\n");
1159 return -1;
1160 }
1161
4dd2df09 1162 ping_manager(devnm);
d070235d
N
1163 }
1164 if (lfd >= 0)
1165 close(lfd);
1166 if (verbose >= 0)
1167 pr_err("hot removed %s from %s\n",
1168 dv->devname, devname);
1169 return 1;
1170}
1171
70c55e36
N
1172int Manage_replace(struct supertype *tst, int fd, struct mddev_dev *dv,
1173 unsigned long rdev, int verbose, char *devname)
1174{
1175 struct mdinfo *mdi, *di;
1176 if (tst->ss->external) {
1177 pr_err("--replace only supported for native metadata (0.90 or 1.x)\n");
1178 return -1;
1179 }
1180 /* Need to find the device in sysfs and add 'want_replacement' to the
1181 * status.
1182 */
4dd2df09 1183 mdi = sysfs_read(fd, NULL, GET_DEVS);
70c55e36
N
1184 if (!mdi || !mdi->devs) {
1185 pr_err("Cannot find status of %s to enable replacement - strange\n",
1186 devname);
1187 return -1;
1188 }
1189 for (di = mdi->devs; di; di = di->next)
1190 if (di->disk.major == (int)major(rdev) &&
1191 di->disk.minor == (int)minor(rdev))
1192 break;
1193 if (di) {
1194 int rv;
1195 if (di->disk.raid_disk < 0) {
1196 pr_err("%s is not active and so cannot be replaced.\n",
1197 dv->devname);
1198 sysfs_free(mdi);
1199 return -1;
1200 }
1201 rv = sysfs_set_str(mdi, di,
1202 "state", "want_replacement");
1203 if (rv) {
1204 sysfs_free(mdi);
1205 pr_err("Failed to request replacement for %s\n",
1206 dv->devname);
1207 return -1;
1208 }
1209 if (verbose >= 0)
1210 pr_err("Marked %s (device %d in %s) for replacement\n",
1211 dv->devname, di->disk.raid_disk, devname);
1212 /* If there is a matching 'with', we need to tell it which
1213 * raid disk
1214 */
1215 while (dv && dv->disposition != 'W')
1216 dv = dv->next;
1217 if (dv) {
1218 dv->disposition = 'w';
1219 dv->used = di->disk.raid_disk;
1220 }
1221 return 1;
1222 }
1223 sysfs_free(mdi);
1224 pr_err("%s not found in %s so cannot --replace it\n",
1225 dv->devname, devname);
1226 return -1;
1227}
1228
1229int Manage_with(struct supertype *tst, int fd, struct mddev_dev *dv,
1230 unsigned long rdev, int verbose, char *devname)
1231{
1232 struct mdinfo *mdi, *di;
1233 /* try to set 'slot' for 'rdev' in 'fd' to 'dv->used' */
4dd2df09 1234 mdi = sysfs_read(fd, NULL, GET_DEVS|GET_STATE);
70c55e36
N
1235 if (!mdi || !mdi->devs) {
1236 pr_err("Cannot find status of %s to enable replacement - strange\n",
1237 devname);
1238 return -1;
1239 }
1240 for (di = mdi->devs; di; di = di->next)
1241 if (di->disk.major == (int)major(rdev) &&
1242 di->disk.minor == (int)minor(rdev))
1243 break;
1244 if (di) {
1245 int rv;
1246 if (di->disk.state & (1<<MD_DISK_FAULTY)) {
1247 pr_err("%s is faulty and cannot be a replacement\n",
1248 dv->devname);
1249 sysfs_free(mdi);
1250 return -1;
1251 }
1252 if (di->disk.raid_disk >= 0) {
1253 pr_err("%s is active and cannot be a replacement\n",
1254 dv->devname);
1255 sysfs_free(mdi);
1256 return -1;
1257 }
1258 rv = sysfs_set_num(mdi, di,
1259 "slot", dv->used);
1260 if (rv) {
1261 sysfs_free(mdi);
51425978 1262 pr_err("Failed to set %s as preferred replacement.\n",
70c55e36
N
1263 dv->devname);
1264 return -1;
1265 }
1266 if (verbose >= 0)
1267 pr_err("Marked %s in %s as replacement for device %d\n",
1268 dv->devname, devname, dv->used);
1269 return 1;
1270 }
1271 sysfs_free(mdi);
1272 pr_err("%s not found in %s so cannot make it preferred replacement\n",
1273 dv->devname, devname);
1274 return -1;
1275}
1276
fc6fd406
MK
1277/**
1278 * is_remove_safe() - Check if remove is safe.
1279 * @array: Array info.
1280 * @fd: Array file descriptor.
1281 * @devname: Name of device to remove.
1282 * @verbose: Verbose.
1283 *
1284 * The function determines if array will be operational
1285 * after removing &devname.
1286 *
1287 * Return: True if array will be operational, false otherwise.
1288 */
1289bool is_remove_safe(mdu_array_info_t *array, const int fd, char *devname, const int verbose)
1290{
1291 dev_t devid = devnm2devid(devname + 5);
1292 struct mdinfo *mdi = sysfs_read(fd, NULL, GET_DEVS | GET_DISKS | GET_STATE);
1293
1294 if (!mdi) {
1295 if (verbose)
1296 pr_err("Failed to read sysfs attributes for %s\n", devname);
1297 return false;
1298 }
1299
1300 char *avail = xcalloc(array->raid_disks, sizeof(char));
1301
1302 for (mdi = mdi->devs; mdi; mdi = mdi->next) {
1303 if (mdi->disk.raid_disk < 0)
1304 continue;
1305 if (!(mdi->disk.state & (1 << MD_DISK_SYNC)))
1306 continue;
1307 if (makedev(mdi->disk.major, mdi->disk.minor) == devid)
1308 continue;
1309 avail[mdi->disk.raid_disk] = 1;
1310 }
1311 sysfs_free(mdi);
1312
1313 bool is_enough = enough(array->level, array->raid_disks,
b3e7b7eb 1314 array->layout, 1, avail);
fc6fd406
MK
1315
1316 free(avail);
1317 return is_enough;
1318}
1319
36a70782
KT
1320/**
1321 * Manage_subdevs() - Execute operation depending on devmode.
1322 *
1323 * @devname: name of the device.
1324 * @fd: file descriptor.
1325 * @devlist: list of sub-devices to manage.
1326 * @verbose: verbose level.
1327 * @test: test flag.
1328 * @update: type of update.
1329 * @force: force flag.
1330 *
1331 * This function executes operation defined by devmode
1332 * for each dev from devlist.
1333 * Devmode can be:
1334 * 'a' - add the device
1335 * 'S' - add the device as a spare - don't try re-add
1336 * 'j' - add the device as a journal device
1337 * 'A' - re-add the device
1338 * 'r' - remove the device: HOT_REMOVE_DISK
1339 * device can be 'faulty' or 'detached' in which case all
1340 * matching devices are removed.
1341 * 'f' - set the device faulty SET_DISK_FAULTY
1342 * device can be 'detached' in which case any device that
1343 * is inaccessible will be marked faulty.
1344 * 'I' - remove device by using incremental fail
1345 * which is executed when device is removed surprisingly.
1346 * 'R' - mark this device as wanting replacement.
1347 * 'W' - this device is added if necessary and activated as
1348 * a replacement for a previous 'R' device.
1349 * -----
1350 * 'w' - 'W' will be changed to 'w' when it is paired with
1351 * a 'R' device. If a 'W' is found while walking the list
1352 * it must be unpaired, and is an error.
1353 * 'M' - this is created by a 'missing' target. It is a slight
1354 * variant on 'A'
1355 * 'F' - Another variant of 'A', where the device was faulty
1356 * so must be removed from the array first.
1357 * 'c' - confirm the device as found (for clustered environments)
1358 *
1359 * For 'f' and 'r', the device can also be a kernel-internal
1360 * name such as 'sdb'.
1361 *
1362 * Return: 0 on success, otherwise 1 or 2.
1363 */
64c4757e 1364int Manage_subdevs(char *devname, int fd,
833bb0f8 1365 struct mddev_dev *devlist, int verbose, int test,
f2e8393b 1366 enum update_opt update, int force)
cd29a5c8 1367{
682c7051 1368 mdu_array_info_t array;
7a3be72f 1369 unsigned long long array_size;
1d997643 1370 struct mddev_dev *dv;
cfad27a9 1371 int tfd = -1;
f6feb3fb 1372 struct supertype *tst = NULL;
4725bc31 1373 char *subarray = NULL;
98d27e39 1374 int sysfd = -1;
7d2e6486 1375 int count = 0; /* number of actions taken */
9f584691 1376 struct mdinfo info;
9465f170 1377 struct mdinfo devinfo;
9f584691 1378 int frozen = 0;
8af530b0 1379 int busy = 0;
4de90913 1380 int raid_slot = -1;
682c7051 1381
dae13137
JS
1382 if (sysfs_init(&info, fd, NULL)) {
1383 pr_err("sysfs not availabile for %s\n", devname);
1384 goto abort;
1385 }
1386
9cd39f01
JS
1387 if (md_get_array_info(fd, &array)) {
1388 pr_err("Cannot get array info for %s\n", devname);
bcbb3112 1389 goto abort;
682c7051 1390 }
7bd04da9 1391 /* array.size is only 32 bits and may be truncated.
7a3be72f
NB
1392 * So read from sysfs if possible, and record number of sectors
1393 */
1394
1395 array_size = get_component_size(fd);
1396 if (array_size <= 0)
1397 array_size = array.size * 2;
1398
4725bc31 1399 tst = super_by_fd(fd, &subarray);
3da92f27 1400 if (!tst) {
e7b84f9d 1401 pr_err("unsupport array - version %d.%d\n",
3da92f27 1402 array.major_version, array.minor_version);
bcbb3112 1403 goto abort;
3da92f27
NB
1404 }
1405
38aeaf3a 1406 for (dv = devlist; dv; dv = dv->next) {
ffaf1a7e 1407 dev_t rdev = 0; /* device to add/remove etc */
38aeaf3a 1408 int rv;
b47024f1 1409 int mj,mn;
4a39c6f2 1410
4de90913
GJ
1411 raid_slot = -1;
1412 if (dv->disposition == 'c') {
1413 rv = parse_cluster_confirm_arg(dv->devname,
1414 &dv->devname,
1415 &raid_slot);
d7a49369 1416 if (rv) {
4de90913
GJ
1417 pr_err("Could not get the devname of cluster\n");
1418 goto abort;
1419 }
1420 }
1421
1d997643
N
1422 if (strcmp(dv->devname, "failed") == 0 ||
1423 strcmp(dv->devname, "faulty") == 0) {
fc54fe7a 1424 if (dv->disposition != 'A' && dv->disposition != 'r') {
7a862a02 1425 pr_err("%s only meaningful with -r or --re-add, not -%c\n",
b80da661 1426 dv->devname, dv->disposition);
bcbb3112 1427 goto abort;
b80da661 1428 }
262e3b7f
N
1429 add_faulty(dv, fd, (dv->disposition == 'A'
1430 ? 'F' : 'r'));
1d997643
N
1431 continue;
1432 }
1433 if (strcmp(dv->devname, "detached") == 0) {
b80da661 1434 if (dv->disposition != 'r' && dv->disposition != 'f') {
7a862a02 1435 pr_err("%s only meaningful with -r of -f, not -%c\n",
b80da661 1436 dv->devname, dv->disposition);
bcbb3112 1437 goto abort;
b80da661 1438 }
1d997643
N
1439 add_detached(dv, fd, dv->disposition);
1440 continue;
1441 }
1442
1443 if (strcmp(dv->devname, "missing") == 0) {
e9ddbb2b 1444 struct mddev_dev *add_devlist;
1d997643 1445 struct mddev_dev **dp;
4de90913
GJ
1446 if (dv->disposition == 'c') {
1447 rv = ioctl(fd, CLUSTERED_DISK_NACK, NULL);
1448 break;
1449 }
1450
c8e1a230 1451 if (dv->disposition != 'A') {
7a862a02 1452 pr_err("'missing' only meaningful with --re-add\n");
bcbb3112 1453 goto abort;
a4e13010 1454 }
1d997643 1455 add_devlist = conf_get_devs();
a4e13010 1456 if (add_devlist == NULL) {
8e5b52cd 1457 pr_err("no devices to scan for missing members.\n");
a4e13010
N
1458 continue;
1459 }
1d997643 1460 for (dp = &add_devlist; *dp; dp = & (*dp)->next)
7bd04da9 1461 /* 'M' (for 'missing') is like 'A' without errors */
1d997643
N
1462 (*dp)->disposition = 'M';
1463 *dp = dv->next;
1464 dv->next = add_devlist;
1465 continue;
1466 }
1467
64a78416
N
1468 if (strncmp(dv->devname, "set-", 4) == 0 &&
1469 strlen(dv->devname) == 5) {
1470 int copies;
1471
1472 if (dv->disposition != 'r' &&
1473 dv->disposition != 'f') {
1474 pr_err("'%s' only meaningful with -r or -f\n",
1475 dv->devname);
1476 goto abort;
1477 }
1478 if (array.level != 10) {
1479 pr_err("'%s' only meaningful with RAID10 arrays\n",
1480 dv->devname);
1481 goto abort;
1482 }
1483 copies = ((array.layout & 0xff) *
1484 ((array.layout >> 8) & 0xff));
1485 if (array.raid_disks % copies != 0 ||
1486 dv->devname[4] < 'A' ||
1487 dv->devname[4] >= 'A' + copies ||
1488 copies > 26) {
1489 pr_err("'%s' not meaningful with this array\n",
1490 dv->devname);
1491 goto abort;
1492 }
1493 add_set(dv, fd, dv->devname[4]);
1494 continue;
1495 }
1496
1d997643 1497 if (strchr(dv->devname, '/') == NULL &&
aab15415
N
1498 strchr(dv->devname, ':') == NULL &&
1499 strlen(dv->devname) < 50) {
98d27e39
N
1500 /* Assume this is a kernel-internal name like 'sda1' */
1501 int found = 0;
1502 char dname[55];
461fae7e
KT
1503 if (dv->disposition != 'r' && dv->disposition != 'f' &&
1504 dv->disposition != 'I') {
1505 pr_err("%s only meaningful with -r, -f or -I, not -%c\n",
98d27e39 1506 dv->devname, dv->disposition);
bcbb3112 1507 goto abort;
98d27e39
N
1508 }
1509
1510 sprintf(dname, "dev-%s", dv->devname);
4dd2df09 1511 sysfd = sysfs_open(fd2devnm(fd), dname, "block/dev");
98d27e39
N
1512 if (sysfd >= 0) {
1513 char dn[20];
98d27e39
N
1514 if (sysfs_fd_get_str(sysfd, dn, 20) > 0 &&
1515 sscanf(dn, "%d:%d", &mj,&mn) == 2) {
5dffd09d 1516 rdev = makedev(mj,mn);
98d27e39
N
1517 found = 1;
1518 }
1519 close(sysfd);
1520 sysfd = -1;
1521 }
1522 if (!found) {
4dd2df09 1523 sysfd = sysfs_open(fd2devnm(fd), dname, "state");
98d27e39 1524 if (sysfd < 0) {
7a862a02 1525 pr_err("%s does not appear to be a component of %s\n",
98d27e39 1526 dv->devname, devname);
bcbb3112 1527 goto abort;
98d27e39
N
1528 }
1529 }
fc54fe7a
JS
1530 } else if ((dv->disposition == 'r' ||
1531 dv->disposition == 'f') &&
1532 get_maj_min(dv->devname, &mj, &mn)) {
b47024f1
N
1533 /* for 'fail' and 'remove', the device might
1534 * not exist.
1535 */
1536 rdev = makedev(mj, mn);
b80da661 1537 } else {
c7b47447 1538 tfd = dev_open(dv->devname, O_RDONLY);
cc5083d1 1539 if (tfd >= 0) {
0a6bff09 1540 fstat_is_blkdev(tfd, dv->devname, &rdev);
cc5083d1
JS
1541 close(tfd);
1542 } else {
5fe7f5f7 1543 int open_err = errno;
9e04ac1c 1544 if (!stat_is_blkdev(dv->devname, &rdev)) {
5fe7f5f7
N
1545 if (dv->disposition == 'M')
1546 /* non-fatal. Also improbable */
1547 continue;
5fe7f5f7
N
1548 goto abort;
1549 }
1550 if (dv->disposition == 'r')
1551 /* Be happy, the stat worked, that is
1552 * enough for --remove
1553 */
1554 ;
1555 else {
1d997643
N
1556 if (dv->disposition == 'M')
1557 /* non-fatal */
1558 continue;
839f27a3 1559 pr_err("Cannot open %s: %s\n",
5fe7f5f7 1560 dv->devname, strerror(open_err));
bcbb3112 1561 goto abort;
5a9de8db 1562 }
b80da661 1563 }
682c7051 1564 }
cd29a5c8 1565 switch(dv->disposition){
682c7051 1566 default:
e7b84f9d 1567 pr_err("internal error - devmode[%s]=%d\n",
c913b90e 1568 dv->devname, dv->disposition);
bcbb3112 1569 goto abort;
682c7051 1570 case 'a':
f33a71f1 1571 case 'S': /* --add-spare */
01290056 1572 case 'j': /* --add-journal */
c8e1a230 1573 case 'A':
262e3b7f
N
1574 case 'M': /* --re-add missing */
1575 case 'F': /* --re-add faulty */
4de90913 1576 case 'c': /* --cluster-confirm */
4a39c6f2 1577 /* add the device */
4725bc31 1578 if (subarray) {
7a862a02 1579 pr_err("Cannot add disks to a \'member\' array, perform this operation on the parent container\n");
bcbb3112 1580 goto abort;
f94d52f4 1581 }
9465f170
GJ
1582
1583 /* Let's first try to write re-add to sysfs */
1584 if (rdev != 0 &&
1585 (dv->disposition == 'A' || dv->disposition == 'F')) {
1586 sysfs_init_dev(&devinfo, rdev);
1587 if (sysfs_set_str(&info, &devinfo, "state", "re-add") == 0) {
1588 pr_err("re-add %s to %s succeed\n",
1589 dv->devname, info.sys_name);
1590 break;
1591 }
1592 }
1593
262e3b7f
N
1594 if (dv->disposition == 'F')
1595 /* Need to remove first */
1ab9ed2a 1596 hot_remove_disk(fd, rdev, force);
f277ce36 1597 /* Make sure it isn't in use (in 2.6 or later) */
1d997643 1598 tfd = dev_open(dv->devname, O_RDONLY|O_EXCL);
38aeaf3a
N
1599 if (tfd >= 0) {
1600 /* We know no-one else is using it. We'll
1601 * need non-exclusive access to add it, so
1602 * do that now.
1603 */
1604 close(tfd);
1605 tfd = dev_open(dv->devname, O_RDONLY);
1011e834 1606 }
0fbf459d 1607 if (tfd < 0) {
1d997643
N
1608 if (dv->disposition == 'M')
1609 continue;
e7b84f9d 1610 pr_err("Cannot open %s: %s\n",
d7eaf49f 1611 dv->devname, strerror(errno));
bcbb3112 1612 goto abort;
d7eaf49f 1613 }
9f584691
N
1614 if (!frozen) {
1615 if (sysfs_freeze_array(&info) == 1)
1616 frozen = 1;
1617 else
1618 frozen = -1;
1619 }
38aeaf3a
N
1620 rv = Manage_add(fd, tfd, dv, tst, &array,
1621 force, verbose, devname, update,
4de90913 1622 rdev, array_size, raid_slot);
38aeaf3a
N
1623 close(tfd);
1624 tfd = -1;
1625 if (rv < 0)
bcbb3112 1626 goto abort;
38aeaf3a
N
1627 if (rv > 0)
1628 count++;
682c7051
NB
1629 break;
1630
1631 case 'r':
1632 /* hot remove */
4725bc31 1633 if (subarray) {
7a862a02 1634 pr_err("Cannot remove disks from a \'member\' array, perform this operation on the parent container\n");
d070235d
N
1635 rv = -1;
1636 } else
1637 rv = Manage_remove(tst, fd, dv, sysfd,
1ab9ed2a 1638 rdev, verbose, force,
d070235d
N
1639 devname);
1640 if (sysfd >= 0)
98d27e39 1641 close(sysfd);
d070235d
N
1642 sysfd = -1;
1643 if (rv < 0)
bcbb3112 1644 goto abort;
d070235d
N
1645 if (rv > 0)
1646 count++;
682c7051
NB
1647 break;
1648
1649 case 'f': /* set faulty */
fc6fd406
MK
1650 if (!is_remove_safe(&array, fd, dv->devname, verbose)) {
1651 pr_err("Cannot remove %s from %s, array will be failed.\n",
1652 dv->devname, devname);
1653 if (sysfd >= 0)
1654 close(sysfd);
1655 goto abort;
1656 }
461fae7e 1657 case 'I': /* incremental fail */
98d27e39
N
1658 if ((sysfd >= 0 && write(sysfd, "faulty", 6) != 6) ||
1659 (sysfd < 0 && ioctl(fd, SET_DISK_FAULTY,
5dffd09d 1660 rdev))) {
8af530b0
N
1661 if (errno == EBUSY)
1662 busy = 1;
e7b84f9d 1663 pr_err("set device faulty failed for %s: %s\n",
1d997643 1664 dv->devname, strerror(errno));
98d27e39
N
1665 if (sysfd >= 0)
1666 close(sysfd);
bcbb3112 1667 goto abort;
682c7051 1668 }
98d27e39
N
1669 if (sysfd >= 0)
1670 close(sysfd);
1671 sysfd = -1;
7d2e6486 1672 count++;
dab6685f 1673 if (verbose >= 0)
e7b84f9d 1674 pr_err("set %s faulty in %s\n",
1d997643 1675 dv->devname, devname);
682c7051 1676 break;
70c55e36
N
1677 case 'R': /* Mark as replaceable */
1678 if (subarray) {
7a862a02 1679 pr_err("Cannot replace disks in a \'member\' array, perform this operation on the parent container\n");
70c55e36
N
1680 rv = -1;
1681 } else {
1682 if (!frozen) {
1683 if (sysfs_freeze_array(&info) == 1)
1684 frozen = 1;
1685 else
1686 frozen = -1;
1687 }
1688 rv = Manage_replace(tst, fd, dv,
5dffd09d 1689 rdev, verbose,
70c55e36
N
1690 devname);
1691 }
1692 if (rv < 0)
1693 goto abort;
1694 if (rv > 0)
1695 count++;
1696 break;
1697 case 'W': /* --with device that doesn't match */
1698 pr_err("No matching --replace device for --with %s\n",
1699 dv->devname);
1700 goto abort;
1701 case 'w': /* --with device which was matched */
1702 rv = Manage_with(tst, fd, dv,
5dffd09d 1703 rdev, verbose, devname);
70c55e36
N
1704 if (rv < 0)
1705 goto abort;
1706 break;
682c7051
NB
1707 }
1708 }
f6feb3fb 1709 free(tst);
9f584691
N
1710 if (frozen > 0)
1711 sysfs_set_str(&info, NULL, "sync_action","idle");
7d2e6486
N
1712 if (test && count == 0)
1713 return 2;
682c7051 1714 return 0;
bcbb3112
N
1715
1716abort:
f6feb3fb 1717 free(tst);
9f584691
N
1718 if (frozen > 0)
1719 sysfs_set_str(&info, NULL, "sync_action","idle");
8af530b0 1720 return !test && busy ? 2 : 1;
64c4757e 1721}
1f48664b
NB
1722
1723int autodetect(void)
1724{
1725 /* Open any md device, and issue the RAID_AUTORUN ioctl */
1726 int rv = 1;
1727 int fd = dev_open("9:0", O_RDONLY);
1728 if (fd >= 0) {
1729 if (ioctl(fd, RAID_AUTORUN, 0) == 0)
1730 rv = 0;
1731 close(fd);
1732 }
1733 return rv;
1734}
aa534678 1735
f2e8393b
MK
1736int Update_subarray(char *dev, char *subarray, enum update_opt update,
1737 struct mddev_ident *ident, int verbose)
aa534678
DW
1738{
1739 struct supertype supertype, *st = &supertype;
1740 int fd, rv = 2;
70f1ff42 1741 struct mdinfo *info = NULL;
f2e8393b 1742 char *update_verb = map_num(update_options, update);
aa534678
DW
1743
1744 memset(st, 0, sizeof(*st));
aa534678 1745
ba728be7 1746 fd = open_subarray(dev, subarray, st, verbose < 0);
aa534678
DW
1747 if (fd < 0)
1748 return 2;
1749
1750 if (!st->ss->update_subarray) {
ba728be7 1751 if (verbose >= 0)
e7b84f9d
N
1752 pr_err("Operation not supported for %s metadata\n",
1753 st->ss->name);
aa534678
DW
1754 goto free_super;
1755 }
1756
db10eab6
MK
1757 if (is_subarray_active(subarray, st->devnm)) {
1758 if (verbose >= 0)
1759 pr_err("Subarray %s in %s is active, cannot update %s\n",
f2e8393b 1760 subarray, dev, update_verb);
db10eab6
MK
1761 goto free_super;
1762 }
1763
4dd2df09 1764 if (mdmon_running(st->devnm))
aa534678
DW
1765 st->update_tail = &st->updates;
1766
70f1ff42
LF
1767 info = st->ss->container_content(st, subarray);
1768
f2e8393b 1769 if (update == UOPT_PPL && !is_level456(info->array.level)) {
70f1ff42
LF
1770 pr_err("RWH policy ppl is supported only for raid4, raid5 and raid6.\n");
1771 goto free_super;
1772 }
1773
f2e8393b 1774 rv = st->ss->update_subarray(st, subarray, update, ident);
aa534678
DW
1775
1776 if (rv) {
ba728be7 1777 if (verbose >= 0)
e7b84f9d 1778 pr_err("Failed to update %s of subarray-%s in %s\n",
f2e8393b 1779 update_verb, subarray, dev);
aa534678
DW
1780 } else if (st->update_tail)
1781 flush_metadata_updates(st);
1782 else
1783 st->ss->sync_metadata(st);
1784
f2e8393b 1785 if (rv == 0 && update == UOPT_NAME && verbose >= 0)
e7b84f9d
N
1786 pr_err("Updated subarray-%s name from %s, UUIDs may have changed\n",
1787 subarray, dev);
aa534678 1788
70f1ff42
LF
1789free_super:
1790 if (info)
1791 free(info);
aa534678
DW
1792 st->ss->free_super(st);
1793 close(fd);
1794
1795 return rv;
1796}
d52bb542 1797
7bd04da9
N
1798/* Move spare from one array to another If adding to destination array fails
1799 * add back to original array.
d52bb542
AC
1800 * Returns 1 on success, 0 on failure */
1801int move_spare(char *from_devname, char *to_devname, dev_t devid)
1802{
1803 struct mddev_dev devlist;
1804 char devname[20];
1805
1806 /* try to remove and add */
1807 int fd1 = open(to_devname, O_RDONLY);
1808 int fd2 = open(from_devname, O_RDONLY);
1809
1810 if (fd1 < 0 || fd2 < 0) {
9cf361f8
JS
1811 if (fd1 >= 0)
1812 close(fd1);
1813 if (fd2 >= 0)
1814 close(fd2);
d52bb542
AC
1815 return 0;
1816 }
1817
1818 devlist.next = NULL;
1819 devlist.used = 0;
e22fe3ae
N
1820 devlist.writemostly = FlagDefault;
1821 devlist.failfast = FlagDefault;
d52bb542
AC
1822 devlist.devname = devname;
1823 sprintf(devname, "%d:%d", major(devid), minor(devid));
1824
1825 devlist.disposition = 'r';
f2e8393b 1826 if (Manage_subdevs(from_devname, fd2, &devlist, -1, 0, UOPT_UNDEFINED, 0) == 0) {
d52bb542 1827 devlist.disposition = 'a';
9cf361f8 1828 if (Manage_subdevs(to_devname, fd1, &devlist, -1, 0,
f2e8393b 1829 UOPT_UNDEFINED, 0) == 0) {
d52bb542
AC
1830 /* make sure manager is aware of changes */
1831 ping_manager(to_devname);
1832 ping_manager(from_devname);
1833 close(fd1);
1834 close(fd2);
1835 return 1;
1836 }
9cf361f8
JS
1837 else
1838 Manage_subdevs(from_devname, fd2, &devlist,
f2e8393b 1839 -1, 0, UOPT_UNDEFINED, 0);
d52bb542
AC
1840 }
1841 close(fd1);
1842 close(fd2);
1843 return 0;
1844}