manage(mdstat, container);
free_mdstat(mdstat);
- } else {
+ } else if (!sigterm) {
mu = malloc(sizeof(*mu));
mu->len = msg->len;
mu->buf = msg->buf;
sigdelset(&set, SIGUSR1);
sigdelset(&set, SIGHUP);
sigdelset(&set, SIGALRM);
+ sigdelset(&set, SIGTERM);
proc_fd = open("/proc/mounts", O_RDONLY);
do {
manager_ready = 1;
+ if (sigterm)
+ wakeup_monitor();
+
if (update_queue == NULL) {
if (container->sock < 0)
mdstat_wait_fd(proc_fd, &set);
int mon_tid, mgr_tid;
+int sigterm;
+
int run_child(void *v)
{
struct supertype *c = v;
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);
{
char buf[100];
+ if (sigterm)
+ return;
+
sprintf(buf, "/var/run/mdadm/%s.pid", devname);
unlink(buf);
sprintf(buf, "/var/run/mdadm/%s.sock", 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);
socket_hup_requested = 1;
}
+static void term(int sig)
+{
+ sigterm = 1;
+}
+
static void wake_me(int sig)
{
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;
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);
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);
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);
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();
}
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;
}
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 */