mirror of
https://github.com/samba-team/samba.git
synced 2024-12-24 21:34:56 +03:00
merge from ronnie
(This used to be ctdb commit e0f1c1acb1188500674626d631e1a1b8726e72ad)
This commit is contained in:
commit
d95476fa38
@ -265,6 +265,8 @@ struct ctdb_statistics {
|
||||
double max_lockwait_latency;
|
||||
};
|
||||
|
||||
|
||||
#define INVALID_GENERATION 1
|
||||
/* table that contains the mapping between a hash value and lmaster
|
||||
*/
|
||||
struct ctdb_vnn_map {
|
||||
@ -506,7 +508,8 @@ struct ctdb_control_tcp_vnn {
|
||||
*/
|
||||
struct ctdb_node_flag_change {
|
||||
uint32_t vnn;
|
||||
uint32_t flags;
|
||||
uint32_t new_flags;
|
||||
uint32_t old_flags;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -230,7 +230,7 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
|
||||
ctdb_release_all_ips(ctdb);
|
||||
ctdb->methods->shutdown(ctdb);
|
||||
ctdb_event_script(ctdb, "shutdown");
|
||||
DEBUG(0,("shutting down\n"));
|
||||
DEBUG(0,("Received SHUTDOWN command. Stopping CTDB daemon.\n"));
|
||||
exit(0);
|
||||
|
||||
case CTDB_CONTROL_MAX_RSN:
|
||||
|
@ -51,7 +51,7 @@ static void flag_change_handler(struct ctdb_context *ctdb, uint64_t srvid,
|
||||
/* don't get the disconnected flag from the other node */
|
||||
ctdb->nodes[c->vnn]->flags =
|
||||
(ctdb->nodes[c->vnn]->flags&NODE_FLAGS_DISCONNECTED)
|
||||
| (c->flags & ~NODE_FLAGS_DISCONNECTED);
|
||||
| (c->new_flags & ~NODE_FLAGS_DISCONNECTED);
|
||||
DEBUG(2,("Node flags for node %u are now 0x%x\n", c->vnn, ctdb->nodes[c->vnn]->flags));
|
||||
|
||||
/* make sure we don't hold any IPs when we shouldn't */
|
||||
@ -218,7 +218,7 @@ int daemon_register_message_handler(struct ctdb_context *ctdb, uint32_t client_i
|
||||
if ((srvid & 0xFFFFFFFF) == srvid &&
|
||||
kill(srvid, 0) == 0) {
|
||||
client->pid = srvid;
|
||||
DEBUG(0,(__location__ " Registered PID %u for client %u\n",
|
||||
DEBUG(3,(__location__ " Registered PID %u for client %u\n",
|
||||
(unsigned)client->pid, client_id));
|
||||
}
|
||||
return res;
|
||||
@ -616,6 +616,10 @@ static int unlink_destructor(const char *name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void print_exit_message(void)
|
||||
{
|
||||
DEBUG(0,("CTDB daemon shutting down\n"));
|
||||
}
|
||||
|
||||
/*
|
||||
start the protocol going as a daemon
|
||||
@ -640,6 +644,9 @@ int ctdb_start_daemon(struct ctdb_context *ctdb, bool do_fork)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Make sure we log something when the daemon terminates */
|
||||
atexit(print_exit_message);
|
||||
|
||||
tdb_reopen_all(False);
|
||||
|
||||
if (do_fork) {
|
||||
|
@ -194,8 +194,19 @@ int32_t ctdb_control_db_attach(struct ctdb_context *ctdb, TDB_DATA indata,
|
||||
{
|
||||
const char *db_name = (const char *)indata.dptr;
|
||||
struct ctdb_db_context *ctdb_db, *tmp_db;
|
||||
struct ctdb_node *node = ctdb->nodes[ctdb->vnn];
|
||||
int ret;
|
||||
|
||||
/* If the node is inactive it is not part of the cluster
|
||||
and we should not allow clients to attach to any
|
||||
databases
|
||||
*/
|
||||
if (node->flags & NODE_FLAGS_INACTIVE) {
|
||||
DEBUG(0,("DB Attach to database %s refused since node is inactive (disconnected or banned)\n", db_name));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* see if we already have this name */
|
||||
for (tmp_db=ctdb->db_list;tmp_db;tmp_db=tmp_db->next) {
|
||||
if (strcmp(db_name, tmp_db->db_name) == 0) {
|
||||
|
@ -103,6 +103,9 @@ static void ctdb_health_callback(struct ctdb_context *ctdb, int status, void *p)
|
||||
timeval_current_ofs(ctdb->tunable.monitor_interval, 0),
|
||||
ctdb_check_health, ctdb);
|
||||
|
||||
c.vnn = ctdb->vnn;
|
||||
c.old_flags = node->flags;
|
||||
|
||||
if (status != 0 && !(node->flags & NODE_FLAGS_UNHEALTHY)) {
|
||||
DEBUG(0,("monitor event failed - disabling node\n"));
|
||||
node->flags |= NODE_FLAGS_UNHEALTHY;
|
||||
@ -114,8 +117,7 @@ static void ctdb_health_callback(struct ctdb_context *ctdb, int status, void *p)
|
||||
return;
|
||||
}
|
||||
|
||||
c.vnn = ctdb->vnn;
|
||||
c.flags = node->flags;
|
||||
c.new_flags = node->flags;
|
||||
|
||||
data.dptr = (uint8_t *)&c;
|
||||
data.dsize = sizeof(c);
|
||||
@ -206,7 +208,8 @@ int32_t ctdb_control_modflags(struct ctdb_context *ctdb, TDB_DATA indata)
|
||||
|
||||
/* if we have been banned, go into recovery mode */
|
||||
c.vnn = ctdb->vnn;
|
||||
c.flags = node->flags;
|
||||
c.old_flags = old_flags;
|
||||
c.new_flags = node->flags;
|
||||
|
||||
data.dptr = (uint8_t *)&c;
|
||||
data.dsize = sizeof(c);
|
||||
@ -218,6 +221,13 @@ int32_t ctdb_control_modflags(struct ctdb_context *ctdb, TDB_DATA indata)
|
||||
if ((node->flags & NODE_FLAGS_BANNED) && !(old_flags & NODE_FLAGS_BANNED)) {
|
||||
/* make sure we are frozen */
|
||||
DEBUG(0,("This node has been banned - forcing freeze and recovery\n"));
|
||||
/* Reset the generation id to 1 to make us ignore any
|
||||
REQ/REPLY CALL/DMASTER someone sends to us.
|
||||
We are now banned so we shouldnt service database calls
|
||||
anymore.
|
||||
*/
|
||||
ctdb->vnn_map->generation = INVALID_GENERATION;
|
||||
|
||||
ctdb_start_freeze(ctdb);
|
||||
ctdb_release_all_ips(ctdb);
|
||||
ctdb->recovery_mode = CTDB_RECOVERY_ACTIVE;
|
||||
|
@ -386,7 +386,8 @@ static int update_flags_on_all_nodes(struct ctdb_context *ctdb, struct ctdb_node
|
||||
TDB_DATA data;
|
||||
|
||||
c.vnn = nodemap->nodes[i].vnn;
|
||||
c.flags = nodemap->nodes[i].flags;
|
||||
c.old_flags = nodemap->nodes[i].flags;
|
||||
c.new_flags = nodemap->nodes[i].flags;
|
||||
|
||||
data.dptr = (uint8_t *)&c;
|
||||
data.dsize = sizeof(c);
|
||||
@ -610,6 +611,24 @@ static void ctdb_wait_timeout(struct ctdb_context *ctdb, uint32_t secs)
|
||||
}
|
||||
}
|
||||
|
||||
/* Create a new random generation ip.
|
||||
The generation id can not be the INVALID_GENERATION id
|
||||
*/
|
||||
static uint32_t new_generation(void)
|
||||
{
|
||||
uint32_t generation;
|
||||
|
||||
while (1) {
|
||||
generation = random();
|
||||
|
||||
if (generation != INVALID_GENERATION) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return generation;
|
||||
}
|
||||
|
||||
/*
|
||||
we are the recmaster, and recovery is needed - start a recovery run
|
||||
*/
|
||||
@ -654,7 +673,7 @@ static int do_recovery(struct ctdb_recoverd *rec,
|
||||
DEBUG(0, (__location__ " Recovery initiated due to problem with node %u\n", culprit));
|
||||
|
||||
/* pick a new generation number */
|
||||
generation = random();
|
||||
generation = new_generation();
|
||||
|
||||
/* change the vnnmap on this node to use the new generation
|
||||
number but not on any other nodes.
|
||||
@ -728,7 +747,7 @@ static int do_recovery(struct ctdb_recoverd *rec,
|
||||
|
||||
/* build a new vnn map with all the currently active and
|
||||
unbanned nodes */
|
||||
generation = random();
|
||||
generation = new_generation();
|
||||
vnnmap = talloc(mem_ctx, struct ctdb_vnn_map);
|
||||
CTDB_NO_MEMORY(ctdb, vnnmap);
|
||||
vnnmap->generation = generation;
|
||||
@ -815,7 +834,7 @@ static int do_recovery(struct ctdb_recoverd *rec,
|
||||
|
||||
/* send a message to all clients telling them that the cluster
|
||||
has been reconfigured */
|
||||
ctdb_send_message(ctdb, CTDB_BROADCAST_ALL, CTDB_SRVID_RECONFIGURE, tdb_null);
|
||||
ctdb_send_message(ctdb, CTDB_BROADCAST_CONNECTED, CTDB_SRVID_RECONFIGURE, tdb_null);
|
||||
|
||||
DEBUG(0, (__location__ " Recovery complete\n"));
|
||||
|
||||
@ -1045,6 +1064,7 @@ static void monitor_handler(struct ctdb_context *ctdb, uint64_t srvid,
|
||||
struct ctdb_node_flag_change *c = (struct ctdb_node_flag_change *)data.dptr;
|
||||
struct ctdb_node_map *nodemap=NULL;
|
||||
TALLOC_CTX *tmp_ctx;
|
||||
uint32_t changed_flags;
|
||||
int i;
|
||||
|
||||
if (data.dsize != sizeof(*c)) {
|
||||
@ -1067,20 +1087,22 @@ static void monitor_handler(struct ctdb_context *ctdb, uint64_t srvid,
|
||||
return;
|
||||
}
|
||||
|
||||
changed_flags = c->old_flags ^ c->new_flags;
|
||||
|
||||
/* Dont let messages from remote nodes change the DISCONNECTED flag.
|
||||
This flag is handled locally based on whether the local node
|
||||
can communicate with the node or not.
|
||||
*/
|
||||
c->flags &= ~NODE_FLAGS_DISCONNECTED;
|
||||
c->new_flags &= ~NODE_FLAGS_DISCONNECTED;
|
||||
if (nodemap->nodes[i].flags&NODE_FLAGS_DISCONNECTED) {
|
||||
c->flags |= NODE_FLAGS_DISCONNECTED;
|
||||
c->new_flags |= NODE_FLAGS_DISCONNECTED;
|
||||
}
|
||||
|
||||
if (nodemap->nodes[i].flags != c->flags) {
|
||||
DEBUG(0,("Node %u has changed flags - now 0x%x\n", c->vnn, c->flags));
|
||||
if (nodemap->nodes[i].flags != c->new_flags) {
|
||||
DEBUG(0,("Node %u has changed flags - now 0x%x was 0x%x\n", c->vnn, c->new_flags, c->old_flags));
|
||||
}
|
||||
|
||||
nodemap->nodes[i].flags = c->flags;
|
||||
nodemap->nodes[i].flags = c->new_flags;
|
||||
|
||||
ret = ctdb_ctrl_getrecmaster(ctdb, CONTROL_TIMEOUT(),
|
||||
CTDB_CURRENT_NODE, &ctdb->recovery_master);
|
||||
@ -1094,9 +1116,21 @@ static void monitor_handler(struct ctdb_context *ctdb, uint64_t srvid,
|
||||
ctdb->recovery_master == ctdb->vnn &&
|
||||
ctdb->recovery_mode == CTDB_RECOVERY_NORMAL &&
|
||||
ctdb->takeover.enabled) {
|
||||
ret = ctdb_takeover_run(ctdb, nodemap);
|
||||
if (ret != 0) {
|
||||
DEBUG(0, (__location__ " Unable to setup public takeover addresses\n"));
|
||||
/* Only do the takeover run if the perm disabled or unhealthy
|
||||
flags changed since these will cause an ip failover but not
|
||||
a recovery.
|
||||
If the node became disconnected or banned this will also
|
||||
lead to an ip address failover but that is handled
|
||||
during recovery
|
||||
*/
|
||||
if (changed_flags & NODE_FLAGS_DISABLED) {
|
||||
ret = ctdb_takeover_run(ctdb, nodemap);
|
||||
if (ret != 0) {
|
||||
DEBUG(0, (__location__ " Unable to setup public takeover addresses\n"));
|
||||
}
|
||||
/* send a message to all clients telling them that the
|
||||
cluster has been reconfigured */
|
||||
ctdb_send_message(ctdb, CTDB_BROADCAST_CONNECTED, CTDB_SRVID_RECONFIGURE, tdb_null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -151,17 +151,10 @@ int ctdb_set_nlist(struct ctdb_context *ctdb, const char *nlist)
|
||||
}
|
||||
|
||||
/* initialize the vnn mapping table now that we have num_nodes setup */
|
||||
/*
|
||||
XXX we currently initialize it to the maximum number of nodes to
|
||||
XXX make it behave the same way as previously.
|
||||
XXX Once we have recovery working we should initialize this always to
|
||||
XXX generation==0 (==invalid) and let the recovery tool populate this
|
||||
XXX table for the daemons.
|
||||
*/
|
||||
ctdb->vnn_map = talloc(ctdb, struct ctdb_vnn_map);
|
||||
CTDB_NO_MEMORY(ctdb, ctdb->vnn_map);
|
||||
|
||||
ctdb->vnn_map->generation = 1;
|
||||
ctdb->vnn_map->generation = INVALID_GENERATION;
|
||||
ctdb->vnn_map->size = ctdb->num_nodes;
|
||||
ctdb->vnn_map->map = talloc_array(ctdb->vnn_map, uint32_t, ctdb->vnn_map->size);
|
||||
CTDB_NO_MEMORY(ctdb, ctdb->vnn_map->map);
|
||||
@ -232,6 +225,18 @@ void ctdb_input_pkt(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
|
||||
case CTDB_REPLY_CALL:
|
||||
case CTDB_REQ_DMASTER:
|
||||
case CTDB_REPLY_DMASTER:
|
||||
/* we dont allow these calls when banned */
|
||||
if (ctdb->nodes[ctdb->vnn]->flags & NODE_FLAGS_BANNED) {
|
||||
DEBUG(0,(__location__ " ctdb operation %u"
|
||||
" request %u"
|
||||
" length %u from node %u to %u while node"
|
||||
" is banned\n",
|
||||
hdr->operation, hdr->reqid,
|
||||
hdr->length,
|
||||
hdr->srcnode, hdr->destnode));
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* for ctdb_call inter-node operations verify that the
|
||||
remote node that sent us the call is running in the
|
||||
same generation instance as this node
|
||||
|
@ -524,6 +524,19 @@ int ctdb_takeover_run(struct ctdb_context *ctdb, struct ctdb_node_map *nodemap)
|
||||
if (!(nodemap->nodes[i].flags & (NODE_FLAGS_INACTIVE|NODE_FLAGS_DISABLED))) {
|
||||
ctdb->nodes[i]->takeover_vnn = nodemap->nodes[i].vnn;
|
||||
} else {
|
||||
uint32_t takeover_vnn;
|
||||
|
||||
/* If this public address has already been taken over
|
||||
by a node and that node is still healthy, then
|
||||
leave the public address at that node.
|
||||
*/
|
||||
takeover_vnn = ctdb->nodes[i]->takeover_vnn;
|
||||
if ( ctdb_validate_vnn(ctdb, takeover_vnn)
|
||||
&& (!(nodemap->nodes[takeover_vnn].flags & (NODE_FLAGS_INACTIVE|NODE_FLAGS_DISABLED))) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
ctdb->nodes[i]->takeover_vnn = (uint32_t)-1;
|
||||
|
||||
ctdb_takeover_find_node(ctdb, nodemap, i, NODE_FLAGS_INACTIVE|NODE_FLAGS_DISABLED);
|
||||
|
@ -147,6 +147,14 @@ int main(int argc, const char *argv[])
|
||||
|
||||
ctdb = ctdb_cmdline_init(ev);
|
||||
|
||||
ret = ctdb_set_logfile(ctdb, options.logfile);
|
||||
if (ret == -1) {
|
||||
printf("ctdb_set_logfile to %s failed - %s\n", options.logfile, ctdb_errstr(ctdb));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
DEBUG(0,("Starting CTDB daemon\n"));
|
||||
|
||||
ctdb->recovery_mode = CTDB_RECOVERY_NORMAL;
|
||||
ctdb->recovery_master = (uint32_t)-1;
|
||||
ctdb->upcalls = &ctdb_upcalls;
|
||||
@ -158,13 +166,13 @@ int main(int argc, const char *argv[])
|
||||
|
||||
ret = ctdb_set_recovery_lock_file(ctdb, options.recovery_lock_file);
|
||||
if (ret == -1) {
|
||||
printf("ctdb_set_recovery_lock_file failed - %s\n", ctdb_errstr(ctdb));
|
||||
DEBUG(0,("ctdb_set_recovery_lock_file failed - %s\n", ctdb_errstr(ctdb)));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = ctdb_set_transport(ctdb, options.transport);
|
||||
if (ret == -1) {
|
||||
printf("ctdb_set_transport failed - %s\n", ctdb_errstr(ctdb));
|
||||
DEBUG(0,("ctdb_set_transport failed - %s\n", ctdb_errstr(ctdb)));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -172,7 +180,7 @@ int main(int argc, const char *argv[])
|
||||
if (options.myaddress) {
|
||||
ret = ctdb_set_address(ctdb, options.myaddress);
|
||||
if (ret == -1) {
|
||||
printf("ctdb_set_address failed - %s\n", ctdb_errstr(ctdb));
|
||||
DEBUG(0,("ctdb_set_address failed - %s\n", ctdb_errstr(ctdb)));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@ -180,24 +188,18 @@ int main(int argc, const char *argv[])
|
||||
/* tell ctdb what nodes are available */
|
||||
ret = ctdb_set_nlist(ctdb, options.nlist);
|
||||
if (ret == -1) {
|
||||
printf("ctdb_set_nlist failed - %s\n", ctdb_errstr(ctdb));
|
||||
DEBUG(0,("ctdb_set_nlist failed - %s\n", ctdb_errstr(ctdb)));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (options.db_dir) {
|
||||
ret = ctdb_set_tdb_dir(ctdb, options.db_dir);
|
||||
if (ret == -1) {
|
||||
printf("ctdb_set_tdb_dir failed - %s\n", ctdb_errstr(ctdb));
|
||||
DEBUG(0,("ctdb_set_tdb_dir failed - %s\n", ctdb_errstr(ctdb)));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
ret = ctdb_set_logfile(ctdb, options.logfile);
|
||||
if (ret == -1) {
|
||||
printf("ctdb_set_logfile to %s failed - %s\n", options.logfile, ctdb_errstr(ctdb));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (options.public_interface) {
|
||||
ctdb->takeover.interface = talloc_strdup(ctdb, options.public_interface);
|
||||
CTDB_NO_MEMORY(ctdb, ctdb->takeover.interface);
|
||||
@ -206,7 +208,7 @@ int main(int argc, const char *argv[])
|
||||
if (options.public_address_list) {
|
||||
ret = ctdb_set_public_addresses(ctdb, options.public_address_list);
|
||||
if (ret == -1) {
|
||||
printf("Unable to setup public address list\n");
|
||||
DEBUG(0,("Unable to setup public address list\n"));
|
||||
exit(1);
|
||||
}
|
||||
ctdb->takeover.enabled = true;
|
||||
@ -214,7 +216,7 @@ int main(int argc, const char *argv[])
|
||||
|
||||
ret = ctdb_set_event_script_dir(ctdb, options.event_script_dir);
|
||||
if (ret == -1) {
|
||||
printf("Unable to setup event script directory\n");
|
||||
DEBUG(0,("Unable to setup event script directory\n"));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
@ -98,6 +98,7 @@ static int ctdb_event_script_v(struct ctdb_context *ctdb, const char *fmt, va_li
|
||||
while ((de=readdir(dir)) != NULL) {
|
||||
int namlen;
|
||||
unsigned num;
|
||||
char *str;
|
||||
|
||||
namlen = strlen(de->d_name);
|
||||
|
||||
@ -117,6 +118,18 @@ static int ctdb_event_script_v(struct ctdb_context *ctdb, const char *fmt, va_li
|
||||
if (sscanf(de->d_name, "%02u.", &num) != 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Make sure the event script is executable */
|
||||
str = talloc_asprintf(tree, "%s/%s", ctdb->takeover.event_script_dir, de->d_name);
|
||||
if (stat(str, &st) != 0) {
|
||||
DEBUG(0,("Could not stat event script %s. Ignoring this event script\n", str));
|
||||
continue;
|
||||
}
|
||||
if (!(st.st_mode & S_IXUSR)) {
|
||||
DEBUG(0,("Event script %s is not executable. Ignoring this event script\n", str));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
/* store the event script in the tree */
|
||||
script = trbt_insert32(tree, num, talloc_strdup(tree, de->d_name));
|
||||
|
@ -282,7 +282,11 @@ static int control_status(struct ctdb_context *ctdb, int argc, const char **argv
|
||||
DEBUG(0, ("Unable to get vnnmap from node %u\n", options.vnn));
|
||||
return ret;
|
||||
}
|
||||
printf("Generation:%d\n",vnnmap->generation);
|
||||
if (vnnmap->generation == INVALID_GENERATION) {
|
||||
printf("Generation:INVALID\n");
|
||||
} else {
|
||||
printf("Generation:%d\n",vnnmap->generation);
|
||||
}
|
||||
printf("Size:%d\n",vnnmap->size);
|
||||
for(i=0;i<vnnmap->size;i++){
|
||||
printf("hash:%d lmaster:%d\n", i, vnnmap->map[i]);
|
||||
|
Loading…
Reference in New Issue
Block a user