diff --git a/managemon.c b/managemon.c index aa10a99..971dcd1 100644 --- a/managemon.c +++ b/managemon.c @@ -382,6 +382,8 @@ void wake_me(int sig) woke = 1; } +int exit_now = 0; +int manager_ready = 0; void do_manager(struct supertype *container) { struct mdstat_ent *mdstat; @@ -395,6 +397,9 @@ void do_manager(struct supertype *container) do { woke = 0; + if (exit_now) + exit(0); + mdstat = mdstat_read(1, 0); manage(mdstat, container); @@ -405,6 +410,7 @@ void do_manager(struct supertype *container) remove_old(); + manager_ready = 1; sigprocmask(SIG_SETMASK, &block, &orig); if (woke == 0) mdstat_wait_fd(container->sock, &orig); diff --git a/mdadm.h b/mdadm.h index 7b11ffb..5586dce 100644 --- a/mdadm.h +++ b/mdadm.h @@ -460,6 +460,7 @@ struct supertype { * external:/md0/12 */ int devcnt; + char *device_name; /* e.g. /dev/md/whatever */ struct mdinfo *devs; diff --git a/mdmon.c b/mdmon.c index 2919a02..323ee62 100644 --- a/mdmon.c +++ b/mdmon.c @@ -146,6 +146,14 @@ static void try_kill_monitor(char *devname) kill(pid, SIGTERM); } +void remove_pidfile(char *devname) +{ + char buf[100]; + + sprintf(buf, "/var/run/mdadm/%s.pid", devname); + unlink(buf); +} + static int make_control_sock(char *devname) { char path[100]; @@ -198,6 +206,7 @@ int main(int argc, char *argv[]) container = malloc(sizeof(*container)); container->devnum = fd2devnum(mdfd); container->devname = devnum2devname(container->devnum); + container->device_name = argv[1]; /* If this fails, we hope it already exists */ mkdir("/var/run/mdadm", 0600); @@ -267,7 +276,7 @@ int main(int argc, char *argv[]) argv[1]); exit(3); } - + close(mdfd); close(mdfd); mlockall(MCL_FUTURE); diff --git a/mdmon.h b/mdmon.h index 29349b7..b84e270 100644 --- a/mdmon.h +++ b/mdmon.h @@ -33,6 +33,7 @@ extern struct active_array *pending_discard; extern struct md_generic_cmd *active_cmd; +void remove_pidfile(char *devname); void do_monitor(struct supertype *container); void do_manager(struct supertype *container); @@ -41,3 +42,5 @@ int read_dev_state(int fd); struct mdstat_ent *mdstat_read(int hold, int start); extern struct superswitch super_ddf, super_ddf_bvd, super_ddf_svd; + +extern int exit_now, manager_ready; diff --git a/monitor.c b/monitor.c index ead96d9..a7e5308 100644 --- a/monitor.c +++ b/monitor.c @@ -436,11 +436,12 @@ static int handle_pipe(struct md_generic_cmd *cmd, struct active_array *aa) return -1; } -static int wait_and_act(struct active_array **aap, int pfd, +static int wait_and_act(struct supertype *container, int pfd, int monfd, int nowait) { fd_set rfds; int maxfd = 0; + struct active_array **aap = &container->arrays; struct active_array *a, **ap; int rv; struct mdinfo *mdi; @@ -473,6 +474,22 @@ static int wait_and_act(struct active_array **aap, int pfd, 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. + */ + int fd = open(container->device_name, O_RDONLY|O_EXCL); + if (fd >= 0 || errno != EBUSY) { + /* OK, we are safe to leave */ + exit_now = 1; + signal_manager(); + remove_pidfile(container->devname); + exit(0); + } + } + if (!nowait) { rv = select(maxfd+1, &rfds, NULL, NULL, NULL); @@ -521,7 +538,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, container->mgr_pipe[0], container->mon_pipe[1], first); first = 0; } while (rv >= 0);