diff options
author | Dan Williams <dan.j.williams@intel.com> | 2008-05-15 16:48:54 +1000 |
---|---|---|
committer | Neil Brown <neilb@suse.de> | 2008-05-15 16:48:54 +1000 |
commit | 3e70c845e25295d80680d884d5671107bf8bded3 (patch) | |
tree | 3a8b69bb18e66ee64db5c6a0705d90a9f0843e02 /monitor.c | |
parent | b109d92863bfa319d140b305132ca41bfb8d1194 (diff) | |
download | mdadm-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>
Diffstat (limited to 'monitor.c')
-rw-r--r-- | monitor.c | 66 |
1 files changed, 61 insertions, 5 deletions
@@ -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); } |