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