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 "mdmon.h"
#include <sys/socket.h>
#include <signal.h>
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);
}

View File

@ -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 {

View File

@ -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;
}

View File

@ -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)

View File

@ -3,7 +3,7 @@
#include "mdmon.h"
#include <sys/select.h>
#include <signal.h>
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);