]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - mdmon.c
Release 3.2.6 - stability release
[thirdparty/mdadm.git] / mdmon.c
diff --git a/mdmon.c b/mdmon.c
index 0c3742603ee5fdf6527ed585b1d08736baceea75..54e12384d6b2c156cd8cf0cf182b82e9b604655d 100644 (file)
--- a/mdmon.c
+++ b/mdmon.c
 #include       <fcntl.h>
 #include       <signal.h>
 #include       <dirent.h>
-
+#ifdef USE_PTHREADS
+#include       <pthread.h>
+#else
 #include       <sched.h>
+#endif
 
 #include       "mdadm.h"
 #include       "mdmon.h"
@@ -71,7 +74,39 @@ int mon_tid, mgr_tid;
 
 int sigterm;
 
-int run_child(void *v)
+#ifdef USE_PTHREADS
+static void *run_child(void *v)
+{
+       struct supertype *c = v;
+
+       mon_tid = syscall(SYS_gettid);
+       do_monitor(c);
+       return 0;
+}
+
+static int clone_monitor(struct supertype *container)
+{
+       pthread_attr_t attr;
+       pthread_t thread;
+       int rc;
+
+       mon_tid = -1;
+       pthread_attr_init(&attr);
+       pthread_attr_setstacksize(&attr, 4096);
+       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+       rc = pthread_create(&thread, &attr, run_child, container);
+       if (rc)
+               return rc;
+       while (mon_tid == -1)
+               usleep(10);
+       pthread_attr_destroy(&attr);
+
+       mgr_tid = syscall(SYS_gettid);
+
+       return mon_tid;
+}
+#else /* USE_PTHREADS */
+static int run_child(void *v)
 {
        struct supertype *c = v;
 
@@ -85,7 +120,7 @@ int __clone2(int (*fn)(void *),
            int flags, void *arg, ...
         /* pid_t *pid, struct user_desc *tls, pid_t *ctid */ );
 #endif
- int clone_monitor(struct supertype *container)
+static int clone_monitor(struct supertype *container)
 {
        static char stack[4096];
 
@@ -103,6 +138,7 @@ int __clone2(int (*fn)(void *),
 
        return mon_tid;
 }
+#endif /* USE_PTHREADS */
 
 static int make_pidfile(char *devname)
 {
@@ -111,10 +147,10 @@ static int make_pidfile(char *devname)
        int fd;
        int n;
 
-       if (mkdir(pid_dir, 0700) < 0 &&
+       if (mkdir(MDMON_DIR, 0755) < 0 &&
            errno != EEXIST)
                return -errno;
-       sprintf(path, "%s/%s.pid", pid_dir, devname);
+       sprintf(path, "%s/%s.pid", MDMON_DIR, devname);
 
        fd = open(path, O_RDWR|O_CREAT|O_EXCL, 0600);
        if (fd < 0)
@@ -148,11 +184,18 @@ static void try_kill_monitor(pid_t pid, char *devname, int sock)
        buf[sizeof(buf)-1] = 0;
        close(fd);
 
-       if (n < 0 || !strstr(buf, "mdmon"))
+       /* Note that if started with --offroot, the name
+        * might be "@dmon"
+        */
+       if (n < 0 || !(strstr(buf, "mdmon") ||
+                      strstr(buf, "@dmon")))
                return;
 
        kill(pid, SIGTERM);
 
+       if (sock < 0)
+               return;
+
        /* Wait for monitor to exit by reading from the socket, after
         * clearing the non-blocking flag */
        fl = fcntl(sock, F_GETFL, 0);
@@ -168,13 +211,10 @@ void remove_pidfile(char *devname)
 {
        char buf[100];
 
-       sprintf(buf, "%s/%s.pid", pid_dir, devname);
+       sprintf(buf, "%s/%s.pid", MDMON_DIR, devname);
        unlink(buf);
-       sprintf(buf, "%s/%s.sock", pid_dir, devname);
+       sprintf(buf, "%s/%s.sock", MDMON_DIR, devname);
        unlink(buf);
-       if (strcmp(pid_dir, ALT_RUN) == 0)
-               /* try to clean up when we are finished with this dir */
-               rmdir(pid_dir);
 }
 
 static int make_control_sock(char *devname)
@@ -187,7 +227,7 @@ static int make_control_sock(char *devname)
        if (sigterm)
                return -1;
 
-       sprintf(path, "%s/%s.sock", pid_dir, devname);
+       sprintf(path, "%s/%s.sock", MDMON_DIR, devname);
        unlink(path);
        sfd = socket(PF_LOCAL, SOCK_STREAM, 0);
        if (sfd < 0)
@@ -229,7 +269,18 @@ static int do_fork(void)
 
 void usage(void)
 {
-       fprintf(stderr, "Usage: mdmon [--all] [--takeover] CONTAINER\n");
+       fprintf(stderr,
+"Usage: mdmon [options] CONTAINER\n"
+"\n"
+"Options are:\n"
+"  --help        -h   : This message\n"
+"  --all              : All devices\n"
+"  --takeover    -t   : Takeover container\n"
+"  --offroot          : Set first character of argv[0] to @ to indicate the\n"
+"                       application was launched from initrd/initramfs and\n"
+"                       should not be shutdown by systemd as part of the\n"
+"                       regular shutdown process.\n"
+);
        exit(2);
 }
 
@@ -241,25 +292,50 @@ int main(int argc, char *argv[])
        int devnum;
        char *devname;
        int status = 0;
-       int arg;
+       int opt;
        int all = 0;
        int takeover = 0;
-
-       for (arg = 1; arg < argc; arg++) {
-               if (strncmp(argv[arg], "--all",5) == 0 ||
-                   strcmp(argv[arg], "/proc/mdstat") == 0) {
-                       container_name = argv[arg];
+       static struct option options[] = {
+               {"all", 0, NULL, 'a'},
+               {"takeover", 0, NULL, 't'},
+               {"help", 0, NULL, 'h'},
+               {"offroot", 0, NULL, OffRootOpt},
+               {NULL, 0, NULL, 0}
+       };
+
+       while ((opt = getopt_long(argc, argv, "tha", options, NULL)) != -1) {
+               switch (opt) {
+               case 'a':
+                       container_name = argv[optind-1];
                        all = 1;
-               } else if (strcmp(argv[arg], "--takeover") == 0)
+                       break;
+               case 't':
                        takeover = 1;
-               else if (container_name == NULL)
-                       container_name = argv[arg];
-               else
+                       break;
+               case OffRootOpt:
+                       argv[0][0] = '@';
+                       break;
+               case 'h':
+               default:
                        usage();
+                       break;
+               }
+       }
+
+       if (all == 0 && container_name == NULL) {
+               if (argv[optind])
+                       container_name = argv[optind];
        }
+
        if (container_name == NULL)
                usage();
 
+       if (argc - optind > 1)
+               usage();
+
+       if (strcmp(container_name, "/proc/mdstat") == 0)
+               all = 1;
+
        if (all) {
                struct mdstat_ent *mdstat, *e;
                int container_len = strlen(container_name);
@@ -267,13 +343,14 @@ int main(int argc, char *argv[])
                /* launch an mdmon instance for each container found */
                mdstat = mdstat_read(0, 0);
                for (e = mdstat; e; e = e->next) {
-                       if (strncmp(e->metadata_version, "external:", 9) == 0 &&
+                       if (e->metadata_version &&
+                           strncmp(e->metadata_version, "external:", 9) == 0 &&
                            !is_subarray(&e->metadata_version[9])) {
                                devname = devnum2devname(e->devnum);
                                /* update cmdline so this mdmon instance can be
                                 * distinguished from others in a call to ps(1)
                                 */
-                               if (strlen(devname) <= container_len) {
+                               if (strlen(devname) <= (unsigned)container_len) {
                                        memset(container_name, 0, container_len);
                                        sprintf(container_name, "%s", devname);
                                }
@@ -365,7 +442,6 @@ static int mdmon(char *devname, int devnum, int must_fork, int takeover)
        container->devnum = devnum;
        container->devname = devname;
        container->arrays = NULL;
-       container->subarray[0] = 0;
        container->sock = -1;
 
        if (!container->devname) {
@@ -423,12 +499,7 @@ static int mdmon(char *devname, int devnum, int must_fork, int takeover)
        act.sa_handler = SIG_IGN;
        sigaction(SIGPIPE, &act, NULL);
 
-       pid_dir = VAR_RUN;
        victim = mdmon_pid(container->devnum);
-       if (victim < 0) {
-               pid_dir = ALT_RUN;
-               victim = mdmon_pid(container->devnum);
-       }
        if (victim >= 0)
                victim_sock = connect_monitor(container->devname);
 
@@ -440,8 +511,9 @@ static int mdmon(char *devname, int devnum, int must_fork, int takeover)
                        exit(3);
                }
                close(victim_sock);
+               victim_sock = -1;
        }
-       if (container->ss->load_super(container, mdfd, devname)) {
+       if (container->ss->load_container(container, mdfd, devname)) {
                fprintf(stderr, "mdmon: Cannot load metadata for %s\n",
                        devname);
                exit(3);
@@ -452,16 +524,8 @@ static int mdmon(char *devname, int devnum, int must_fork, int takeover)
         */
        if (victim > 0)
                remove_pidfile(devname);
-       pid_dir = VAR_RUN;
        if (make_pidfile(devname) < 0) {
-               /* Try the alternate */
-               pid_dir = ALT_RUN;
-               if (make_pidfile(devname) < 0) {
-                       fprintf(stderr, "mdmon: Neither %s nor %s are writable\n"
-                               "       cannot create .pid or .sock files.  Aborting\n",
-                               VAR_RUN, ALT_RUN);
-                       exit(3);
-               }
+               exit(3);
        }
        container->sock = make_control_sock(devname);
 
@@ -481,7 +545,8 @@ static int mdmon(char *devname, int devnum, int must_fork, int takeover)
 
        if (victim > 0) {
                try_kill_monitor(victim, container->devname, victim_sock);
-               close(victim_sock);
+               if (victim_sock >= 0)
+                       close(victim_sock);
        }
 
        setsid();
@@ -494,7 +559,45 @@ static int mdmon(char *devname, int devnum, int must_fork, int takeover)
        ignore = dup(0);
 #endif
 
+       /* This silliness is to stop the compiler complaining
+        * that we ignore 'ignore'
+        */
+       if (ignore)
+               ignore++;
+
        do_manager(container);
 
        exit(0);
 }
+
+/* Some stub functions so super-* can link with us */
+int child_monitor(int afd, struct mdinfo *sra, struct reshape *reshape,
+                 struct supertype *st, unsigned long blocks,
+                 int *fds, unsigned long long *offsets,
+                 int dests, int *destfd, unsigned long long *destoffsets)
+{
+       return 0;
+}
+
+int restore_stripes(int *dest, unsigned long long *offsets,
+                   int raid_disks, int chunk_size, int level, int layout,
+                   int source, unsigned long long read_offset,
+                   unsigned long long start, unsigned long long length,
+                   char *src_buf)
+{
+       return 1;
+}
+
+void abort_reshape(struct mdinfo *sra)
+{
+       return;
+}
+
+int save_stripes(int *source, unsigned long long *offsets,
+                int raid_disks, int chunk_size, int level, int layout,
+                int nwrites, int *dest,
+                unsigned long long start, unsigned long long length,
+                char *buf)
+{
+       return 0;
+}