]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - mdmon.c
Add gpt pseudo-metadata
[thirdparty/mdadm.git] / mdmon.c
diff --git a/mdmon.c b/mdmon.c
index 8e62a68b2319e1c3087c485d02aff03beaf516ba..e416b2e42f4559c69b896252f6d4cb4f8efa4447 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,15 +138,7 @@ int __clone2(int (*fn)(void *),
 
        return mon_tid;
 }
-
-static struct superswitch *find_metadata_methods(char *vers)
-{
-       if (strcmp(vers, "ddf") == 0)
-               return &super_ddf;
-       if (strcmp(vers, "imsm") == 0)
-               return &super_imsm;
-       return NULL;
-}
+#endif /* USE_PTHREADS */
 
 static int make_pidfile(char *devname)
 {
@@ -120,7 +147,10 @@ static int make_pidfile(char *devname)
        int fd;
        int n;
 
-       sprintf(path, "%s/%s.pid", pid_dir, devname);
+       if (mkdir(MDMON_DIR, 0755) < 0 &&
+           errno != EEXIST)
+               return -errno;
+       sprintf(path, "%s/%s.pid", MDMON_DIR, devname);
 
        fd = open(path, O_RDWR|O_CREAT|O_EXCL, 0600);
        if (fd < 0)
@@ -133,18 +163,6 @@ static int make_pidfile(char *devname)
        return 0;
 }
 
-int is_container_member(struct mdstat_ent *mdstat, char *container)
-{
-       if (mdstat->metadata_version == NULL ||
-           strncmp(mdstat->metadata_version, "external:", 9) != 0 ||
-           !is_subarray(mdstat->metadata_version+9) ||
-           strncmp(mdstat->metadata_version+10, container, strlen(container)) != 0 ||
-           mdstat->metadata_version[10+strlen(container)] != '/')
-               return 0;
-
-       return 1;
-}
-
 static void try_kill_monitor(pid_t pid, char *devname, int sock)
 {
        char buf[100];
@@ -186,13 +204,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)
@@ -205,7 +220,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)
@@ -247,7 +262,7 @@ static int do_fork(void)
 
 void usage(void)
 {
-       fprintf(stderr, "Usage: mdmon /device/name/for/container [target_dir]\n");
+       fprintf(stderr, "Usage: mdmon [--all] [--takeover] CONTAINER\n");
        exit(2);
 }
 
@@ -264,19 +279,23 @@ int main(int argc, char *argv[])
        int takeover = 0;
 
        for (arg = 1; arg < argc; arg++) {
-               if (strcmp(argv[arg], "--all") == 0 ||
-                   strcmp(argv[arg], "/proc/mdstat") == 0)
+               if (strncmp(argv[arg], "--all",5) == 0 ||
+                   strcmp(argv[arg], "/proc/mdstat") == 0) {
+                       container_name = argv[arg];
                        all = 1;
-               else if (strcmp(argv[arg], "--takeover") == 0)
+               else if (strcmp(argv[arg], "--takeover") == 0)
                        takeover = 1;
                else if (container_name == NULL)
                        container_name = argv[arg];
                else
                        usage();
        }
+       if (container_name == NULL)
+               usage();
 
        if (all) {
                struct mdstat_ent *mdstat, *e;
+               int container_len = strlen(container_name);
 
                /* launch an mdmon instance for each container found */
                mdstat = mdstat_read(0, 0);
@@ -287,8 +306,8 @@ int main(int argc, char *argv[])
                                /* update cmdline so this mdmon instance can be
                                 * distinguished from others in a call to ps(1)
                                 */
-                               if (strlen(devname) <= strlen(container_name)) {
-                                       memset(container_name, 0, strlen(container_name));
+                               if (strlen(devname) <= (unsigned)container_len) {
+                                       memset(container_name, 0, container_len);
                                        sprintf(container_name, "%s", devname);
                                }
                                status |= mdmon(devname, e->devnum, 1,
@@ -387,8 +406,7 @@ static int mdmon(char *devname, int devnum, int must_fork, int takeover)
                exit(3);
        }
 
-       mdi = sysfs_read(mdfd, container->devnum,
-                        GET_VERSION|GET_LEVEL|GET_DEVS|SKIP_GONE_DEVS);
+       mdi = sysfs_read(mdfd, container->devnum, GET_VERSION|GET_LEVEL|GET_DEVS);
 
        if (!mdi) {
                fprintf(stderr, "mdmon: failed to load sysfs info for %s\n",
@@ -407,9 +425,9 @@ static int mdmon(char *devname, int devnum, int must_fork, int takeover)
                exit(3);
        }
 
-       container->ss = find_metadata_methods(mdi->text_version);
+       container->ss = version_to_superswitch(mdi->text_version);
        if (container->ss == NULL) {
-               fprintf(stderr, "mdmon: %s uses unknown metadata: %s\n",
+               fprintf(stderr, "mdmon: %s uses unsupported metadata: %s\n",
                        devname, mdi->text_version);
                exit(3);
        }
@@ -438,26 +456,18 @@ static int mdmon(char *devname, int devnum, int must_fork, int takeover)
        act.sa_handler = SIG_IGN;
        sigaction(SIGPIPE, &act, NULL);
 
-       if (takeover) {
-               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);
-       }
+       victim = mdmon_pid(container->devnum);
+       if (victim >= 0)
+               victim_sock = connect_monitor(container->devname);
 
        ignore = chdir("/");
-       if (victim < 0) {
-               if (ping_monitor(container->devname) == 0) {
+       if (!takeover && victim > 0 && victim_sock >= 0) {
+               if (fping_monitor(victim_sock) == 0) {
                        fprintf(stderr, "mdmon: %s already managed\n",
                                container->devname);
                        exit(3);
                }
-               /* if there is a pid file, kill whoever is there just in case */
-               victim = mdmon_pid(container->devnum);
+               close(victim_sock);
        }
        if (container->ss->load_super(container, mdfd, devname)) {
                fprintf(stderr, "mdmon: Cannot load metadata for %s\n",
@@ -470,19 +480,7 @@ static int mdmon(char *devname, int devnum, int must_fork, int takeover)
         */
        if (victim > 0)
                remove_pidfile(devname);
-       if (mkdir(VAR_RUN, 0600) >= 0 || errno == EEXIST)
-               pid_dir = VAR_RUN;
-       else if (mkdir(ALT_RUN, 0600) >= 0 || errno == EEXIST)
-               pid_dir = ALT_RUN;
-       else {
-               fprintf(stderr, "mdmon: Neither %s nor %s are writable\n"
-                       "       cannot create .pid or .sock files.  Aborting\n",
-                       VAR_RUN, ALT_RUN);
-               exit(3);
-       }
        if (make_pidfile(devname) < 0) {
-               fprintf(stderr, "mdmon: Cannot create pid file in %s - aborting.\n",
-                       pid_dir);
                exit(3);
        }
        container->sock = make_control_sock(devname);