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 <vagnihotri@ddn.com>
Reviewed-by: Martin Schwenke <mschwenke@ddn.com>
Reviewed-by: Volker Lendecke <vl@samba.org>
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);
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;
}
+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;
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,
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);