From: Martin Schwenke Date: Wed, 4 Feb 2026 03:53:54 +0000 (+1100) Subject: ctdb-server: Avoid removing connections for released IP X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;p=thirdparty%2Fsamba.git ctdb-server: Avoid removing connections for released IP Commit c6602b686b4e50d93272667ef86d3904181fb1ab causes TCP connections to be cleared whenever an associated client goes away. This shouldn't happen when the associated public IP is being released, since the takeover node will need the connection details to send tickle ACKs. Sorry, I missed this when reviewing that commit. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15994 Signed-off-by: Martin Schwenke Reviewed-by: Stefan Metzmacher Autobuild-User(master): Martin Schwenke Autobuild-Date(master): Wed Apr 29 02:58:12 UTC 2026 on atb-devel-224 --- diff --git a/ctdb/server/ctdb_takeover.c b/ctdb/server/ctdb_takeover.c index cbf8d0a5b10..5ec9ce0c2c4 100644 --- a/ctdb/server/ctdb_takeover.c +++ b/ctdb/server/ctdb_takeover.c @@ -97,6 +97,13 @@ struct ctdb_vnn { This helps to avoid races. */ bool update_in_flight; + /* + * Help avoid removing connections when a RELEASE_IP is in + * progress. In this case the takeover node will need the + * connection information to send tickle ACKs. + */ + bool release_in_flight; + /* If CTDB_CONTROL_DEL_PUBLIC_IP is received for this IP * address then this flag is set. It will be deleted in the * release IP callback. */ @@ -939,6 +946,7 @@ static int ctdb_releaseip_destructor(struct release_ip_callback_state *state) { if (state->vnn != NULL) { state->vnn->update_in_flight = false; + state->vnn->release_in_flight = false; } return 0; } @@ -1040,6 +1048,7 @@ int32_t ctdb_control_release_ip(struct ctdb_context *ctdb, state->vnn = vnn; vnn->update_in_flight = true; + vnn->release_in_flight = true; talloc_set_destructor(state, ctdb_releaseip_destructor); ret = ctdb_event_script_callback(ctdb, @@ -1393,6 +1402,7 @@ int32_t ctdb_control_tcp_client_disconnected(struct ctdb_context *ctdb, int ret; TDB_DATA data; char conn_str[132] = { 0, }; + struct ctdb_vnn *vnn = NULL; bool found = false; tcp_sock = (struct ctdb_connection *)indata.dptr; @@ -1421,6 +1431,22 @@ int32_t ctdb_control_tcp_client_disconnected(struct ctdb_context *ctdb, "(client_id %u pid %u)\n", conn_str, client_id, client->pid); + /* + * If the public IP has been released or is in the process of + * being released, don't remove connection info from all + * nodes. The takeover node will need it send a tickle ACK. + */ + vnn = find_public_ip_vnn(ctdb, &tcp_sock->dst); + if (vnn != NULL) { + if (vnn->pnn != ctdb->pnn) { + /* Moved elsewhere */ + return 0; + } + if (vnn->release_in_flight) { + return 0; + } + } + data.dptr = (uint8_t *)tcp_sock; data.dsize = sizeof(*tcp_sock); @@ -1775,6 +1801,7 @@ void ctdb_release_all_ips(struct ctdb_context *ctdb) continue; } vnn->update_in_flight = true; + vnn->release_in_flight = true; D_INFO("Release of IP %s/%u on interface %s node:-1\n", ctdb_vnn_address_string(vnn), @@ -1804,18 +1831,21 @@ void ctdb_release_all_ips(struct ctdb_context *ctdb) ctdb_vnn_address_string(vnn)); } vnn->update_in_flight = false; + vnn->release_in_flight = false; continue; } if (ret != 0) { DBG_ERR("Error releasing IP %s (but IP is gone!)\n", ctdb_vnn_address_string(vnn)); vnn->update_in_flight = false; + vnn->release_in_flight = false; continue; } vnn = release_ip_post(ctdb, vnn, &vnn->public_address); if (vnn != NULL) { vnn->update_in_flight = false; + vnn->release_in_flight = false; } count++; }