If we shutdown through a ctdb_fatal(), unless there is an external mechanism to trap this and restart ctdb, we will get a duplicate address problem since addresses held on the node remain which collides with the addresses when failed over to other nodes.
During ctdb_fatal(), spawn a child process to try to drop all held public addresses.
void ctdb_fatal(struct ctdb_context *ctdb, const char *msg)
{
DEBUG(DEBUG_ALERT,("ctdb fatal error: %s\n", msg));
+ if (ctdb->emergency_shutdown != NULL) {
+ ctdb->emergency_shutdown(ctdb);
+ }
abort();
}
/* used in the recovery daemon to remember the ip allocation */
struct trbt_tree *ip_tree;
+
+ /* emergency shutdown cleanup */
+ void (*emergency_shutdown)(struct ctdb_context *);
};
struct ctdb_db_context {
int update_ip_assignment_tree(struct ctdb_context *ctdb,
struct ctdb_public_ip *ip);
+void ctdb_emergency_shutdown(struct ctdb_context *ctdb);
+
#endif
exit(11);
}
+ /* set up a function so we try to clean up during emergency shutdown such as ctdb_fatal()
+ at the very least we should drop all ips at this stage
+ */
+ ctdb->emergency_shutdown = ctdb_emergency_shutdown;
+
/* Make sure we log something when the daemon terminates */
atexit(print_exit_message);
return 0;
}
+
+void ctdb_emergency_shutdown(struct ctdb_context *ctdb)
+{
+ DEBUG(DEBUG_ERR,("CTDB_FATAL create child process to release all held ips\n"));
+ if (fork() == 0) {
+ DEBUG(DEBUG_ERR,("CTDB_FATAL drop all ip\n"));
+ ctdb_release_all_ips(ctdb);
+ DEBUG(DEBUG_ERR,("CTDB_FATAL all ips dropped\n"));
+ _exit(0);
+ }
+}