]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - managemon.c
Alway use a unique file name for opendev
[thirdparty/mdadm.git] / managemon.c
index 14e7184b0359801dd5fd9b25b3c674011635d177..c5ba2f4c40a7b4d88069f889a1723e9018212fae 100644 (file)
 #include       "mdmon.h"
 #include       <sys/socket.h>
 
+static void close_aa(struct active_array *aa)
+{
+       struct mdinfo *d;
+
+       for (d = aa->info.devs; d; d = d->next)
+               close(d->state_fd);
+
+       close(aa->action_fd);
+       close(aa->info.state_fd);
+       close(aa->resync_start_fd);
+       close(aa->sync_pos_fd);
+}
 
 static void free_aa(struct active_array *aa)
 {
-       /* Note that this doesn't close fds, as they may be in used
-        * by a clone.  Use close_aa for that.
+       /* Note that this doesn't close fds if they are being used
+        * by a clone.  ->container will be set for a clone
         */
+       if (!aa->container)
+               close_aa(aa);
        while (aa->info.devs) {
                struct mdinfo *d = aa->info.devs;
                aa->info.devs = d->next;
@@ -90,6 +104,18 @@ static void free_aa(struct active_array *aa)
        free(aa);
 }
 
+static void write_wakeup(struct supertype *c)
+{
+       static struct md_generic_cmd cmd = { .action = md_action_ping_monitor };
+       int err;
+
+       active_cmd = &cmd;
+
+       /* send the monitor thread a pointer to the ping action */
+       write(c->mgr_pipe[1], &err, 1);
+       read(c->mon_pipe[0], &err, 1);
+}
+
 static void replace_array(struct supertype *container,
                          struct active_array *old,
                          struct active_array *new)
@@ -115,6 +141,7 @@ static void replace_array(struct supertype *container,
        new->replaces = old;
        new->next = container->arrays;
        container->arrays = new;
+       write_wakeup(container);
 }
 
 
@@ -158,13 +185,9 @@ static void manage_member(struct mdstat_ent *mdstat,
 
 }
 
-static void write_wakeup(struct supertype *c)
-{
-       write(c->pipe[1], "PING", 4);
-}
-
 static void manage_new(struct mdstat_ent *mdstat,
-                      struct supertype *container)
+                      struct supertype *container,
+                      struct active_array *victim)
 {
        /* A new array has appeared in this container.
         * Hopefully it is already recorded in the metadata.
@@ -200,7 +223,7 @@ static void manage_new(struct mdstat_ent *mdstat,
                 * Mark it to be ignored by setting container to NULL
                 */
                new->container = NULL;
-               replace_array(container, NULL, new);
+               replace_array(container, victim, new);
                return;
        }
 
@@ -236,15 +259,15 @@ static void manage_new(struct mdstat_ent *mdstat,
        new->sync_pos_fd = sysfs_open(new->devnum, NULL, "sync_completed");
        new->sync_pos = 0;
 
+       sysfs_free(mdi);
        // finds and compares.
        if (container->ss->open_new(container, new, inst) < 0) {
                // FIXME close all those files
                new->container = NULL;
-               replace_array(container, NULL, new);
+               replace_array(container, victim, new);
                return;
        }
-       replace_array(container, NULL, new);
-       write_wakeup(container);
+       replace_array(container, victim, new);
        return;
 }
 
@@ -278,20 +301,70 @@ void manage(struct mdstat_ent *mdstat, struct active_array *aa,
                                break;
                        }
                }
-               if (a == NULL)
-                       manage_new(mdstat, container);
+               if (a == NULL || !a->container)
+                       manage_new(mdstat, container, a);
+       }
+}
+
+static int handle_message(struct supertype *container, struct md_message *msg)
+{
+       int err;
+       struct md_generic_cmd *cmd = msg->buf;
+
+       if (!cmd)
+               return 0;
+
+       switch (cmd->action) {
+       case md_action_remove_device:
+
+               /* forward to the monitor */
+               active_cmd = cmd;
+               write(container->mgr_pipe[1], &err, 1);
+               read(container->mon_pipe[0], &err, 1);
+               return err;
+
+       default:
+               return -1;
        }
 }
 
-void read_sock(int pfd)
+void read_sock(struct supertype *container)
 {
        int fd;
+       struct md_message msg;
+       int terminate = 0;
+       long fl;
+       int tmo = 3; /* 3 second timeout before hanging up the socket */
 
-       // FIXME set non-blocking
-       fd = accept(pfd, NULL, NULL);
+       fd = accept(container->sock, NULL, NULL);
        if (fd < 0)
                return;
-       // FIXME do something useful
+
+       fl = fcntl(fd, F_GETFL, 0);
+       fl |= O_NONBLOCK;
+       fcntl(fd, F_SETFL, fl);
+
+       do {
+               int err;
+
+               msg.buf = NULL;
+
+               /* read and validate the message */
+               if (receive_message(fd, &msg, tmo) == 0) {
+                       err = handle_message(container, &msg);
+                       if (!err)
+                               ack(fd, msg.seq, tmo);
+                       else
+                               nack(fd, err, tmo);
+               } else {
+                       terminate = 1;
+                       nack(fd, -1, tmo);
+               }
+
+               if (msg.buf)
+                       free(msg.buf);
+       } while (!terminate);
+
        close(fd);
 }
 void do_manager(struct supertype *container)
@@ -303,7 +376,9 @@ void do_manager(struct supertype *container)
 
                manage(mdstat, array_list, container);
 
-               read_sock(container->sock);
+               read_sock(container);
+
+               free_mdstat(mdstat);
 
                mdstat_wait_fd(container->sock);
        } while(1);