1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-10 01:18:15 +03:00

ctdb-recovery: Create database on nodes where it is missing

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14294

Signed-off-by: Martin Schwenke <martin@meltin.net>
Reviewed-by: Amitay Isaacs <amitay@gmail.com>
This commit is contained in:
Martin Schwenke 2020-02-24 11:31:33 +11:00 committed by Martin Schwenke
parent e6e63f8fb8
commit 76a8174279

View File

@ -294,6 +294,150 @@ static int db_list_check_and_add(struct db_list *dblist,
return 0;
}
/*
* Create database on nodes where it is missing
*/
struct db_create_missing_state {
struct tevent_context *ev;
struct ctdb_client_context *client;
struct node_list *nlist;
const char *db_name;
uint32_t *missing_pnn_list;
int missing_num_nodes;
};
static void db_create_missing_done(struct tevent_req *subreq);
static struct tevent_req *db_create_missing_send(
TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct ctdb_client_context *client,
struct node_list *nlist,
const char *db_name,
struct db *db)
{
struct tevent_req *req, *subreq;
struct db_create_missing_state *state;
struct ctdb_req_control request;
unsigned int i, j;
req = tevent_req_create(mem_ctx,
&state,
struct db_create_missing_state);
if (req == NULL) {
return NULL;
}
state->ev = ev;
state->client = client;
state->nlist = nlist;
state->db_name = db_name;
if (nlist->count == db->num_nodes) {
tevent_req_done(req);
return tevent_req_post(req, ev);
}
state->missing_pnn_list = talloc_array(mem_ctx, uint32_t, nlist->count);
if (tevent_req_nomem(state->missing_pnn_list, req)) {
return tevent_req_post(req, ev);
}
for (i = 0; i < nlist->count; i++) {
uint32_t pnn = nlist->pnn_list[i] ;
for (j = 0; j < db->num_nodes; j++) {
if (pnn == db->pnn_list[j]) {
break;
}
}
if (j < db->num_nodes) {
continue;
}
DBG_INFO("Create database %s on node %u\n",
state->db_name,
pnn);
state->missing_pnn_list[state->missing_num_nodes] = pnn;
state->missing_num_nodes++;
}
if (db->db_flags & CTDB_DB_FLAGS_PERSISTENT) {
ctdb_req_control_db_attach_persistent(&request, db_name);
} else if (db->db_flags & CTDB_DB_FLAGS_REPLICATED) {
ctdb_req_control_db_attach_replicated(&request, db_name);
} else {
ctdb_req_control_db_attach(&request, db_name);
}
request.flags = CTDB_CTRL_FLAG_ATTACH_RECOVERY;
subreq = ctdb_client_control_multi_send(state,
state->ev,
state->client,
state->missing_pnn_list,
state->missing_num_nodes,
TIMEOUT(),
&request);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
tevent_req_set_callback(subreq, db_create_missing_done, req);
return req;
}
static void db_create_missing_done(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(
subreq, struct tevent_req);
struct db_create_missing_state *state = tevent_req_data(
req, struct db_create_missing_state);
int *err_list;
int ret;
bool status;
status = ctdb_client_control_multi_recv(subreq,
&ret,
NULL,
&err_list,
NULL);
TALLOC_FREE(subreq);
if (! status) {
int ret2;
uint32_t pnn;
ret2 = ctdb_client_control_multi_error(
state->missing_pnn_list,
state->missing_num_nodes,
err_list,
&pnn);
if (ret2 != 0) {
D_ERR("control DB_ATTACH failed for db %s"
" on node %u, ret=%d\n",
state->db_name,
pnn,
ret2);
node_list_ban_credits(state->nlist, pnn);
} else {
D_ERR("control DB_ATTACH failed for db %s, ret=%d\n",
state->db_name,
ret);
}
tevent_req_error(req, ret);
return;
}
tevent_req_done(req);
}
static bool db_create_missing_recv(struct tevent_req *req, int *perr)
{
return generic_recv(req, perr);
}
/*
* Recovery database functions
*/
@ -1657,6 +1801,7 @@ static bool collect_all_db_recv(struct tevent_req *req, int *perr)
/**
* For each database do the following:
* - Get DB name from all nodes
* - Attach database on missing nodes
* - Get DB path
* - Freeze database on all nodes
* - Start transaction on all nodes
@ -1682,6 +1827,7 @@ struct recover_db_state {
};
static void recover_db_name_done(struct tevent_req *subreq);
static void recover_db_create_missing_done(struct tevent_req *subreq);
static void recover_db_path_done(struct tevent_req *subreq);
static void recover_db_freeze_done(struct tevent_req *subreq);
static void recover_db_transaction_started(struct tevent_req *subreq);
@ -1741,7 +1887,6 @@ static void recover_db_name_done(struct tevent_req *subreq)
struct recover_db_state *state = tevent_req_data(
req, struct recover_db_state);
struct ctdb_reply_control **reply;
struct ctdb_req_control request;
int *err_list;
unsigned int i;
int ret;
@ -1813,6 +1958,37 @@ static void recover_db_name_done(struct tevent_req *subreq)
talloc_free(reply);
subreq = db_create_missing_send(state,
state->ev,
state->client,
state->nlist,
state->db_name,
state->db);
if (tevent_req_nomem(subreq, req)) {
return;
}
tevent_req_set_callback(subreq, recover_db_create_missing_done, req);
}
static void recover_db_create_missing_done(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(
subreq, struct tevent_req);
struct recover_db_state *state = tevent_req_data(
req, struct recover_db_state);
struct ctdb_req_control request;
int ret;
bool status;
/* Could sanity check the db_id here */
status = db_create_missing_recv(subreq, &ret);
TALLOC_FREE(subreq);
if (! status) {
tevent_req_error(req, ret);
return;
}
ctdb_req_control_getdbpath(&request, state->db->db_id);
subreq = ctdb_client_control_send(state, state->ev, state->client,
state->destnode, TIMEOUT(),