From b30dcf9738d7fa87f8da4afa1f024376130b80a9 Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Sun, 4 Jun 2006 07:11:53 +0000 Subject: [PATCH] viced-swap-old-cbcon-diff-20060603 FIXES 32985 swap cbconn when other side changes IPs --- src/viced/host.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/viced/host.c b/src/viced/host.c index 80b64ec008..58222e203c 100644 --- a/src/viced/host.c +++ b/src/viced/host.c @@ -1384,6 +1384,8 @@ h_GetHost_r(struct rx_connection *tcon) * the list of interfaces for the existing host and * delete the host structure we just allocated. */ if (oldHost->host != haddr || oldHost->port != hport) { + struct rx_connection *rxconn; + ViceLog(25, ("CB: new addr %s:%d for old host %s:%d\n", afs_inet_ntoa_r(haddr, hoststr), @@ -1419,6 +1421,30 @@ h_GetHost_r(struct rx_connection *tcon) addInterfaceAddr_r(oldHost, haddr, hport); oldHost->host = haddr; oldHost->port = hport; + rxconn = oldHost->callback_rxcon; + oldHost->callback_rxcon = host->callback_rxcon; + host->callback_rxcon = NULL; + + if (rxconn) { + struct client *client; + /* + * If rx_DestroyConnection calls h_FreeConnection we will + * deadlock on the host_glock_mutex. Work around the problem + * by unhooking the client from the connection before + * destroying the connection. + */ + client = rx_GetSpecific(rxconn, rxcon_client_key); + if (client) { + if (client->tcon != rxconn) + ViceLog(0,("CB: client %x tcon %x didn't match rxconn %x\n", client, client->tcon, rxconn)); + else { + rx_PutConnection(client->tcon); + client->tcon = NULL; + } + } + rx_SetSpecific(rxconn, rxcon_client_key, (void *)0); + rx_DestroyConnection(rxconn); + } } host->hostFlags |= HOSTDELETED; h_Unlock_r(host);