diff options
author | Andrew Tridgell <tridge@samba.org> | 2007-05-30 13:26:50 +1000 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2007-05-30 13:26:50 +1000 |
commit | 8ed48aac5100933d5f81836b3d33e646af7a3819 (patch) | |
tree | aa2a5b6e62c4fc0fdfdc973d0309a4b982b9e4d8 | |
parent | 3eb96b4553a6cad3b317ab1bffd4779f747dd665 (diff) | |
download | samba-8ed48aac5100933d5f81836b3d33e646af7a3819.tar.gz samba-8ed48aac5100933d5f81836b3d33e646af7a3819.tar.xz samba-8ed48aac5100933d5f81836b3d33e646af7a3819.zip |
don't start the transport connecting to the other nodes until after the startup event script has run
(This used to be ctdb commit afca3cc74211aa2e18b1f74d36b2add8dffcfdc7)
-rw-r--r-- | ctdb/common/ctdb_daemon.c | 48 | ||||
-rw-r--r-- | ctdb/common/ctdb_recoverd.c | 4 | ||||
-rw-r--r-- | ctdb/ib/ibw_ctdb_init.c | 16 | ||||
-rw-r--r-- | ctdb/include/ctdb_private.h | 4 | ||||
-rw-r--r-- | ctdb/takeover/system.c | 107 | ||||
-rw-r--r-- | ctdb/tcp/tcp_init.c | 15 |
6 files changed, 168 insertions, 26 deletions
diff --git a/ctdb/common/ctdb_daemon.c b/ctdb/common/ctdb_daemon.c index 015b8a1868..1ffd70f61f 100644 --- a/ctdb/common/ctdb_daemon.c +++ b/ctdb/common/ctdb_daemon.c @@ -31,6 +31,28 @@ static void daemon_incoming_packet(void *, struct ctdb_req_header *); +/* called when the "startup" event script has finished */ +static void ctdb_start_transport(struct ctdb_context *ctdb, int status) +{ + if (status != 0) { + DEBUG(0,("startup event failed!\n")); + ctdb_fatal(ctdb, "startup event script failed"); + } + + /* start the transport running */ + if (ctdb->methods->start(ctdb) != 0) { + DEBUG(0,("transport failed to start!\n")); + ctdb_fatal(ctdb, "transport failed to start"); + } + + /* start the recovery daemon process */ + if (ctdb_start_recoverd(ctdb) != 0) { + DEBUG(0,("Failed to start recovery daemon\n")); + exit(11); + } +} + +/* go into main ctdb loop */ static void ctdb_main_loop(struct ctdb_context *ctdb) { int ret = -1; @@ -50,16 +72,10 @@ static void ctdb_main_loop(struct ctdb_context *ctdb) return; } - ret = ctdb_event_script(ctdb, "startup"); - if (ret != 0) { - DEBUG(0,("Failed startup event script\n")); - return; - } - - /* start the transport running */ - if (ctdb->methods->start(ctdb) != 0) { - DEBUG(0,("transport failed to start!\n")); - ctdb_fatal(ctdb, "transport failed to start"); + /* initialise the transport */ + if (ctdb->methods->initialise(ctdb) != 0) { + DEBUG(0,("transport failed to initialise!\n")); + ctdb_fatal(ctdb, "transport failed to initialise"); } /* tell all other nodes we've just started up */ @@ -68,6 +84,12 @@ static void ctdb_main_loop(struct ctdb_context *ctdb) CTDB_CTRL_FLAG_NOREPLY, tdb_null, NULL, NULL); + ret = ctdb_event_script_callback(ctdb, ctdb_start_transport, "startup"); + if (ret != 0) { + DEBUG(0,("Failed startup event script\n")); + return; + } + /* go into a wait loop to allow other nodes to complete */ event_loop_wait(ctdb->ev); @@ -744,12 +766,6 @@ int ctdb_start_daemon(struct ctdb_context *ctdb, bool do_fork) /* try to set us up as realtime */ ctdb_set_realtime(); - /* start the recovery daemon process */ - if (ctdb_start_recoverd(ctdb) != 0) { - DEBUG(0,("Failed to start recovery daemon\n")); - exit(11); - } - /* ensure the socket is deleted on exit of the daemon */ domain_socket_name = talloc_strdup(talloc_autofree_context(), ctdb->daemon.name); talloc_set_destructor(domain_socket_name, unlink_destructor); diff --git a/ctdb/common/ctdb_recoverd.c b/ctdb/common/ctdb_recoverd.c index dca340bff2..b05b02050f 100644 --- a/ctdb/common/ctdb_recoverd.c +++ b/ctdb/common/ctdb_recoverd.c @@ -972,6 +972,10 @@ int ctdb_start_recoverd(struct ctdb_context *ctdb) close(fd[1]); + /* we need a new event context */ + talloc_free(ctdb->ev); + ctdb->ev = event_context_init(ctdb); + event_add_fd(ctdb->ev, ctdb, fd[0], EVENT_FD_READ|EVENT_FD_AUTOCLOSE, ctdb_recoverd_parent, &fd[0]); diff --git a/ctdb/ib/ibw_ctdb_init.c b/ctdb/ib/ibw_ctdb_init.c index 66919568df..b41c61687b 100644 --- a/ctdb/ib/ibw_ctdb_init.c +++ b/ctdb/ib/ibw_ctdb_init.c @@ -70,9 +70,9 @@ static int ctdb_ibw_add_node(struct ctdb_node *node) } /* - * Start infiniband + * initialise infiniband */ -static int ctdb_ibw_start(struct ctdb_context *ctdb) +static int ctdb_ibw_initialise(struct ctdb_context *ctdb) { int i, ret; @@ -88,6 +88,17 @@ static int ctdb_ibw_start(struct ctdb_context *ctdb) } } + return 0; +} + + +/* + * Start infiniband + */ +static int ctdb_ibw_start(struct ctdb_context *ctdb) +{ + int i, ret; + /* listen on our own address */ if (ctdb_ibw_listen(ctdb, 10)) /* TODO: backlog as param */ return -1; @@ -190,6 +201,7 @@ static int ctdb_ibw_stop(struct ctdb_context *cctx) #endif /* __NOTDEF__ */ static const struct ctdb_methods ctdb_ibw_methods = { + .initialise= ctdb_ibw_initialise, .start = ctdb_ibw_start, .queue_pkt = ctdb_ibw_queue_pkt, .add_node = ctdb_ibw_add_node, diff --git a/ctdb/include/ctdb_private.h b/ctdb/include/ctdb_private.h index 37176748e9..92cc1a4263 100644 --- a/ctdb/include/ctdb_private.h +++ b/ctdb/include/ctdb_private.h @@ -129,6 +129,7 @@ struct ctdb_node { transport specific methods */ struct ctdb_methods { + int (*initialise)(struct ctdb_context *); /* initialise transport structures */ int (*start)(struct ctdb_context *); /* start protocol processing */ int (*add_node)(struct ctdb_node *); /* setup a new node */ int (*queue_pkt)(struct ctdb_node *, uint8_t *data, uint32_t length); @@ -949,6 +950,9 @@ int32_t ctdb_control_startup(struct ctdb_context *ctdb, uint32_t vnn); void ctdb_takeover_client_destructor_hook(struct ctdb_client *client); int ctdb_event_script(struct ctdb_context *ctdb, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); +int ctdb_event_script_callback(struct ctdb_context *ctdb, + void (*callback)(struct ctdb_context *, int), + const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); void ctdb_release_all_ips(struct ctdb_context *ctdb); diff --git a/ctdb/takeover/system.c b/ctdb/takeover/system.c index c6624f2485..a1b6da6cf5 100644 --- a/ctdb/takeover/system.c +++ b/ctdb/takeover/system.c @@ -24,6 +24,7 @@ #include "system/filesys.h" #include "system/wait.h" #include "../include/ctdb_private.h" +#include "lib/events/events.h" #include <net/ethernet.h> #include <net/if_arp.h> @@ -258,17 +259,24 @@ bool ctdb_sys_have_ip(const char *ip) } /* - run the event script + run the event script - varargs version */ -int ctdb_event_script(struct ctdb_context *ctdb, const char *fmt, ...) +static int ctdb_event_script_v(struct ctdb_context *ctdb, const char *fmt, va_list ap) { - va_list ap; char *options, *cmdstr; int ret; + va_list ap2; + struct stat st; - va_start(ap, fmt); - options = talloc_vasprintf(ctdb, fmt, ap); - va_end(ap); + if (stat(ctdb->takeover.event_script, &st) != 0 && + errno == ENOENT) { + DEBUG(0,("No event script found at '%s'\n", ctdb->takeover.event_script)); + return 0; + } + + va_copy(ap2, ap); + options = talloc_vasprintf(ctdb, fmt, ap2); + va_end(ap2); CTDB_NO_MEMORY(ctdb, options); cmdstr = talloc_asprintf(ctdb, "%s %s", ctdb->takeover.event_script, options); @@ -285,3 +293,90 @@ int ctdb_event_script(struct ctdb_context *ctdb, const char *fmt, ...) return ret; } +/* + run the event script + */ +int ctdb_event_script(struct ctdb_context *ctdb, const char *fmt, ...) +{ + va_list ap; + int ret; + + va_start(ap, fmt); + ret = ctdb_event_script_v(ctdb, fmt, ap); + va_end(ap); + + return ret; +} + + +struct ctdb_event_script_state { + struct ctdb_context *ctdb; + pid_t child; + void (*callback)(struct ctdb_context *, int); + int fd[2]; +}; + +/* called when child is finished */ +static void ctdb_event_script_handler(struct event_context *ev, struct fd_event *fde, + uint16_t flags, void *p) +{ + struct ctdb_event_script_state *state = + talloc_get_type(p, struct ctdb_event_script_state); + int status = -1; + waitpid(state->child, &status, 0); + if (status != -1) { + status = WEXITSTATUS(status); + } + state->callback(state->ctdb, status); + talloc_free(state); +} + + +/* + run the event script in the background, calling the callback when + finished + */ +int ctdb_event_script_callback(struct ctdb_context *ctdb, + void (*callback)(struct ctdb_context *, int), + const char *fmt, ...) +{ + struct ctdb_event_script_state *state; + va_list ap; + int ret; + + state = talloc(ctdb, struct ctdb_event_script_state); + CTDB_NO_MEMORY(ctdb, state); + + state->ctdb = ctdb; + state->callback = callback; + + ret = pipe(state->fd); + if (ret != 0) { + talloc_free(state); + return -1; + } + + state->child = fork(); + + if (state->child == (pid_t)-1) { + close(state->fd[0]); + close(state->fd[1]); + talloc_free(state); + return -1; + } + + if (state->child == 0) { + close(state->fd[0]); + va_start(ap, fmt); + ret = ctdb_event_script_v(ctdb, fmt, ap); + va_end(ap); + _exit(ret); + } + + close(state->fd[1]); + + event_add_fd(ctdb->ev, state, state->fd[0], EVENT_FD_READ|EVENT_FD_AUTOCLOSE, + ctdb_event_script_handler, state); + + return 0; +} diff --git a/ctdb/tcp/tcp_init.c b/ctdb/tcp/tcp_init.c index 35b43bd5e2..665336e947 100644 --- a/ctdb/tcp/tcp_init.c +++ b/ctdb/tcp/tcp_init.c @@ -46,9 +46,9 @@ static int ctdb_tcp_add_node(struct ctdb_node *node) } /* - start the protocol going + initialise transport structures */ -static int ctdb_tcp_start(struct ctdb_context *ctdb) +static int ctdb_tcp_initialise(struct ctdb_context *ctdb) { int i; @@ -59,6 +59,16 @@ static int ctdb_tcp_start(struct ctdb_context *ctdb) } } + return 0; +} + +/* + start the protocol going +*/ +static int ctdb_tcp_start(struct ctdb_context *ctdb) +{ + int i; + /* listen on our own address */ if (ctdb_tcp_listen(ctdb) != 0) return -1; @@ -90,6 +100,7 @@ static void *ctdb_tcp_allocate_pkt(TALLOC_CTX *mem_ctx, size_t size) static const struct ctdb_methods ctdb_tcp_methods = { + .initialise = ctdb_tcp_initialise, .start = ctdb_tcp_start, .queue_pkt = ctdb_tcp_queue_pkt, .add_node = ctdb_tcp_add_node, |