Support re-adding of old devices when assembling an array. From: NeilBrown When we assemble an array, either with -A or -I, it is possible that the kernel will reject some devices because they have old event counts. If the 'action=re-add' policy is in effect, we want to add those devices anyway on the assumption that they were only missing due to a cabling problem, and it has been fixed. So after starting the array, attempt to add each device again. Any that are members of the array will failed with -EBUSY. Others might succeed if the kernel is happy enough with them. Also disable the re-adding of devices to an active array with -I, unless 'action=re-add' is in effect. That behaviour is inconsistent with --assemble. Signed-off-by: NeilBrown array.chunk_size / 4096) + 1); } } + if (okcnt < content->array.raid_disks + && conf_get_readd()) { + /* If any devices did not get added + * because the kernel rejected them based + * on event count, try adding them again. + * The bitmap might allow them to be + * included - or they will become spares + */ + for (i=0; i<=bestcnt; i++) { + int j = best[i]; + if (j >= 0 && !devices[j].uptodate) { + rv = add_disk(mdfd, st, content, + &devices[j].i); + if (rv == 0 && verbose >= 0) + fprintf(stderr, Name ": %s has been re-added.\n", + devices[j].devname); + } + } + } wait_for(mddev, mdfd); close(mdfd); if (auto_assem) { diff --git a/Incremental.c b/Incremental.c index 1ff0731..c109267 100644 --- a/Incremental.c +++ b/Incremental.c @@ -355,6 +355,18 @@ int Incremental(char *devname, int verbose, int runstop, else strcpy(chosen_name, devnum2devname(mp->devnum)); + /* It is only OK to add drives to a running array if + * the action=re-add policy is in effect + */ + if (!conf_get_readd()) { + if (ioctl(mdfd, GET_ARRAY_INFO, &ainf) == 0) { + fprintf(stderr, Name + ": not adding %s to active array %s\n", + devname, chosen_name); + close(mdfd); + return 2; + } + } sra = sysfs_read(mdfd, fd2devnum(mdfd), (GET_DEVS | GET_STATE)); if (sra->devs) { @@ -470,7 +482,7 @@ int Incremental(char *devname, int verbose, int runstop, map_unlock(&map); if (runstop > 0 || active_disks >= info.array.working_disks) { - struct mdinfo *sra; + struct mdinfo *sra, *dsk; /* Let's try to start it */ if (match && match->bitmap_file) { int bmfd = open(match->bitmap_file, O_RDWR); @@ -491,7 +503,8 @@ int Incremental(char *devname, int verbose, int runstop, } close(bmfd); } - sra = sysfs_read(mdfd, fd2devnum(mdfd), 0); + sra = sysfs_read(mdfd, fd2devnum(mdfd), + GET_DEVS|GET_OFFSET|GET_SIZE|GET_STATE); if ((sra == NULL || active_disks >= info.array.working_disks) && trustworthy != FOREIGN) rv = ioctl(mdfd, RUN_ARRAY, NULL); @@ -511,6 +524,15 @@ int Incremental(char *devname, int verbose, int runstop, devname, chosen_name, strerror(errno)); rv = 1; } + if (conf_get_readd()) { + /* anything that just fell out could usefully be re-added */ + for (dsk = sra->devs ; dsk ; dsk = dsk->next) { + if (add_disk(mdfd, st, sra, dsk) == 0) + fprintf(stderr, Name + ": %s re-added to %s\n", + dsk->sys_name, chosen_name); + } + } } else { if (verbose >= 0) fprintf(stderr, Name