summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeil Brown <neilb@suse.de>2008-05-27 09:18:39 +1000
committerNeil Brown <neilb@suse.de>2008-05-27 09:18:39 +1000
commit1ed3f38758ff23dabfa3f67e2a02ff98d9d0fea8 (patch)
tree4adad57c7c06f3ac2ef8508fc911f256fa77df7b
parent7a7cc50430d0d99dfe9b802e9723537360abf9d9 (diff)
downloadmdadm-1ed3f38758ff23dabfa3f67e2a02ff98d9d0fea8.tar.gz
mdadm-1ed3f38758ff23dabfa3f67e2a02ff98d9d0fea8.tar.xz
mdadm-1ed3f38758ff23dabfa3f67e2a02ff98d9d0fea8.zip
Remove stopped arrays.
When an array becomes inactive, clean up and forget it. This involves signalling the manager.
-rw-r--r--managemon.c45
-rw-r--r--mdadm.h2
-rw-r--r--mdmon.c6
-rw-r--r--mdstat.c5
-rw-r--r--monitor.c42
5 files changed, 76 insertions, 24 deletions
diff --git a/managemon.c b/managemon.c
index c771104..aa10a99 100644
--- a/managemon.c
+++ b/managemon.c
@@ -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);
}
diff --git a/mdadm.h b/mdadm.h
index 5ff66cd..20ed452 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 c8a3341..7ba8be0 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 a65e7c3..040df15 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 a630c93..ead96d9 100644
--- a/monitor.c
+++ b/monitor.c
@@ -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);