X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fmdadm.git;a=blobdiff_plain;f=managemon.c;h=c5ba2f4c40a7b4d88069f889a1723e9018212fae;hp=14e7184b0359801dd5fd9b25b3c674011635d177;hb=8c21018330e6adc15f347bd7c9e924866b8ca608;hpb=c052ba301b417d4fc8493d95a4a87f0472cc0483 diff --git a/managemon.c b/managemon.c index 14e7184b..c5ba2f4c 100644 --- a/managemon.c +++ b/managemon.c @@ -76,12 +76,26 @@ #include "mdmon.h" #include +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; @@ -90,6 +104,18 @@ static void free_aa(struct active_array *aa) 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) @@ -115,6 +141,7 @@ static void replace_array(struct supertype *container, new->replaces = old; new->next = container->arrays; container->arrays = new; + write_wakeup(container); } @@ -158,13 +185,9 @@ static void manage_member(struct mdstat_ent *mdstat, } -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. @@ -200,7 +223,7 @@ static void manage_new(struct mdstat_ent *mdstat, * Mark it to be ignored by setting container to NULL */ new->container = NULL; - replace_array(container, NULL, new); + replace_array(container, victim, new); return; } @@ -236,15 +259,15 @@ static void manage_new(struct mdstat_ent *mdstat, 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; } @@ -278,20 +301,70 @@ void manage(struct mdstat_ent *mdstat, struct active_array *aa, 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) @@ -303,7 +376,9 @@ 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);