+/*
+ * mdmon - monitor external metadata arrays
+ *
+ * Copyright (C) 2007-2008 Neil Brown <neilb@suse.de>
+ * Copyright (C) 2007-2008 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
#include "mdadm.h"
#include "mdmon.h"
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);
+ int fd = open_dev_excl(container->devnum);
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 */