From: Dan Williams Date: Mon, 21 Dec 2009 19:51:57 +0000 (-0700) Subject: Support external metadata recovery-resume X-Git-Tag: mdadm-3.1.2~64^2~1 X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fmdadm.git;a=commitdiff_plain;h=2904b26f059c5d82d9d631c9987e92e3f9af498c;hp=d23534e4646313a67296b295666d165a87bb2c92 Support external metadata recovery-resume Minimal changes needed to permit reassembling partially recovered external metadata arrays. The biggest logical change is that ->container_content() can now surface partially rebuilt members rather than omitting them from the disk list. Signed-off-by: Dan Williams --- diff --git a/Assemble.c b/Assemble.c index 560e2fe2..014d644b 100644 --- a/Assemble.c +++ b/Assemble.c @@ -1286,7 +1286,7 @@ int assemble_container_content(struct supertype *st, int mdfd, sysfs_free(sra); for (dev = content->devs; dev; dev = dev->next) - if (sysfs_add_disk(content, dev) == 0) + if (sysfs_add_disk(content, dev, 1) == 0) working++; else if (errno == EEXIST) preexist++; diff --git a/Manage.c b/Manage.c index 6f0a6a20..df6079bf 100644 --- a/Manage.c +++ b/Manage.c @@ -697,7 +697,7 @@ int Manage_subdevs(char *devname, int fd, new_mdi.disk.major = disc.major; new_mdi.disk.minor = disc.minor; new_mdi.recovery_start = 0; - if (sysfs_add_disk(sra, &new_mdi) != 0) { + if (sysfs_add_disk(sra, &new_mdi, 0) != 0) { fprintf(stderr, Name ": add new device to external metadata" " failed for %s\n", dv->devname); close(container_fd); diff --git a/managemon.c b/managemon.c index 3a20e2b6..e3350778 100644 --- a/managemon.c +++ b/managemon.c @@ -410,7 +410,7 @@ static void manage_member(struct mdstat_ent *mdstat, newd = malloc(sizeof(*newd)); if (!newd) continue; - if (sysfs_add_disk(&newa->info, d) < 0) { + if (sysfs_add_disk(&newa->info, d, 0) < 0) { free(newd); continue; } diff --git a/mdadm.h b/mdadm.h index af6d91b2..27ef6937 100644 --- a/mdadm.h +++ b/mdadm.h @@ -385,7 +385,7 @@ extern int sysfs_get_str(struct mdinfo *sra, struct mdinfo *dev, char *name, char *val, int size); extern int sysfs_set_safemode(struct mdinfo *sra, unsigned long ms); extern int sysfs_set_array(struct mdinfo *info, int vers); -extern int sysfs_add_disk(struct mdinfo *sra, struct mdinfo *sd); +extern int sysfs_add_disk(struct mdinfo *sra, struct mdinfo *sd, int resume); extern int sysfs_disk_to_scsi_id(int fd, __u32 *id); extern int sysfs_unique_holder(int devnum, long rdev); extern int load_sys(char *path, char *buf); diff --git a/sysfs.c b/sysfs.c index 8fdb5299..c3bbbe32 100644 --- a/sysfs.c +++ b/sysfs.c @@ -572,7 +572,7 @@ int sysfs_set_array(struct mdinfo *info, int vers) return rv; } -int sysfs_add_disk(struct mdinfo *sra, struct mdinfo *sd) +int sysfs_add_disk(struct mdinfo *sra, struct mdinfo *sd, int resume) { char dv[100]; char nm[100]; @@ -595,6 +595,13 @@ int sysfs_add_disk(struct mdinfo *sra, struct mdinfo *sd) strcpy(sd->sys_name, "dev-"); strcpy(sd->sys_name+4, dname); + /* test write to see if 'recovery_start' is available */ + if (resume && sd->recovery_start < MaxSector && + sysfs_set_num(sra, sd, "recovery_start", 0)) { + sysfs_set_str(sra, sd, "state", "remove"); + return -1; + } + rv = sysfs_set_num(sra, sd, "offset", sd->data_offset); rv |= sysfs_set_num(sra, sd, "size", (sd->component_size+1) / 2); if (sra->array.level != LEVEL_CONTAINER) { @@ -604,6 +611,8 @@ int sysfs_add_disk(struct mdinfo *sra, struct mdinfo *sd) */ sysfs_set_str(sra, sd, "state", "insync"); rv |= sysfs_set_num(sra, sd, "slot", sd->disk.raid_disk); + if (resume) + sysfs_set_num(sra, sd, "recovery_start", sd->recovery_start); } return rv; } diff --git a/util.c b/util.c index 05be64c6..927a0ee4 100644 --- a/util.c +++ b/util.c @@ -1166,7 +1166,7 @@ int add_disk(int mdfd, struct supertype *st, info->recovery_start = MaxSector; else info->recovery_start = 0; - rv = sysfs_add_disk(sra, info); + rv = sysfs_add_disk(sra, info, 0); if (! rv) { struct mdinfo *sd2; for (sd2 = sra->devs; sd2; sd2=sd2->next)