Remove stopped arrays.

When an array becomes inactive, clean up and forget it.

This involves signalling the manager.
This commit is contained in:
Neil Brown 2008-05-27 09:18:39 +10:00
parent 7a7cc50430
commit 1ed3f38758
5 changed files with 76 additions and 24 deletions

View File

@ -75,6 +75,7 @@
#include "mdadm.h" #include "mdadm.h"
#include "mdmon.h" #include "mdmon.h"
#include <sys/socket.h> #include <sys/socket.h>
#include <signal.h>
static void close_aa(struct active_array *aa) static void close_aa(struct active_array *aa)
{ {
@ -116,6 +117,17 @@ static void write_wakeup(struct supertype *c)
read(c->mon_pipe[0], &err, 1); read(c->mon_pipe[0], &err, 1);
} }
static void remove_old(void)
{
if (discard_this) {
discard_this->next = NULL;
free_aa(discard_this);
if (pending_discard == discard_this)
pending_discard = NULL;
discard_this = NULL;
}
}
static void replace_array(struct supertype *container, static void replace_array(struct supertype *container,
struct active_array *old, struct active_array *old,
struct active_array *new) struct active_array *new)
@ -126,16 +138,12 @@ static void replace_array(struct supertype *container,
* and put it on 'discard_this'. We take it from there * and put it on 'discard_this'. We take it from there
* and discard it. * and discard it.
*/ */
remove_old();
while (pending_discard) { while (pending_discard) {
write_wakeup(container);
while (discard_this == NULL) while (discard_this == NULL)
sleep(1); sleep(1);
if (discard_this != pending_discard) remove_old();
abort();
discard_this->next = NULL;
free_aa(discard_this);
discard_this = NULL;
pending_discard = NULL;
} }
pending_discard = old; pending_discard = old;
new->replaces = old; new->replaces = old;
@ -144,7 +152,6 @@ static void replace_array(struct supertype *container,
write_wakeup(container); write_wakeup(container);
} }
static void manage_container(struct mdstat_ent *mdstat, static void manage_container(struct mdstat_ent *mdstat,
struct supertype *container) struct supertype *container)
{ {
@ -368,11 +375,26 @@ void read_sock(struct supertype *container)
close(fd); close(fd);
} }
static int woke = 0;
void wake_me(int sig)
{
woke = 1;
}
void do_manager(struct supertype *container) void do_manager(struct supertype *container)
{ {
struct mdstat_ent *mdstat; struct mdstat_ent *mdstat;
sigset_t block, orig;
sigemptyset(&block);
sigaddset(&block, SIGUSR1);
signal(SIGUSR1, wake_me);
do { do {
woke = 0;
mdstat = mdstat_read(1, 0); mdstat = mdstat_read(1, 0);
manage(mdstat, container); manage(mdstat, container);
@ -381,6 +403,11 @@ void do_manager(struct supertype *container)
free_mdstat(mdstat); free_mdstat(mdstat);
mdstat_wait_fd(container->sock); remove_old();
sigprocmask(SIG_SETMASK, &block, &orig);
if (woke == 0)
mdstat_wait_fd(container->sock, &orig);
sigprocmask(SIG_SETMASK, &orig, NULL);
} while(1); } while(1);
} }

View File

