From: Vinit Agnihotri Date: Thu, 26 Oct 2023 06:55:17 +0000 (-0700) Subject: ctdb-server: Implement CTDB_CONTROL_START_IPREALLOCATE X-Git-Tag: tdb-1.4.11~1515 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b7cc56d22dbd117f4c32a794f3116a61b3c8a7ee;p=thirdparty%2Fsamba.git ctdb-server: Implement CTDB_CONTROL_START_IPREALLOCATE Trigger a "startipreallocate" event, but only if in RUNNING runstate. "startipreallocate" is intended to allow an NFS server to be put into grace on all nodes before any locks are released as part of releaseip during failover. If node A is leader and initiates a takeover run then node B may be connected/active but may not have completed startup. In this case, the attempt to put NFS-Ganesha into grace on node B will fail, startipreallocate will fail, and the node will be banned. Signed-off-by: Vinit Agnihotri Reviewed-by: Martin Schwenke Reviewed-by: Volker Lendecke --- diff --git a/ctdb/include/ctdb_private.h b/ctdb/include/ctdb_private.h index 80278123778..cee95792ead 100644 --- a/ctdb/include/ctdb_private.h +++ b/ctdb/include/ctdb_private.h @@ -887,6 +887,9 @@ int32_t ctdb_control_release_ip(struct ctdb_context *ctdb, int32_t ctdb_control_ipreallocated(struct ctdb_context *ctdb, struct ctdb_req_control_old *c, bool *async_reply); +int32_t ctdb_control_start_ipreallocate(struct ctdb_context *ctdb, + struct ctdb_req_control_old *c, + bool *async_reply); int ctdb_set_public_addresses(struct ctdb_context *ctdb, bool check_addresses); diff --git a/ctdb/server/ctdb_control.c b/ctdb/server/ctdb_control.c index 422c4cf1e58..a51795f340a 100644 --- a/ctdb/server/ctdb_control.c +++ b/ctdb/server/ctdb_control.c @@ -876,6 +876,10 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb, CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_connection)); return ctdb_control_tcp_client_passed(ctdb, client_id, indata); + case CTDB_CONTROL_START_IPREALLOCATE: + CHECK_CONTROL_DATA_SIZE(0); + return ctdb_control_start_ipreallocate(ctdb, c, async_reply); + default: DEBUG(DEBUG_CRIT,(__location__ " Unknown CTDB control opcode %u\n", opcode)); return -1; diff --git a/ctdb/server/ctdb_takeover.c b/ctdb/server/ctdb_takeover.c index b622fafd95f..70d9b85b746 100644 --- a/ctdb/server/ctdb_takeover.c +++ b/ctdb/server/ctdb_takeover.c @@ -2449,6 +2449,72 @@ int32_t ctdb_control_ipreallocated(struct ctdb_context *ctdb, } +struct start_ipreallocate_callback_state { + struct ctdb_req_control_old *c; +}; + +static void ctdb_start_ipreallocate_callback(struct ctdb_context *ctdb, + int status, void *p) +{ + struct start_ipreallocate_callback_state *state = talloc_get_type_abort( + p, struct start_ipreallocate_callback_state); + + if (status != 0) { + D_ERR("\"startipreallocate\" event failed (status %d)\n", + status); + if (status == -ETIMEDOUT) { + ctdb_ban_self(ctdb); + } + } + + ctdb_request_control_reply(ctdb, state->c, NULL, status, NULL); + talloc_free(state); +} + +/* A control to run the startipreallocate event */ +int32_t ctdb_control_start_ipreallocate(struct ctdb_context *ctdb, + struct ctdb_req_control_old *c, + bool *async_reply) +{ + int ret; + struct start_ipreallocate_callback_state *state; + + /* Nodes that are not RUNNING can not host IPs */ + if (ctdb->runstate != CTDB_RUNSTATE_RUNNING) { + DBG_INFO("Skipping \"startipreallocate\" event, not RUNNING\n"); + return 0; + } + + state = talloc(ctdb, struct start_ipreallocate_callback_state); + if (state == NULL) { + DBG_ERR("Memory allocation error\n"); + return -1; + } + + DBG_INFO("Running \"startipreallocate\" event\n"); + + ret = ctdb_event_script_callback(ctdb, + state, + ctdb_start_ipreallocate_callback, + state, + CTDB_EVENT_START_IPREALLOCATE, + "%s", + ""); + + if (ret != 0) { + D_ERR("Failed to run \"startipreallocate\" event \n"); + talloc_free(state); + return -1; + } + + /* tell the control that we will be reply asynchronously */ + state->c = talloc_steal(state, c); + *async_reply = true; + + return 0; +} + + struct ctdb_reloadips_handle { struct ctdb_context *ctdb; struct ctdb_req_control_old *c; diff --git a/ctdb/tests/src/fake_ctdbd.c b/ctdb/tests/src/fake_ctdbd.c index 0d430a37834..a569b0686c3 100644 --- a/ctdb/tests/src/fake_ctdbd.c +++ b/ctdb/tests/src/fake_ctdbd.c @@ -3450,6 +3450,21 @@ done: client_send_control(req, header, &reply); } +static void control_start_ipreallocate(TALLOC_CTX *mem_ctx, + struct tevent_req *req, + struct ctdb_req_header *header, + struct ctdb_req_control *request) +{ + struct ctdb_reply_control reply; + + /* Always succeed */ + reply.rdata.opcode = request->opcode; + reply.status = 0; + reply.errmsg = NULL; + + client_send_control(req, header, &reply); +} + static void control_ipreallocated(TALLOC_CTX *mem_ctx, struct tevent_req *req, struct ctdb_req_header *header, @@ -4364,6 +4379,10 @@ static void client_process_control(struct tevent_req *req, control_enable_node(mem_ctx, req, &header, &request); break; + case CTDB_CONTROL_START_IPREALLOCATE: + control_start_ipreallocate(mem_ctx, req, &header, &request); + break; + default: if (! (request.flags & CTDB_CTRL_FLAG_NOREPLY)) { control_error(mem_ctx, req, &header, &request);