/*
* mdmon - monitor external metadata arrays
*
- * Copyright (C) 2007-2008 Neil Brown <neilb@suse.de>
- * Copyright (C) 2007-2008 Intel Corporation
+ * Copyright (C) 2007-2009 Neil Brown <neilb@suse.de>
+ * 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,
{
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,
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);
* 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;
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;
* 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;
if (i == di->disk.raid_disk)
break;
- if (di) {
+ if (di && newd) {
memcpy(newd, di, sizeof(*newd));
newd->state_fd = sysfs_open(new->devnum,
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);