@ -292,7 +292,7 @@ struct mdstat_ent {
extern struct mdstat_ent *mdstat_read(int hold, int start); extern struct mdstat_ent *mdstat_read(int hold, int start);
extern void free_mdstat(struct mdstat_ent *ms); extern void free_mdstat(struct mdstat_ent *ms);
extern void mdstat_wait(int seconds); extern void mdstat_wait(int seconds);
extern void mdstat_wait_fd(int fd); extern void mdstat_wait_fd(int fd, const sigset_t *sigmask);
extern int mddev_busy(int devnum); extern int mddev_busy(int devnum);
struct map_ent { struct map_ent {

View File

@ -48,6 +48,12 @@ struct md_generic_cmd *active_cmd;
int run_child(void *v) int run_child(void *v)
{ {
struct supertype *c = v; struct supertype *c = v;
sigset_t set;
/* SIGUSR is sent from child to parent, So child must block it */
sigemptyset(&set);
sigaddset(&set, SIGUSR1);
sigprocmask(SIG_BLOCK, &set, NULL);
do_monitor(c); do_monitor(c);
return 0; return 0;
} }

View File

@ -272,7 +272,7 @@ void mdstat_wait(int seconds)
select(mdstat_fd >2 ? mdstat_fd+1:3, NULL, NULL, &fds, &tm); select(mdstat_fd >2 ? mdstat_fd+1:3, NULL, NULL, &fds, &tm);
} }
void mdstat_wait_fd(int fd) void mdstat_wait_fd(int fd, const sigset_t *sigmask)
{ {
fd_set fds, rfds; fd_set fds, rfds;
@ -282,7 +282,8 @@ void mdstat_wait_fd(int fd)
FD_SET(mdstat_fd, &fds); FD_SET(mdstat_fd, &fds);
FD_SET(fd, &rfds); FD_SET(fd, &rfds);
select(mdstat_fd >2 ? mdstat_fd+1:3, &rfds, NULL, &fds, NULL); pselect(mdstat_fd >2 ? mdstat_fd+1:3, &rfds, NULL, &fds,
NULL, sigmask);
} }
int mddev_busy(int devnum) int mddev_busy(int devnum)

View File

@ -3,7 +3,7 @@
#include "mdmon.h" #include "mdmon.h"
#include <sys/select.h> #include <sys/select.h>
#include <signal.h>
static char *array_states[] = { static char *array_states[] = {
"clear", "inactive", "suspended", "readonly", "read-auto", "clear", "inactive", "suspended", "readonly", "read-auto",
@ -152,6 +152,10 @@ int read_dev_state(int fd)
return rv; return rv;
} }
static void signal_manager(void)
{
kill(getpid(), SIGUSR1);
}
/* Monitor a set of active md arrays - all of which share the /* Monitor a set of active md arrays - all of which share the
* same metadata - and respond to events that require * same metadata - and respond to events that require
@ -432,28 +436,41 @@ static int handle_pipe(struct md_generic_cmd *cmd, struct active_array *aa)
return -1; return -1;
} }
static int wait_and_act(struct active_array *aa, int pfd, int monfd, int nowait) static int wait_and_act(struct active_array **aap, int pfd,
int monfd, int nowait)
{ {
fd_set rfds; fd_set rfds;
int maxfd = 0; int maxfd = 0;
struct active_array *a; struct active_array *a, **ap;
int rv; int rv;
struct mdinfo *mdi; struct mdinfo *mdi;
FD_ZERO(&rfds); FD_ZERO(&rfds);
add_fd(&rfds, &maxfd, pfd); add_fd(&rfds, &maxfd, pfd);
for (a = aa ; a ; a = a->next) { for (ap = aap ; *ap ;) {
/* once an array has been deactivated only the manager a = *ap;
* thread can make us care about it again /* once an array has been deactivated we want to
* ask the manager to discard it.
*/ */
if (!a->container) if (!a->container) {
if (discard_this) {
ap = &(*ap)->next;
continue;
}
*ap = a->next;
a->next = NULL;
discard_this = a;
signal_manager();
continue; continue;
}
add_fd(&rfds, &maxfd, a->info.state_fd); add_fd(&rfds, &maxfd, a->info.state_fd);
add_fd(&rfds, &maxfd, a->action_fd); add_fd(&rfds, &maxfd, a->action_fd);
for (mdi = a->info.devs ; mdi ; mdi = mdi->next) for (mdi = a->info.devs ; mdi ; mdi = mdi->next)
add_fd(&rfds, &maxfd, mdi->state_fd); add_fd(&rfds, &maxfd, mdi->state_fd);
ap = &(*ap)->next;
} }
if (!nowait) { if (!nowait) {
@ -466,12 +483,12 @@ static int wait_and_act(struct active_array *aa, int pfd, int monfd, int nowait)
int err = -1; int err = -1;
if (read(pfd, &err, 1) > 0) if (read(pfd, &err, 1) > 0)
err = handle_pipe(active_cmd, aa); err = handle_pipe(active_cmd, *aap);
write(monfd, &err, 1); write(monfd, &err, 1);
} }
} }
for (a = aa; a ; a = a->next) { for (a = *aap; a ; a = a->next) {
if (a->replaces && !discard_this) { if (a->replaces && !discard_this) {
struct active_array **ap; struct active_array **ap;
for (ap = &a->next; *ap && *ap != a->replaces; for (ap = &a->next; *ap && *ap != a->replaces;
@ -481,18 +498,19 @@ static int wait_and_act(struct active_array *aa, int pfd, int monfd, int nowait)
*ap = (*ap)->next; *ap = (*ap)->next;
discard_this = a->replaces; discard_this = a->replaces;
a->replaces = NULL; a->replaces = NULL;
signal_manager();
} }
if (a->container) if (a->container)
rv += read_and_act(a); rv += read_and_act(a);
} }
/* propagate failures across container members */ /* propagate failures across container members */
for (a = aa; a ; a = a->next) { for (a = *aap; a ; a = a->next) {
if (!a->container) if (!a->container)
continue; continue;
for (mdi = a->info.devs ; mdi ; mdi = mdi->next) for (mdi = a->info.devs ; mdi ; mdi = mdi->next)
if (mdi->curr_state & DS_FAULTY) if (mdi->curr_state & DS_FAULTY)
reconcile_failed(aa, mdi); reconcile_failed(*aap, mdi);
} }
return rv; return rv;
@ -503,7 +521,7 @@ void do_monitor(struct supertype *container)
int rv; int rv;
int first = 1; int first = 1;
do { do {
rv = wait_and_act(container->arrays, container->mgr_pipe[0], rv = wait_and_act(&container->arrays, container->mgr_pipe[0],
container->mon_pipe[1], first); container->mon_pipe[1], first);
first = 0; first = 0;
} while (rv >= 0); } while (rv >= 0);