mirror of
https://github.com/samba-team/samba.git
synced 2025-01-03 01:18:10 +03:00
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 <metze@samba.org> Reviewed-by: Martin Schwenke <martin@meltin.net>
This commit is contained in:
parent
c6602b686b
commit
037e8e449d
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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, "" },
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user