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>
This commit is contained in:
Dan Williams 2008-05-15 16:48:54 +10:00 committed by Neil Brown
parent b109d92863
commit 3e70c845e2
6 changed files with 125 additions and 24 deletions

View File

@ -74,10 +74,8 @@
#endif #endif
#include "mdadm.h" #include "mdadm.h"
#include "mdmon.h" #include "mdmon.h"
#include "msg.h"
#include <sys/socket.h> #include <sys/socket.h>
static void close_aa(struct active_array *aa) static void close_aa(struct active_array *aa)
{ {
struct mdinfo *d; struct mdinfo *d;
@ -108,7 +106,14 @@ static void free_aa(struct active_array *aa)
static void write_wakeup(struct supertype *c) 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, 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; int fd;
struct md_message msg; struct md_message msg;
@ -308,7 +335,7 @@ void read_sock(int pfd)
long fl; long fl;
int tmo = 3; /* 3 second timeout before hanging up the socket */ 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) if (fd < 0)
return; return;
@ -317,12 +344,17 @@ void read_sock(int pfd)
fcntl(fd, F_SETFL, fl); fcntl(fd, F_SETFL, fl);
do { do {
int err;
msg.buf = NULL; msg.buf = NULL;
/* read and validate the message */ /* read and validate the message */
if (receive_message(fd, &msg, tmo) == 0) { if (receive_message(fd, &msg, tmo) == 0) {
// FIXME: handle message contents err = handle_message(container, &msg);
ack(fd, msg.seq, tmo); if (!err)
ack(fd, msg.seq, tmo);
else
nack(fd, err, tmo);
} else { } else {
terminate = 1; terminate = 1;
nack(fd, -1, tmo); nack(fd, -1, tmo);
@ -343,7 +375,7 @@ void do_manager(struct supertype *container)
manage(mdstat, array_list, container); manage(mdstat, array_list, container);
read_sock(container->sock); read_sock(container);
mdstat_wait_fd(container->sock); mdstat_wait_fd(container->sock);
} while(1); } while(1);

View File

@ -439,7 +439,8 @@ struct supertype {
struct active_array *arrays; struct active_array *arrays;
int devfd; int devfd;
int sock; /* listen to external programs */ 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; int devnum;
char *devname; /* e.g. md0. This appears in metadata_verison: char *devname; /* e.g. md0. This appears in metadata_verison:
* external:/md0/12 * external:/md0/12

26
mdmon.c
View File

@ -44,6 +44,7 @@
struct active_array *array_list; struct active_array *array_list;
struct active_array *discard_this; struct active_array *discard_this;
struct active_array *pending_discard; struct active_array *pending_discard;
struct md_generic_cmd *active_cmd;
int run_child(void *v) int run_child(void *v)
{ {
@ -54,19 +55,32 @@ int run_child(void *v)
int clone_monitor(struct supertype *container) int clone_monitor(struct supertype *container)
{ {
int pfd[2];
static char stack[4096]; static char stack[4096];
int rv; 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, rv = clone(run_child, stack+4096-64,
CLONE_FS|CLONE_FILES|CLONE_VM|CLONE_SIGHAND|CLONE_THREAD, CLONE_FS|CLONE_FILES|CLONE_VM|CLONE_SIGHAND|CLONE_THREAD,
container); container);
if (rv < 0) if (rv < 0)
goto err_clone;
else
return rv; 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) 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 main(int argc, char *argv[])
{ {
int mdfd; int mdfd;
int pipefd;
struct mdinfo *mdi, *di; struct mdinfo *mdi, *di;
struct supertype *container; struct supertype *container;
if (argc != 2) { if (argc != 2) {
@ -254,8 +267,7 @@ int main(int argc, char *argv[])
mlockall(MCL_FUTURE); mlockall(MCL_FUTURE);
pipefd = clone_monitor(container); if (clone_monitor(container) < 0) {
if (pipefd < 0) {
fprintf(stderr, "md-manage: failed to start monitor process: %s\n", fprintf(stderr, "md-manage: failed to start monitor process: %s\n",
strerror(errno)); strerror(errno));
exit(2); exit(2);

View File

@ -31,6 +31,7 @@ extern struct active_array *container;
extern struct active_array *array_list; extern struct active_array *array_list;
extern struct active_array *discard_this; extern struct active_array *discard_this;
extern struct active_array *pending_discard; extern struct active_array *pending_discard;
extern struct md_generic_cmd *active_cmd;
void do_monitor(struct supertype *container); void do_monitor(struct supertype *container);

View File

@ -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; fd_set rfds;
int maxfd = 0; int maxfd = 0;
@ -408,9 +461,11 @@ static int wait_and_act(struct active_array *aa, int pfd, int nowait)
return rv; return rv;
if (FD_ISSET(pfd, &rfds)) { if (FD_ISSET(pfd, &rfds)) {
char buf[4]; int err = -1;
read(pfd, buf, 4);
; // FIXME read from the pipe 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 rv;
int first = 1; int first = 1;
do { 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; first = 0;
} while (rv >= 0); } while (rv >= 0);
} }

5
msg.h
View File

@ -17,8 +17,8 @@
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#ifndef _MSG_H
#define _MSG_H struct mdinfo;
struct mdinfo; struct mdinfo;
struct md_message { struct md_message {
@ -60,4 +60,3 @@ extern int connect_monitor(char *devname);
extern int ping_monitor(char *devname); extern int ping_monitor(char *devname);
extern int send_remove_device(int fd, dev_t rdev, int seq, int tmo); extern int send_remove_device(int fd, dev_t rdev, int seq, int tmo);
#endif