X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=managemon.c;h=3835c995cfa8803ac135a005581ef0a6feb32d73;hb=603f24a05f48063a7239e323e2aeab497cb0feb6;hp=c9b054ff4a0605953a28792a463e959a067c24f1;hpb=6c766cf10178b9bae4ddcfd6b8de2d70f9d84568;p=thirdparty%2Fmdadm.git diff --git a/managemon.c b/managemon.c index c9b054ff..3835c995 100644 --- a/managemon.c +++ b/managemon.c @@ -241,7 +241,9 @@ static void add_disk_to_container(struct supertype *st, struct mdinfo *sd) { int dfd; char nm[20]; + struct supertype *st2; struct metadata_update *update = NULL; + struct mdinfo info; mdu_disk_info_t dk = { .number = -1, .major = sd->disk.major, @@ -253,11 +255,33 @@ static void add_disk_to_container(struct supertype *st, struct mdinfo *sd) dprintf("%s: add %d:%d to container\n", __func__, sd->disk.major, sd->disk.minor); + sd->next = st->devs; + st->devs = sd; + sprintf(nm, "%d:%d", sd->disk.major, sd->disk.minor); dfd = dev_open(nm, O_RDWR); if (dfd < 0) return; + /* Check the metadata and see if it is already part of this + * array + */ + st2 = dup_super(st); + if (st2->ss->load_super(st2, dfd, NULL) == 0) { + st2->ss->getinfo_super(st, &info); + if (st->ss->compare_super(st, st2) == 0 && + info.disk.raid_disk >= 0) { + /* Looks like a good member of array. + * Just accept it. + * mdadm will incorporate any parts into + * active arrays. + */ + st2->ss->free_super(st2); + return; + } + } + st2->ss->free_super(st2); + st->update_tail = &update; st->ss->add_to_super(st, &dk, dfd, NULL); st->ss->write_init_super(st); @@ -283,7 +307,7 @@ static void manage_container(struct mdstat_ent *mdstat, * To see what is removed and what is added. * These need to be remove from, or added to, the array */ - mdi = sysfs_read(-1, mdstat->devnum, GET_DEVS); + mdi = sysfs_read(-1, mdstat->devnum, GET_DEVS|SKIP_GONE_DEVS); if (!mdi) { /* invalidate the current count so we can try again */ container->devcnt = -1; @@ -313,8 +337,16 @@ static void manage_container(struct mdstat_ent *mdstat, if (di->disk.major == cd->disk.major && di->disk.minor == cd->disk.minor) break; - if (!cd) - add_disk_to_container(container, di); + if (!cd) { + struct mdinfo *newd = malloc(sizeof(*newd)); + + if (!newd) { + container->devcnt = -1; + continue; + } + *newd = *di; + add_disk_to_container(container, newd); + } } sysfs_free(mdi); container->devcnt = mdstat->devcnt; @@ -363,7 +395,7 @@ static void manage_member(struct mdstat_ent *mdstat, * and open files for each newdev */ for (d = newdev; d ; d = d->next) { struct mdinfo *newd; - if (sysfs_add_disk(&newa->info, d) < 0) + if (sysfs_add_disk(&newa->info, d, 0) < 0) continue; newd = malloc(sizeof(*newd)); *newd = *d; @@ -460,7 +492,7 @@ static void manage_new(struct mdstat_ent *mdstat, if (i == di->disk.raid_disk) break; - if (di) { + if (di && newd) { memcpy(newd, di, sizeof(*newd)); newd->state_fd = sysfs_open(new->devnum, @@ -469,13 +501,16 @@ static void manage_new(struct mdstat_ent *mdstat, newd->prev_state = read_dev_state(newd->state_fd); newd->curr_state = newd->prev_state; - } else if (failed + 1 > new->info.array.failed_disks) { - /* we cannot properly monitor without all working disks */ - new->container = NULL; - break; } else { + if (newd) + free(newd); + failed++; - free(newd); + if (failed > new->info.array.failed_disks) { + /* we cannot properly monitor without all working disks */ + new->container = NULL; + break; + } continue; } sprintf(newd->sys_name, "rd%d", i);