From 3e70c845e25295d80680d884d5671107bf8bded3 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 15 May 2008 16:48:54 +1000 Subject: [PATCH] add infrastructure to receive higher order commands, like remove_device From: Dan Williams 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 --- managemon.c | 48 +++++++++++++++++++++++++++++++------- mdadm.h | 3 ++- mdmon.c | 26 +++++++++++++++------ mdmon.h | 1 + monitor.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++---- msg.h | 5 ++-- 6 files changed, 125 insertions(+), 24 deletions(-) diff --git a/managemon.c b/managemon.c index f8123d0e..23019468 100644 --- a/managemon.c +++ b/managemon.c @@ -74,10 +74,8 @@ #endif #include "mdadm.h" #include "mdmon.h" -#include "msg.h" #include - 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 29cfbf2b..c5760950 100644 --- 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 2cce760f..d013dc8f 100644 --- 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 3886b09e..e83f4236 100644 --- 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); diff --git a/monitor.c b/monitor.c index e941a1ab..5fbbc833 100644 --- 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 6f0d9c16..afe14040 100644 --- 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 -- 2.39.2