]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - mdmon.c
Remove st->text_version in favour of info->text_version
[thirdparty/mdadm.git] / mdmon.c
diff --git a/mdmon.c b/mdmon.c
index 1284a1249b9e22aedc7f0e1b59d710f61038768b..323ee62ee56ed37617dbda90a330d18813815490 100644 (file)
--- a/mdmon.c
+++ b/mdmon.c
 #include       <errno.h>
 #include       <string.h>
 #include       <fcntl.h>
+#include       <signal.h>
 
 #include       <sched.h>
 
 #include       "mdadm.h"
 #include       "mdmon.h"
 
-struct active_array *array_list;
 struct active_array *discard_this;
 struct active_array *pending_discard;
+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;
 }
 
 int clone_monitor(struct supertype *container)
 {
-       int pfd[2];
        static char stack[4096];
        int rv;
 
-       pipe(container->pipe);
+       rv = pipe(container->mgr_pipe);
+       if (rv < 0)
+               return rv;
+       rv = pipe(container->mon_pipe);
+       if (rv < 0)
+               goto err_mon_pipe;
 
        rv = clone(run_child, stack+4096-64,
                   CLONE_FS|CLONE_FILES|CLONE_VM|CLONE_SIGHAND|CLONE_THREAD,
                   container);
-
        if (rv < 0)
+               goto err_clone;
+       else
                return rv;
-       return pfd[1];
+
+ err_clone:
+       close(container->mon_pipe[0]);
+       close(container->mon_pipe[1]);
+ err_mon_pipe:
+       close(container->mgr_pipe[0]);
+       close(container->mgr_pipe[1]);
+
+       return rv;
 }
 
 static struct superswitch *find_metadata_methods(char *vers)
@@ -76,14 +96,14 @@ static struct superswitch *find_metadata_methods(char *vers)
 }
 
 
-static int make_pidfile(char *devname)
+static int make_pidfile(char *devname, int o_excl)
 {
        char path[100];
        char pid[10];
        int fd;
        sprintf(path, "/var/run/mdadm/%s.pid", devname);
 
-       fd = open(path, O_RDWR|O_CREAT|O_EXCL, 0600);
+       fd = open(path, O_RDWR|O_CREAT|o_excl, 0600);
        if (fd < 0)
                return -1;
        sprintf(pid, "%d\n", getpid());
@@ -92,6 +112,48 @@ static int make_pidfile(char *devname)
        return 0;
 }
 
+static void try_kill_monitor(char *devname)
+{
+       char buf[100];
+       int fd;
+       pid_t pid;
+
+       sprintf(buf, "/var/run/mdadm/%s.pid", devname);
+       fd = open(buf, O_RDONLY);
+       if (fd < 0)
+               return;
+
+       if (read(fd, buf, sizeof(buf)) < 0) {
+               close(fd);
+               return;
+       }
+
+       close(fd);
+       pid = strtoul(buf, NULL, 10);
+
+       /* kill this process if it is mdmon */
+       sprintf(buf, "/proc/%lu/cmdline", (unsigned long) pid);
+       fd = open(buf, O_RDONLY);
+       if (fd < 0)
+               return;
+
+       if (read(fd, buf, sizeof(buf)) < 0) {
+               close(fd);
+               return;
+       }
+
+       if (strstr(buf, "mdmon") != NULL)
+               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];
@@ -121,7 +183,6 @@ static int make_control_sock(char *devname)
 int main(int argc, char *argv[])
 {
        int mdfd;
-       int pipefd;
        struct mdinfo *mdi, *di;
        struct supertype *container;
        if (argc != 2) {
@@ -143,17 +204,27 @@ int main(int argc, char *argv[])
        /* hopefully it is a container - we'll check later */
 
        container = malloc(sizeof(*container));
-       container->devfd = mdfd;
        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);
        /* pid file lives in /var/run/mdadm/mdXX.pid */
-       if (make_pidfile(container->devname) < 0) {
-               fprintf(stderr, "md-manage: %s already managed\n",
-                       container->devname);
-               exit(3);
+       if (make_pidfile(container->devname, O_EXCL) < 0) {
+               if (ping_monitor(container->devname) == 0) {
+                       fprintf(stderr, "mdmon: %s already managed\n",
+                               container->devname);
+                       exit(3);
+               } else {
+                       /* cleanup the old monitor, this one is taking over */
+                       try_kill_monitor(container->devname);
+                       if (make_pidfile(container->devname, 0) < 0) {
+                               fprintf(stderr, "mdmon: %s Cannot create pidfile\n",
+                                       container->devname);
+                               exit(3);
+                       }
+               }
        }
 
        container->sock = make_control_sock(container->devname);
@@ -205,12 +276,12 @@ int main(int argc, char *argv[])
                        argv[1]);
                exit(3);
        }
-
+       close(mdfd);
+       close(mdfd);
 
        mlockall(MCL_FUTURE);
 
-       pipefd = clone_monitor(container);
-       if (pipefd < 0) {
+       if (clone_monitor(container) < 0) {
                fprintf(stderr, "md-manage: failed to start monitor process: %s\n",
                        strerror(errno));
                exit(2);