#include "mdmon.h"
#include <sys/socket.h>
+static void close_aa(struct active_array *aa)
+{
+ struct mdinfo *d;
+
+ for (d = aa->info.devs; d; d = d->next)
+ close(d->state_fd);
+
+ close(aa->action_fd);
+ close(aa->info.state_fd);
+ close(aa->resync_start_fd);
+ close(aa->sync_pos_fd);
+}
static void free_aa(struct active_array *aa)
{
- /* Note that this doesn't close fds, as they may be in used
- * by a clone. Use close_aa for that.
+ /* Note that this doesn't close fds if they are being used
+ * by a clone. ->container will be set for a clone
*/
+ if (!aa->container)
+ close_aa(aa);
while (aa->info.devs) {
struct mdinfo *d = aa->info.devs;
aa->info.devs = d->next;
free(aa);
}
+static void write_wakeup(struct supertype *c)
+{
+ 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,
struct active_array *old,
struct active_array *new)
new->replaces = old;
new->next = container->arrays;
container->arrays = new;
+ write_wakeup(container);
}
}
-static void write_wakeup(struct supertype *c)
-{
- write(c->pipe[1], "PING", 4);
-}
-
static void manage_new(struct mdstat_ent *mdstat,
- struct supertype *container)
+ struct supertype *container,
+ struct active_array *victim)
{
/* A new array has appeared in this container.
* Hopefully it is already recorded in the metadata.
* Mark it to be ignored by setting container to NULL
*/
new->container = NULL;
- replace_array(container, NULL, new);
+ replace_array(container, victim, new);
return;
}
new->sync_pos_fd = sysfs_open(new->devnum, NULL, "sync_completed");
new->sync_pos = 0;
+ sysfs_free(mdi);
// finds and compares.
if (container->ss->open_new(container, new, inst) < 0) {
// FIXME close all those files
new->container = NULL;
- replace_array(container, NULL, new);
+ replace_array(container, victim, new);
return;
}
- replace_array(container, NULL, new);
- write_wakeup(container);
+ replace_array(container, victim, new);
return;
}
break;
}
}
- if (a == NULL)
- manage_new(mdstat, container);
+ if (a == NULL || !a->container)
+ manage_new(mdstat, container, a);
+ }
+}
+
+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(int pfd)
+void read_sock(struct supertype *container)
{
int fd;
+ struct md_message msg;
+ int terminate = 0;
+ long fl;
+ int tmo = 3; /* 3 second timeout before hanging up the socket */
- // FIXME set non-blocking
- fd = accept(pfd, NULL, NULL);
+ fd = accept(container->sock, NULL, NULL);
if (fd < 0)
return;
- // FIXME do something useful
+
+ fl = fcntl(fd, F_GETFL, 0);
+ fl |= O_NONBLOCK;
+ fcntl(fd, F_SETFL, fl);
+
+ do {
+ int err;
+
+ msg.buf = NULL;
+
+ /* read and validate the message */
+ if (receive_message(fd, &msg, tmo) == 0) {
+ err = handle_message(container, &msg);
+ if (!err)
+ ack(fd, msg.seq, tmo);
+ else
+ nack(fd, err, tmo);
+ } else {
+ terminate = 1;
+ nack(fd, -1, tmo);
+ }
+
+ if (msg.buf)
+ free(msg.buf);
+ } while (!terminate);
+
close(fd);
}
void do_manager(struct supertype *container)
manage(mdstat, array_list, container);
- read_sock(container->sock);
+ read_sock(container);
+
+ free_mdstat(mdstat);
mdstat_wait_fd(container->sock);
} while(1);