X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=managemon.c;h=f9d545d46fbac9142c06f1ea540896a78980e01d;hb=148acb7baaa810b68d55df4c1784d6bd0dfd1b78;hp=a8af614af0be5304b9349b95eaa80226a59aeb7d;hpb=6144ed441445ee4d567614aaed78dd24148881ce;p=thirdparty%2Fmdadm.git diff --git a/managemon.c b/managemon.c index a8af614a..f9d545d4 100644 --- a/managemon.c +++ b/managemon.c @@ -1,3 +1,22 @@ +/* + * mdmon - monitor external metadata arrays + * + * Copyright (C) 2007-2009 Neil Brown + * Copyright (C) 2007-2009 Intel Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + */ /* * The management thread for monitoring active md arrays. @@ -222,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, @@ -234,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); @@ -264,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; @@ -294,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; @@ -344,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; @@ -441,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, @@ -450,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); @@ -504,13 +558,7 @@ void manage(struct mdstat_ent *mdstat, struct supertype *container) manage_container(mdstat, container); continue; } - if (mdstat->metadata_version == NULL || - strncmp(mdstat->metadata_version, "external:", 9) != 0 || - !is_subarray(mdstat->metadata_version+9) || - strncmp(mdstat->metadata_version+10, container->devname, - strlen(container->devname)) != 0 || - mdstat->metadata_version[10+strlen(container->devname)] - != '/') + if (!is_container_member(mdstat, container->devname)) /* Not for this array */ continue; /* Looks like a member of this container */