From: Stefan Metzmacher Date: Fri, 17 Nov 2023 14:59:57 +0000 (+0100) Subject: ctdb: add/implement CTDB_CONTROL_TCP_CLIENT_PASSED X-Git-Url: http://git.samba.org/?a=commitdiff_plain;h=118d6c81ec9fd19a98d5f674ccff2a57aed81881;p=metze%2Fsamba-autobuild-v4-19-test%2F.git ctdb: add/implement CTDB_CONTROL_TCP_CLIENT_PASSED With multichannel a tcp connection is registered first with a temporary smbd process, that calls CTDB_CONTROL_TCP_CLIENT first and then passes the tcp connection to the longterm smbd that already handles all connections belonging to the specific client_guid. That smbd process calls CTDB_CONTROL_TCP_CLIENT again, but the 'tickle' information is already there. When the temporary smbd process exists/disconnects from ctdb or calls CTDB_CONTROL_TCP_CLIENT_DISCONNECTED, the 'tickle' information is removed, while the longterm smbd process still serves the tcp connection. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15523 Signed-off-by: Stefan Metzmacher Reviewed-by: Martin Schwenke (cherry picked from commit 037e8e449deb136ad5ed5e4de05439411b545b6d) --- diff --git a/ctdb/include/ctdb_private.h b/ctdb/include/ctdb_private.h index ca350df2cf4..80278123778 100644 --- a/ctdb/include/ctdb_private.h +++ b/ctdb/include/ctdb_private.h @@ -895,6 +895,9 @@ int32_t ctdb_control_tcp_client(struct ctdb_context *ctdb, uint32_t client_id, int32_t ctdb_control_tcp_client_disconnected(struct ctdb_context *ctdb, uint32_t client_id, TDB_DATA indata); +int32_t ctdb_control_tcp_client_passed(struct ctdb_context *ctdb, + uint32_t client_id, + TDB_DATA indata); int32_t ctdb_control_tcp_add(struct ctdb_context *ctdb, TDB_DATA indata, bool tcp_update_needed); int32_t ctdb_control_tcp_remove(struct ctdb_context *ctdb, TDB_DATA indata); diff --git a/ctdb/protocol/protocol.h b/ctdb/protocol/protocol.h index 42b992ae6db..3b66c403ab8 100644 --- a/ctdb/protocol/protocol.h +++ b/ctdb/protocol/protocol.h @@ -382,6 +382,7 @@ enum ctdb_controls {CTDB_CONTROL_PROCESS_EXISTS = 0, CTDB_CONTROL_DISABLE_NODE = 157, CTDB_CONTROL_ENABLE_NODE = 158, CTDB_CONTROL_TCP_CLIENT_DISCONNECTED = 159, + CTDB_CONTROL_TCP_CLIENT_PASSED = 160, }; #define MAX_COUNT_BUCKETS 16 diff --git a/ctdb/protocol/protocol_control.c b/ctdb/protocol/protocol_control.c index 5e2cf13c579..83ed6cb4ee1 100644 --- a/ctdb/protocol/protocol_control.c +++ b/ctdb/protocol/protocol_control.c @@ -414,6 +414,10 @@ static size_t ctdb_req_control_data_len(struct ctdb_req_control_data *cd) case CTDB_CONTROL_TCP_CLIENT_DISCONNECTED: len = ctdb_connection_len(cd->data.conn); break; + + case CTDB_CONTROL_TCP_CLIENT_PASSED: + len = ctdb_connection_len(cd->data.conn); + break; } return len; @@ -1028,6 +1032,14 @@ static int ctdb_req_control_data_pull(uint8_t *buf, size_t buflen, &cd->data.conn, &np); break; + + case CTDB_CONTROL_TCP_CLIENT_PASSED: + ret = ctdb_connection_pull(buf, + buflen, + mem_ctx, + &cd->data.conn, + &np); + break; } if (ret != 0) { @@ -1391,6 +1403,9 @@ static size_t ctdb_reply_control_data_len(struct ctdb_reply_control_data *cd) case CTDB_CONTROL_TCP_CLIENT_DISCONNECTED: break; + + case CTDB_CONTROL_TCP_CLIENT_PASSED: + break; } return len; diff --git a/ctdb/protocol/protocol_debug.c b/ctdb/protocol/protocol_debug.c index 2dc4a702eae..ae091b04d32 100644 --- a/ctdb/protocol/protocol_debug.c +++ b/ctdb/protocol/protocol_debug.c @@ -246,6 +246,7 @@ static void ctdb_opcode_print(uint32_t opcode, FILE *fp) { CTDB_CONTROL_DISABLE_NODE, "DISABLE_NODE" }, { CTDB_CONTROL_ENABLE_NODE, "ENABLE_NODE" }, { CTDB_CONTROL_TCP_CLIENT_DISCONNECTED, "TCP_CLIENT_DISCONNECTED" }, + { CTDB_CONTROL_TCP_CLIENT_PASSED, "TCP_CLIENT_PASSED" }, { MAP_END, "" }, }; diff --git a/ctdb/server/ctdb_control.c b/ctdb/server/ctdb_control.c index 3ea93f52cfe..422c4cf1e58 100644 --- a/ctdb/server/ctdb_control.c +++ b/ctdb/server/ctdb_control.c @@ -872,6 +872,10 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb, CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_connection)); return ctdb_control_tcp_client_disconnected(ctdb, client_id, indata); + case CTDB_CONTROL_TCP_CLIENT_PASSED: + CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_connection)); + return ctdb_control_tcp_client_passed(ctdb, client_id, indata); + 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 da3077e5140..1668e569739 100644 --- a/ctdb/server/ctdb_takeover.c +++ b/ctdb/server/ctdb_takeover.c @@ -1463,6 +1463,55 @@ int32_t ctdb_control_tcp_client_disconnected(struct ctdb_context *ctdb, return 0; } +/* + called by a client to inform us of a TCP connection was passed to a different + "client" (typically with multichannel to another smbd process). + */ +int32_t ctdb_control_tcp_client_passed(struct ctdb_context *ctdb, + uint32_t client_id, + TDB_DATA indata) +{ + struct ctdb_client *client = reqid_find(ctdb->idr, client_id, struct ctdb_client); + struct ctdb_connection *tcp_sock = NULL; + int ret; + char conn_str[132] = { 0, }; + bool found = false; + + tcp_sock = (struct ctdb_connection *)indata.dptr; + + ctdb_canonicalize_ip_inplace(&tcp_sock->src); + ctdb_canonicalize_ip_inplace(&tcp_sock->dst); + + ret = ctdb_connection_to_buf(conn_str, + sizeof(conn_str), + tcp_sock, + false, + " -> "); + if (ret != 0) { + strlcpy(conn_str, "UNKNOWN", sizeof(conn_str)); + } + + found = ctdb_client_remove_tcp(client, tcp_sock); + if (!found) { + DBG_DEBUG("TCP connection from %s not found " + "(client_id %u pid %u).\n", + conn_str, client_id, client->pid); + return 0; + } + + D_INFO("TCP connection from %s " + "(client_id %u pid %u) passed to another client\n", + conn_str, client_id, client->pid); + + /* + * We don't call CTDB_CONTROL_TCP_REMOVE + * nor ctdb_remove_connection() as the connection + * is still alive, but handled by another client + */ + + return 0; +} + /* find a tcp address on a list */