summaryrefslogtreecommitdiffstats
path: root/monitor.c
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 /monitor.c
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>
Diffstat (limited to 'monitor.c')
-rw-r--r--monitor.c66
1 files changed, 61 insertions, 5 deletions
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);
}