From 1ed3f38758ff23dabfa3f67e2a02ff98d9d0fea8 Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Tue, 27 May 2008 09:18:39 +1000 Subject: [PATCH] Remove stopped arrays. When an array becomes inactive, clean up and forget it. This involves signalling the manager. --- managemon.c | 45 ++++++++++++++++++++++++++++++++++++--------- mdadm.h | 2 +- mdmon.c | 6 ++++++ mdstat.c | 5 +++-- monitor.c | 42 ++++++++++++++++++++++++++++++------------ 5 files changed, 76 insertions(+), 24 deletions(-) diff --git a/managemon.c b/managemon.c index c7711040..aa10a993 100644 --- a/managemon.c +++ b/managemon.c @@ -75,6 +75,7 @@ #include "mdadm.h" #include "mdmon.h" #include +#include 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); } +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, struct active_array *old, 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 discard it. */ - + remove_old(); while (pending_discard) { + write_wakeup(container); while (discard_this == NULL) sleep(1); - if (discard_this != pending_discard) - abort(); - discard_this->next = NULL; - free_aa(discard_this); - discard_this = NULL; - pending_discard = NULL; + remove_old(); } pending_discard = old; new->replaces = old; @@ -144,7 +152,6 @@ static void replace_array(struct supertype *container, write_wakeup(container); } - static void manage_container(struct mdstat_ent *mdstat, struct supertype *container) { @@ -368,11 +375,26 @@ void read_sock(struct supertype *container) close(fd); } + +static int woke = 0; +void wake_me(int sig) +{ + woke = 1; +} + void do_manager(struct supertype *container) { struct mdstat_ent *mdstat; + sigset_t block, orig; + + sigemptyset(&block); + sigaddset(&block, SIGUSR1); + + signal(SIGUSR1, wake_me); do { + woke = 0; + mdstat = mdstat_read(1, 0); manage(mdstat, container); @@ -381,6 +403,11 @@ void do_manager(struct supertype *container) 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); } diff --git a/mdadm.h b/mdadm.h index 5ff66cd8..20ed4520 100644 --- a/mdadm.h +++ b/mdadm.h @@ -292,7 +292,7 @@ struct mdstat_ent { extern struct mdstat_ent *mdstat_read(int hold, int start); extern void free_mdstat(struct mdstat_ent *ms); 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); struct map_ent { diff --git a/mdmon.c b/mdmon.c index c8a3341e..7ba8be04 100644 --- a/mdmon.c +++ b/mdmon.c @@ -48,6 +48,12 @@ struct md_generic_cmd *active_cmd; int run_child(void *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); return 0; } diff --git a/mdstat.c b/mdstat.c index a65e7c3a..040df150 100644 --- a/mdstat.c +++ b/mdstat.c @@ -272,7 +272,7 @@ void mdstat_wait(int seconds) 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; @@ -282,7 +282,8 @@ void mdstat_wait_fd(int fd) FD_SET(mdstat_fd, &fds); 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) diff --git a/monitor.c b/monitor.c index a630c937..ead96d9d 100644 --- a/monitor.c +++ b/monitor.c @@ -3,7 +3,7 @@ #include "mdmon.h" #include - +#include static char *array_states[] = { "clear", "inactive", "suspended", "readonly", "read-auto", @@ -152,6 +152,10 @@ int read_dev_state(int fd) return rv; } +static void signal_manager(void) +{ + kill(getpid(), SIGUSR1); +} /* Monitor a set of active md arrays - all of which share the * 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; } -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; int maxfd = 0; - struct active_array *a; + struct active_array *a, **ap; int rv; struct mdinfo *mdi; FD_ZERO(&rfds); add_fd(&rfds, &maxfd, pfd); - for (a = aa ; a ; a = a->next) { - /* once an array has been deactivated only the manager - * thread can make us care about it again + for (ap = aap ; *ap ;) { + a = *ap; + /* 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; + } add_fd(&rfds, &maxfd, a->info.state_fd); add_fd(&rfds, &maxfd, a->action_fd); for (mdi = a->info.devs ; mdi ; mdi = mdi->next) add_fd(&rfds, &maxfd, mdi->state_fd); + + ap = &(*ap)->next; } if (!nowait) { @@ -466,12 +483,12 @@ static int wait_and_act(struct active_array *aa, int pfd, int monfd, int nowait) int err = -1; if (read(pfd, &err, 1) > 0) - err = handle_pipe(active_cmd, aa); + err = handle_pipe(active_cmd, *aap); write(monfd, &err, 1); } } - for (a = aa; a ; a = a->next) { + for (a = *aap; a ; a = a->next) { if (a->replaces && !discard_this) { struct active_array **ap; 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; discard_this = a->replaces; a->replaces = NULL; + signal_manager(); } if (a->container) rv += read_and_act(a); } /* propagate failures across container members */ - for (a = aa; a ; a = a->next) { + for (a = *aap; a ; a = a->next) { if (!a->container) continue; for (mdi = a->info.devs ; mdi ; mdi = mdi->next) if (mdi->curr_state & DS_FAULTY) - reconcile_failed(aa, mdi); + reconcile_failed(*aap, mdi); } return rv; @@ -503,7 +521,7 @@ void do_monitor(struct supertype *container) int rv; int first = 1; 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); first = 0; } while (rv >= 0); -- 2.39.2