mdmon: terminate clean

We generally don't want mdmon to be terminated, but if a SIGTERM gets
through try to leave the monitored arrays in a clean state, block
attempts to mark the array dirty, and stop servicing the socket.

When we are killed by sigterm don't remove the pidfile let that be
cleaned up by the next monitor.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
This commit is contained in:
Dan Williams 2008-10-02 06:32:08 -07:00
parent 57ed8c9155
commit 6144ed4414
4 changed files with 63 additions and 7 deletions

View File

@ -555,7 +555,7 @@ static void handle_message(struct supertype *container, struct metadata_update *
manage(mdstat, container);
free_mdstat(mdstat);
} else {
} else if (!sigterm) {
mu = malloc(sizeof(*mu));
mu->len = msg->len;
mu->buf = msg->buf;
@ -612,6 +612,7 @@ void do_manager(struct supertype *container)
sigdelset(&set, SIGUSR1);
sigdelset(&set, SIGHUP);
sigdelset(&set, SIGALRM);
sigdelset(&set, SIGTERM);
proc_fd = open("/proc/mounts", O_RDONLY);
do {
@ -647,6 +648,9 @@ void do_manager(struct supertype *container)
manager_ready = 1;
if (sigterm)
wakeup_monitor();
if (update_queue == NULL) {
if (container->sock < 0)
mdstat_wait_fd(proc_fd, &set);

19
mdmon.c
View File

@ -49,6 +49,8 @@ struct active_array *pending_discard;
int mon_tid, mgr_tid;
int sigterm;
int run_child(void *v)
{
struct supertype *c = v;
@ -87,6 +89,9 @@ int make_pidfile(char *devname, int o_excl)
int fd;
int n;
if (sigterm)
return -1;
sprintf(path, "/var/run/mdadm/%s.pid", devname);
fd = open(path, O_RDWR|O_CREAT|o_excl, 0600);
@ -138,6 +143,9 @@ void remove_pidfile(char *devname)
{
char buf[100];
if (sigterm)
return;
sprintf(buf, "/var/run/mdadm/%s.pid", devname);
unlink(buf);
sprintf(buf, "/var/run/mdadm/%s.sock", devname);
@ -151,6 +159,9 @@ int make_control_sock(char *devname)
long fl;
struct sockaddr_un addr;
if (sigterm)
return -1;
sprintf(path, "/var/run/mdadm/%s.sock", devname);
unlink(path);
sfd = socket(PF_LOCAL, SOCK_STREAM, 0);
@ -176,6 +187,11 @@ static void hup(int sig)
socket_hup_requested = 1;
}
static void term(int sig)
{
sigterm = 1;
}
static void wake_me(int sig)
{
@ -355,6 +371,7 @@ int main(int argc, char *argv[])
sigaddset(&set, SIGUSR1);
sigaddset(&set, SIGHUP);
sigaddset(&set, SIGALRM);
sigaddset(&set, SIGTERM);
sigprocmask(SIG_BLOCK, &set, NULL);
act.sa_handler = wake_me;
act.sa_flags = 0;
@ -362,6 +379,8 @@ int main(int argc, char *argv[])
sigaction(SIGALRM, &act, NULL);
act.sa_handler = hup;
sigaction(SIGHUP, &act, NULL);
act.sa_handler = term;
sigaction(SIGTERM, &act, NULL);
act.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &act, NULL);

View File

@ -50,6 +50,7 @@ void do_manager(struct supertype *container);
int make_control_sock(char *devname);
int make_pidfile(char *devname, int o_excl);
extern int socket_hup_requested;
extern int sigterm;
int read_dev_state(int fd);
int get_resync_start(struct active_array *a);

View File

@ -414,6 +414,7 @@ static int wait_and_act(struct supertype *container, int nowait)
struct active_array *a, **ap;
int rv;
struct mdinfo *mdi;
static unsigned int dirty_arrays = ~0; /* start at some non-zero value */
FD_ZERO(&rfds);
@ -442,16 +443,20 @@ static int wait_and_act(struct supertype *container, int nowait)
ap = &(*ap)->next;
}
if (manager_ready && *aap == NULL) {
/* No interesting arrays. Lets see about exiting.
* Note that blocking at this point is not a problem
* as there are no active arrays, there is nothing that
* we need to be ready to do.
if (manager_ready && (*aap == NULL || (sigterm && !dirty_arrays))) {
/* No interesting arrays, or we have been told to
* terminate and everything is clean. Lets see about
* exiting. Note that blocking at this point is not a
* problem as there are no active arrays, there is
* nothing that we need to be ready to do.
*/
int fd = open(container->device_name, O_RDONLY|O_EXCL);
if (fd >= 0 || errno != EBUSY) {
/* OK, we are safe to leave */
dprintf("no arrays to monitor... exiting\n");
if (sigterm && !dirty_arrays)
dprintf("caught sigterm, all clean... exiting\n");
else
dprintf("no arrays to monitor... exiting\n");
remove_pidfile(container->devname);
exit_now = 1;
signal_manager();
@ -487,7 +492,10 @@ static int wait_and_act(struct supertype *container, int nowait)
}
rv = 0;
dirty_arrays = 0;
for (a = *aap; a ; a = a->next) {
int is_dirty;
if (a->replaces && !discard_this) {
struct active_array **ap;
for (ap = &a->next; *ap && *ap != a->replaces;
@ -502,6 +510,30 @@ static int wait_and_act(struct supertype *container, int nowait)
}
if (a->container)
rv += read_and_act(a);
else
continue;
/* when terminating stop manipulating the array after it is
* clean, but make sure read_and_act() is given a chance to
* handle 'active_idle'
*/
switch (read_state(a->info.state_fd)) {
case active:
case active_idle:
case suspended:
case bad_word:
is_dirty = 1;
break;
default:
if (a->curr_state == active_idle)
is_dirty = 1;
else
is_dirty = 0;
break;
}
dirty_arrays += is_dirty;
if (sigterm && !is_dirty)
a->container = NULL; /* stop touching this array */
}
/* propagate failures across container members */