summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2008-05-15 16:48:54 +1000
committerNeil Brown <neilb@suse.de>2008-05-15 16:48:54 +1000
commit3e70c845e25295d80680d884d5671107bf8bded3 (patch)
tree3a8b69bb18e66ee64db5c6a0705d90a9f0843e02
parentb109d92863bfa319d140b305132ca41bfb8d1194 (diff)
downloadmdadm-3e70c845e25295d80680d884d5671107bf8bded3.tar.gz
mdadm-3e70c845e25295d80680d884d5671107bf8bded3.tar.xz
mdadm-3e70c845e25295d80680d884d5671107bf8bded3.zip
add infrastructure to receive higher order commands, like remove_device
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>
-rw-r--r--managemon.c48
-rw-r--r--mdadm.h3
-rw-r--r--mdmon.c26
-rw-r--r--mdmon.h1
-rw-r--r--monitor.c66
-rw-r--r--msg.h5
6 files changed, 125 insertions, 24 deletions
diff --git a/managemon.c b/managemon.c
index f8123d0..2301946 100644
--- a/managemon.c
+++ b/managemon.c
@@ -74,10 +74,8 @@
#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 29cfbf2..c576095 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 2cce760..d013dc8 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 3886b09..e83f423 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 e941a1a..5fbbc83 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 6f0d9c1..afe1404 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