#include <sys/socket.h>
+static void close_aa(struct active_array *aa)
+{
+ struct mdinfo *d;
+
+ for (d = aa->info.devs; d; d = d->next)
+ close(d->state_fd);
+
+ close(aa->action_fd);
+ close(aa->info.state_fd);
+ close(aa->resync_start_fd);
+ close(aa->sync_pos_fd);
+}
+
static void free_aa(struct active_array *aa)
{
- /* Note that this doesn't close fds, as they may be in used
- * by a clone. Use close_aa for that.
+ /* Note that this doesn't close fds if they are being used
+ * by a clone. ->container will be set for a clone
*/
+ if (!aa->container)
+ close_aa(aa);
while (aa->info.devs) {
struct mdinfo *d = aa->info.devs;
aa->info.devs = d->next;
free(aa);
}
+static void write_wakeup(struct supertype *c)
+{
+ write(c->pipe[1], "PING", 4);
+}
+
static void replace_array(struct supertype *container,
struct active_array *old,
struct active_array *new)
new->replaces = old;
new->next = container->arrays;
container->arrays = new;
+ write_wakeup(container);
}
}
-static void write_wakeup(struct supertype *c)
-{
- write(c->pipe[1], "PING", 4);
-}
-
static void manage_new(struct mdstat_ent *mdstat,
- struct supertype *container)
+ struct supertype *container,
+ struct active_array *victim)
{
/* A new array has appeared in this container.
* Hopefully it is already recorded in the metadata.
* Mark it to be ignored by setting container to NULL
*/
new->container = NULL;
- replace_array(container, NULL, new);
+ replace_array(container, victim, new);
return;
}
if (container->ss->open_new(container, new, inst) < 0) {
// FIXME close all those files
new->container = NULL;
- replace_array(container, NULL, new);
+ replace_array(container, victim, new);
return;
}
- replace_array(container, NULL, new);
- write_wakeup(container);
+ replace_array(container, victim, new);
return;
}
break;
}
}
- if (a == NULL)
- manage_new(mdstat, container);
+ if (a == NULL || !a->container)
+ manage_new(mdstat, container, a);
}
}
static int read_and_act(struct active_array *a)
{
int check_degraded;
+ int deactivate = 0;
struct mdinfo *mdi;
a->next_state = bad_word;
get_sync_pos(a);
a->container->ss->mark_clean(a, a->sync_pos);
a->next_state = clear;
+ deactivate = 1;
}
if (a->curr_state == write_pending) {
a->container->ss->mark_dirty(a);
mdi->next_state = 0;
}
+ if (deactivate)
+ a->container = NULL;
+
return 1;
}
for (a = aa ; a ; a = a->next) {
struct mdinfo *mdi;
+ /* once an array has been deactivated only the manager
+ * thread can make us care about it again
+ */
+ if (!a->container)
+ continue;
+
add_fd(&rfds, &maxfd, a->info.state_fd);
add_fd(&rfds, &maxfd, a->action_fd);
for (mdi = a->info.devs ; mdi ; mdi = mdi->next)
}
for (a = aa; a ; a = a->next) {
- if (a->replaces) {
+ if (a->replaces && !discard_this) {
struct active_array **ap;
for (ap = &a->next; *ap && *ap != a->replaces;
ap = & (*ap)->next)
discard_this = a->replaces;
a->replaces = NULL;
}
- rv += read_and_act(a);
+ if (a->container)
+ rv += read_and_act(a);
}
return rv;
}