]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
add infrastructure to receive higher order commands, like remove_device
authorDan Williams <dan.j.williams@intel.com>
Thu, 15 May 2008 06:48:54 +0000 (16:48 +1000)
committerNeil Brown <neilb@suse.de>
Thu, 15 May 2008 06:48:54 +0000 (16:48 +1000)
From: Dan Williams <dan.j.williams@intel.com>

Each md_message encapsulates a single command.  A command includes an 'action'
member which describes what if any data comes after the action.  Communication
with the monitor involves updating the active_cmd pointer and then writing to
mgr_pipe.  Pass/fail status is returned via mon_pipe.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
managemon.c
mdadm.h
mdmon.c
mdmon.h
monitor.c
msg.h

index f8123d0efd974210889ca6bcac8f2be890638e42..230194688ab35cea405be75b1e20dd1a531658aa 100644 (file)
 #endif
 #include       "mdadm.h"
 #include       "mdmon.h"
-#include       "msg.h"
 #include       <sys/socket.h>
 
-
 static void close_aa(struct active_array *aa)
 {
        struct mdinfo *d;
@@ -108,7 +106,14 @@ static void free_aa(struct active_array *aa)
 
 static void write_wakeup(struct supertype *c)
 {
-       write(c->pipe[1], "PING", 4);
+       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,
@@ -300,7 +305,29 @@ void manage(struct mdstat_ent *mdstat, struct active_array *aa,
        }
 }
 
-void read_sock(int pfd)
+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(struct supertype *container)
 {
        int fd;
        struct md_message msg;
@@ -308,7 +335,7 @@ void read_sock(int pfd)
        long fl;
        int tmo = 3; /* 3 second timeout before hanging up the socket */
 
-       fd = accept(pfd, NULL, NULL);
+       fd = accept(container->sock, NULL, NULL);
        if (fd < 0)
                return;
 
@@ -317,12 +344,17 @@ void read_sock(int pfd)
        fcntl(fd, F_SETFL, fl);
 
        do {
+               int err;
+
                msg.buf = NULL;
 
                /* read and validate the message */
                if (receive_message(fd, &msg, tmo) == 0) {
-                       // FIXME: handle message contents
-                       ack(fd, msg.seq, tmo);
+                       err = handle_message(container, &msg);
+                       if (!err)
+                               ack(fd, msg.seq, tmo);
+                       else
+                               nack(fd, err, tmo);
                } else {
                        terminate = 1;
                        nack(fd, -1, tmo);
@@ -343,7 +375,7 @@ void do_manager(struct supertype *container)
 
                manage(mdstat, array_list, container);
 
-               read_sock(container->sock);
+               read_sock(container);
 
                mdstat_wait_fd(container->sock);
        } while(1);
diff --git a/mdadm.h b/mdadm.h
index 29cfbf2ba2176a357e54d509d8941ed0b87483a4..c576095067c60e104dc6390345395d8b8f58a126 100644 (file)
--- a/mdadm.h
+++ b/mdadm.h
@@ -439,7 +439,8 @@ struct supertype {
        struct active_array *arrays;
        int devfd;
        int sock; /* listen to external programs */
-       int pipe[2]; /* communicate between threads */
+       int mgr_pipe[2]; /* communicate between threads */
+       int mon_pipe[2]; /* communicate between threads */
        int devnum;
        char *devname; /* e.g. md0.  This appears in metadata_verison:
                        *  external:/md0/12
diff --git a/mdmon.c b/mdmon.c
index 2cce760fccfcb8e33ba09db807c18dc16d070b3d..d013dc8ffc9749a643beb4430d2da2a042b9e57c 100644 (file)
--- a/mdmon.c
+++ b/mdmon.c
@@ -44,6 +44,7 @@
 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)
 {
@@ -54,19 +55,32 @@ int run_child(void *v)
 
 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)
@@ -156,7 +170,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) {
@@ -254,8 +267,7 @@ int main(int argc, char *argv[])
 
        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);
diff --git a/mdmon.h b/mdmon.h
index 3886b09eaaf10d65c548c69c41fb2d21083167f4..e83f42362259a7a35eb035b38bbad42533633f19 100644 (file)
--- a/mdmon.h
+++ b/mdmon.h
@@ -31,6 +31,7 @@ extern struct active_array *container;
 extern struct active_array *array_list;
 extern struct active_array *discard_this;
 extern struct active_array *pending_discard;
+extern struct md_generic_cmd *active_cmd;
 
 
 void do_monitor(struct supertype *container);
index e941a1abd8352548660122ae6a3770cac265e35d..5fbbc83393c72b75cb029fe0b17f0757ff5cf66d 100644 (file)
--- a/monitor.c
+++ b/monitor.c
@@ -377,7 +377,60 @@ static void reconcile_failed(struct active_array *aa, struct mdinfo *failed)
        }
 }
 
-static int wait_and_act(struct active_array *aa, int pfd, int nowait)
+static int handle_remove_device(struct md_remove_device_cmd *cmd, struct active_array *aa)
+{
+       struct active_array *a;
+       struct mdinfo *victim;
+       int rv;
+
+       /* scan all arrays for the given device, if ->state_fd is closed (-1)
+        * in all cases then mark the disk as removed in the metadata.
+        * Otherwise reply that it is busy.
+        */
+
+       /* pass1 check that it is not in use anywhere */
+       /* note: we are safe from re-adds as long as the device exists in the
+        * container
+        */
+       for (a = aa; a; a = a->next) {
+               if (!a->container)
+                       continue;
+               victim = find_device(a, major(cmd->rdev), minor(cmd->rdev));
+               if (!victim)
+                       continue;
+               if (victim->state_fd > 0)
+                       return -EBUSY;
+       }
+
+       /* pass2 schedule and process removal per array */
+       for (a = aa; a; a = a->next) {
+               if (!a->container)
+                       continue;
+               victim = find_device(a, major(cmd->rdev), minor(cmd->rdev));
+               if (!victim)
+                       continue;
+               victim->curr_state |= DS_REMOVE;
+               rv = read_and_act(a);
+               if (rv < 0)
+                       return rv;
+       }
+
+       return 0;
+}
+
+static int handle_pipe(struct md_generic_cmd *cmd, struct active_array *aa)
+{
+       switch (cmd->action) {
+       case md_action_ping_monitor:
+               return 0;
+       case md_action_remove_device:
+               return handle_remove_device((void *) cmd, aa);
+       }
+
+       return -1;
+}
+
+static int wait_and_act(struct active_array *aa, int pfd, int monfd, int nowait)
 {
        fd_set rfds;
        int maxfd = 0;
@@ -408,9 +461,11 @@ static int wait_and_act(struct active_array *aa, int pfd, int nowait)
                        return rv;
 
                if (FD_ISSET(pfd, &rfds)) {
-                       char buf[4];
-                       read(pfd, buf, 4);
-                       ; // FIXME read from the pipe
+                       int err = -1;
+
+                       if (read(pfd, &err, 1) > 0)
+                               err = handle_pipe(active_cmd, aa);
+                       write(monfd, &err, 1);
                }
        }
 
@@ -446,7 +501,8 @@ void do_monitor(struct supertype *container)
        int rv;
        int first = 1;
        do {
-               rv = wait_and_act(container->arrays, container->pipe[0], first);
+               rv = wait_and_act(container->arrays, container->mgr_pipe[0],
+                                 container->mon_pipe[1], first);
                first = 0;
        } while (rv >= 0);
 }
diff --git a/msg.h b/msg.h
index 6f0d9c1656847febf4bf5b6bc26babc4292d09e0..afe14040391b6e49fdde5a3d68708095f0be6b03 100644 (file)
--- a/msg.h
+++ b/msg.h
@@ -17,8 +17,8 @@
  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#ifndef _MSG_H
-#define _MSG_H
+
+struct mdinfo;
 
 struct mdinfo;
 struct md_message {
@@ -60,4 +60,3 @@ extern int connect_monitor(char *devname);
 extern int ping_monitor(char *devname);
 extern int send_remove_device(int fd, dev_t rdev, int seq, int tmo);
 
-#endif