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:
parent
b109d92863
commit
3e70c845e2
48
managemon.c
48
managemon.c
|
@ -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);
|
||||||
|
|
3
mdadm.h
3
mdadm.h
|
@ -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
26
mdmon.c
|
@ -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);
|
||||||
|
|
1
mdmon.h
1
mdmon.h
|
@ -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);
|
||||||
|
|
66
monitor.c
66
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;
|
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
5
msg.h
|
@ -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
|
|
||||||
|
|
Loading…
Reference in New Issue