summaryrefslogtreecommitdiff
path: root/managemon.c
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2008-07-29 19:01:06 -0700
committerDan Williams <dan.j.williams@intel.com>2008-08-04 16:48:27 -0700
commit836759d561453e7777a233122ec6acba8663a180 (patch)
tree4dd55e3e35e031a5ec693fede27830187dc28f13 /managemon.c
parent9ca2c81c0f8bd37ef24e5e3ac898ffb6cfd00117 (diff)
mdmon: ignore inactive arrays and other manage_new() cleanups
While mdadm is constructing an array mdmon may see an intermediate state (some disks not yet added / redundancy attributes like sync_action not available). Waiting for mdstat->active == true ensures that the array is ready to be handled. This fixes a bug in create array via mdmon update whereby failures are not detected in the new array. Introduce aa_ready() to catch cases where the active_array is not correctly initialized. Barring a kernel bug this should never trigger, nonetheless it precludes a class of bugs like the one mentioned above from triggering. Cleanup the exit paths and only call replace_array when the new array is ready to be inserted into container->arrays. Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'managemon.c')
-rw-r--r--managemon.c72
1 files changed, 49 insertions, 23 deletions
diff --git a/managemon.c b/managemon.c
index c947552e..94f42962 100644
--- a/managemon.c
+++ b/managemon.c
@@ -306,6 +306,27 @@ static void manage_member(struct mdstat_ent *mdstat,
}
}
+static int aa_ready(struct active_array *aa)
+{
+ struct mdinfo *d;
+ int level = aa->info.array.level;
+
+ for (d = aa->info.devs; d; d = d->next)
+ if (d->state_fd < 0)
+ return 0;
+
+ if (aa->info.state_fd < 0)
+ return 0;
+
+ if (level > 0 && (aa->action_fd < 0 || aa->resync_start_fd < 0))
+ return 0;
+
+ if (!aa->container)
+ return 0;
+
+ return 1;
+}
+
static void manage_new(struct mdstat_ent *mdstat,
struct supertype *container,
struct active_array *victim)
@@ -321,8 +342,23 @@ static void manage_new(struct mdstat_ent *mdstat,
char *inst;
int i;
+ /* check if array is ready to be monitored */
+ if (!mdstat->active)
+ return;
+
+ mdi = sysfs_read(-1, mdstat->devnum,
+ GET_LEVEL|GET_CHUNK|GET_DISKS|GET_COMPONENT|
+ GET_DEVS|GET_OFFSET|GET_SIZE|GET_STATE);
+
new = malloc(sizeof(*new));
+ if (!new || !mdi) {
+ if (mdi)
+ sysfs_free(mdi);
+ if (new)
+ free(new);
+ return;
+ }
memset(new, 0, sizeof(*new));
new->devnum = mdstat->devnum;
@@ -335,18 +371,6 @@ static void manage_new(struct mdstat_ent *mdstat,
inst = &mdstat->metadata_version[10+strlen(container->devname)+1];
- mdi = sysfs_read(-1, new->devnum,
- GET_LEVEL|GET_CHUNK|GET_DISKS|GET_COMPONENT|
- GET_DEVS|GET_OFFSET|GET_SIZE|GET_STATE);
- if (!mdi) {
- /* Eeek. Cannot monitor this array.
- * Mark it to be ignored by setting container to NULL
- */
- new->container = NULL;
- replace_array(container, victim, new);
- return;
- }
-
new->info.array = mdi->array;
new->info.component_size = mdi->component_size;
@@ -367,15 +391,15 @@ static void manage_new(struct mdstat_ent *mdstat,
newd->prev_state = read_dev_state(newd->state_fd);
newd->curr_state = newd->prev_state;
} else {
- newd->state_fd = -1;
- newd->disk.raid_disk = i;
- newd->prev_state = DS_REMOVE;
- newd->curr_state = DS_REMOVE;
+ /* we cannot properly monitor without all raid_disks */
+ new->container = NULL;
+ break;
}
sprintf(newd->sys_name, "rd%d", i);
newd->next = new->info.devs;
new->info.devs = newd;
}
+
new->action_fd = sysfs_open(new->devnum, NULL, "sync_action");
new->info.state_fd = sysfs_open(new->devnum, NULL, "array_state");
new->resync_start_fd = sysfs_open(new->devnum, NULL, "resync_start");
@@ -384,15 +408,17 @@ static void manage_new(struct mdstat_ent *mdstat,
new->action_fd, new->info.state_fd);
sysfs_free(mdi);
- // finds and compares.
- if (container->ss->open_new(container, new, inst) < 0) {
- // FIXME close all those files
+
+ /* if everything checks out tell the metadata handler we want to
+ * manage this instance
+ */
+ if (!aa_ready(new) || container->ss->open_new(container, new, inst) < 0) {
+ fprintf(stderr, "mdmon: failed to monitor %s\n",
+ mdstat->metadata_version);
new->container = NULL;
+ free_aa(new);
+ } else
replace_array(container, victim, new);
- return;
- }
- replace_array(container, victim, new);
- return;
}
void manage(struct mdstat_ent *mdstat, struct supertype *container)