rx: Remove ADAPT_MTU and MISCMTU
[openafs.git] / src / viced / callback.c
index 5555391..53cea3a 100644 (file)
 
 #include <afsconfig.h>
 #include <afs/param.h>
+#include <afs/stds.h>
 
+#include <roken.h>
 
-#include <stdio.h>
-#include <stdlib.h>            /* for malloc() */
-#include <time.h>              /* ANSI standard location for time stuff */
-#include <string.h>
-#ifdef AFS_NT40_ENV
-#include <fcntl.h>
-#include <io.h>
-#else
-#include <sys/time.h>
+#ifdef HAVE_SYS_FILE_H
 #include <sys/file.h>
-#include <unistd.h>
 #endif
-#include <afs/assert.h>
-
-#include <afs/stds.h>
 
 #include <afs/nfs.h>           /* yuck.  This is an abomination. */
 #include <lwp.h>
 #include "host.h"
 #include "callback.h"
 #ifdef AFS_DEMAND_ATTACH_FS
-#include "../tviced/serialize_state.h"
+#include "serialize_state.h"
 #endif /* AFS_DEMAND_ATTACH_FS */
 
 
@@ -190,11 +180,10 @@ static int FDel(struct FileEntry *fe);
 static int AddCallBack1_r(struct host *host, AFSFid * fid, afs_uint32 * thead,
                          int type, int locked);
 static void MultiBreakCallBack_r(struct cbstruct cba[], int ncbas,
-                                struct AFSCBFids *afidp, struct host *xhost);
-static int MultiBreakVolumeCallBack_r(struct host *host, int isheld,
+                                struct AFSCBFids *afidp);
+static int MultiBreakVolumeCallBack_r(struct host *host,
                                      struct VCBParams *parms, int deletefe);
-static int MultiBreakVolumeLaterCallBack(struct host *host, int isheld,
-                                        void *rock);
+static int MultiBreakVolumeLaterCallBack(struct host *host, void *rock);
 static int GetSomeSpace_r(struct host *hostp, int locked);
 static int ClearHostCallbacks_r(struct host *hp, int locked);
 static int DumpCallBackState_r(void);
@@ -354,10 +343,9 @@ CDel(struct CallBack *cb, int deletefe)
     for (safety = 0, cbp = &fe->firstcb; *cbp && *cbp != cbi;
         cbp = &itocb(*cbp)->cnext, safety++) {
        if (safety > cbstuff.nblks + 10) {
-           assert(0);
-           ViceLog(0,
-                   ("CDel: Internal Error -- shutting down: wanted %d from %d, now at %d\n",
-                    cbi, fe->firstcb, *cbp));
+           ViceLogThenPanic(0, ("CDel: Internal Error -- shutting down: "
+                                "wanted %d from %d, now at %d\n",
+                                cbi, fe->firstcb, *cbp));
            DumpCallBackState_r();
            ShutDownAndCore(PANIC);
        }
@@ -422,7 +410,7 @@ FDel(struct FileEntry *fe)
 
     while (*p && *p != fei)
        p = &itofe(*p)->fnext;
-    assert(*p);
+    osi_Assert(*p);
     *p = fe->fnext;
     FreeFE(fe);
     return 0;
@@ -438,8 +426,7 @@ InitCallBack(int nblks)
      * FE[0] and CB[0] are not used--and not allocated */
     FE = ((struct FileEntry *)(calloc(nblks, sizeof(struct FileEntry))));
     if (!FE) {
-       ViceLog(0, ("Failed malloc in InitCallBack\n"));
-       assert(0);
+       ViceLogThenPanic(0, ("Failed malloc in InitCallBack\n"));
     }
     FE--;  /* FE[0] is supposed to point to junk */
     cbstuff.nFEs = nblks;
@@ -447,8 +434,7 @@ InitCallBack(int nblks)
        FreeFE(&FE[cbstuff.nFEs]);      /* This is correct */
     CB = ((struct CallBack *)(calloc(nblks, sizeof(struct CallBack))));
     if (!CB) {
-       ViceLog(0, ("Failed malloc in InitCallBack\n"));
-       assert(0);
+       ViceLogThenPanic(0, ("Failed malloc in InitCallBack\n"));
     }
     CB--;  /* CB[0] is supposed to point to junk */
     cbstuff.nCBs = nblks;
@@ -471,10 +457,8 @@ XCallBackBulk_r(struct host * ahost, struct AFSFid * fids, afs_int32 nfids)
     int j;
     struct rx_connection *cb_conn = NULL;
 
-#ifdef ADAPT_MTU
     rx_SetConnDeadTime(ahost->callback_rxcon, 4);
     rx_SetConnHardDeadTime(ahost->callback_rxcon, AFS_HARDDEADTIME);
-#endif
 
     code = 0;
     j = 0;
@@ -667,8 +651,8 @@ CompareCBA(const void *e1, const void *e2)
 }
 
 /* Take an array full of hosts, all held.  Break callbacks to them, and
- * release the holds once you're done, except don't release xhost.  xhost
- * may be NULL.  Currently only works for a single Fid in afidp array.
+ * release the holds once you're done.
+ * Currently only works for a single Fid in afidp array.
  * If you want to make this work with multiple fids, you need to fix
  * the error handling.  One approach would be to force a reset if a
  * multi-fid call fails, or you could add delayed callbacks for each
@@ -686,14 +670,14 @@ CompareCBA(const void *e1, const void *e2)
  * wherever that is done. */
 static void
 MultiBreakCallBack_r(struct cbstruct cba[], int ncbas,
-                    struct AFSCBFids *afidp, struct host *xhost)
+                    struct AFSCBFids *afidp)
 {
     int i, j;
     struct rx_connection *conns[MAX_CB_HOSTS];
     static struct AFSCBs tc = { 0, 0 };
     int multi_to_cba_map[MAX_CB_HOSTS];
 
-    assert(ncbas <= MAX_CB_HOSTS);
+    osi_Assert(ncbas <= MAX_CB_HOSTS);
 
     /* sort cba list to avoid makecall issues */
     qsort(cba, ncbas, sizeof(struct cbstruct), CompareCBA);
@@ -708,10 +692,8 @@ MultiBreakCallBack_r(struct cbstruct cba[], int ncbas,
        multi_to_cba_map[j] = i;
        conns[j++] = thishost->callback_rxcon;
 
-#ifdef ADAPT_MTU
        rx_SetConnDeadTime(thishost->callback_rxcon, 4);
        rx_SetConnHardDeadTime(thishost->callback_rxcon, AFS_HARDDEADTIME);
-#endif
     }
 
     if (j) {                   /* who knows what multi would do with 0 conns? */
@@ -773,7 +755,7 @@ MultiBreakCallBack_r(struct cbstruct cba[], int ncbas,
     for (i = 0; i < ncbas; i++) {
        struct host *hp;
        hp = cba[i].hp;
-       if (hp && xhost != hp) {
+       if (hp) {
            h_Release_r(hp);
        }
     }
@@ -806,16 +788,21 @@ BreakCallBack(struct host *xhost, AFSFid * fid, int flag)
 {
     struct FileEntry *fe;
     struct CallBack *cb, *nextcb;
-    struct cbstruct cba[MAX_CB_HOSTS];
-    int ncbas;
+    struct cbstruct cbaDef[MAX_CB_HOSTS], *cba = cbaDef;
+    unsigned int ncbas, cbaAlloc = MAX_CB_HOSTS;
     struct AFSCBFids tf;
     int hostindex;
     char hoststr[16];
 
-    ViceLog(7,
-           ("BCB: BreakCallBack(Host %p all but %s:%d, (%u,%u,%u))\n",
-            xhost, afs_inet_ntoa_r(xhost->host, hoststr), ntohs(xhost->port),
-            fid->Volume, fid->Vnode, fid->Unique));
+    if (xhost)
+       ViceLog(7,
+               ("BCB: BreakCallBack(Host %p all but %s:%d, (%u,%u,%u))\n",
+                xhost, afs_inet_ntoa_r(xhost->host, hoststr), ntohs(xhost->port),
+                fid->Volume, fid->Vnode, fid->Unique));
+    else
+       ViceLog(7,
+               ("BCB: BreakCallBack(No Host, (%u,%u,%u))\n",
+               fid->Volume, fid->Vnode, fid->Unique));
 
     H_LOCK;
     cbstuff.BreakCallBacks++;
@@ -823,7 +810,7 @@ BreakCallBack(struct host *xhost, AFSFid * fid, int flag)
     if (!fe) {
        goto done;
     }
-    hostindex = h_htoi(xhost);
+    hostindex = xhost ? h_htoi(xhost) : 0;
     cb = itocb(fe->firstcb);
     if (!cb || ((fe->ncbs == 1) && (cb->hhead == hostindex) && !flag)) {
        /* the most common case is what follows the || */
@@ -832,8 +819,7 @@ BreakCallBack(struct host *xhost, AFSFid * fid, int flag)
     tf.AFSCBFids_len = 1;
     tf.AFSCBFids_val = fid;
 
-    for (; cb;) {
-       for (ncbas = 0; cb && ncbas < MAX_CB_HOSTS; cb = nextcb) {
+       for (ncbas = 0; cb ; cb = nextcb) {
            nextcb = itocb(cb->cnext);
            if ((cb->hhead != hostindex || flag)
                && (cb->status == CB_BULK || cb->status == CB_NORMAL
@@ -850,6 +836,21 @@ BreakCallBack(struct host *xhost, AFSFid * fid, int flag)
                } else {
                    if (!(thishost->hostFlags & HOSTDELETED)) {
                        h_Hold_r(thishost);
+                       if (ncbas == cbaAlloc) {        /* Need more space */
+                           int curLen = cbaAlloc*sizeof(cba[0]);
+                           struct cbstruct *cbaOld = (cba == cbaDef) ? NULL : cba;
+
+                           /* There are logical contraints elsewhere that the number of hosts
+                              (i.e. h_HTSPERBLOCK*h_MAXHOSTTABLES) remains in the realm of a signed "int".
+                              cbaAlloc is defined unsigned int hence doubling below cannot overflow
+                           */
+                           cbaAlloc = cbaAlloc<<1;     /* double */
+                           cba = realloc(cbaOld, cbaAlloc * sizeof(cba[0]));
+
+                           if (cbaOld == NULL) {       /* realloc wouldn't have copied from cbaDef */
+                               memcpy(cba, cbaDef, curLen);
+                           }
+                       }
                        cba[ncbas].hp = thishost;
                        cba[ncbas].thead = cb->thead;
                        ncbas++;
@@ -863,20 +864,16 @@ BreakCallBack(struct host *xhost, AFSFid * fid, int flag)
        }
 
        if (ncbas) {
-           MultiBreakCallBack_r(cba, ncbas, &tf, xhost);
+           struct cbstruct *cba2;
+           int num;
 
-           /* we need to to all these initializations again because MultiBreakCallBack may block */
-           fe = FindFE(fid);
-           if (!fe) {
-               goto done;
-           }
-           cb = itocb(fe->firstcb);
-           if (!cb || ((fe->ncbs == 1) && (cb->hhead == hostindex) && !flag)) {
-               /* the most common case is what follows the || */
-               goto done;
+           for (cba2 = cba, num = ncbas; ncbas > 0; cba2 += num, ncbas -= num) {
+               num = (ncbas > MAX_CB_HOSTS) ? MAX_CB_HOSTS : ncbas;
+               MultiBreakCallBack_r(cba2, num, &tf);
            }
        }
-    }
+
+       if (cba != cbaDef) free(cba);
 
   done:
     H_UNLOCK;
@@ -1112,18 +1109,14 @@ BreakDelayedCallBacks_r(struct host *host)
     return (host->hostFlags & VENUSDOWN);
 }
 
-/*
-** isheld is 0 if the host is held in h_Enumerate
-** isheld is 1 if the host is held in BreakVolumeCallBacks
-*/
 static int
-MultiBreakVolumeCallBack_r(struct host *host, int isheld,
+MultiBreakVolumeCallBack_r(struct host *host,
                           struct VCBParams *parms, int deletefe)
 {
     char hoststr[16];
 
     if (host->hostFlags & HOSTDELETED)
-       return 0;               /* host is deleted, release hold */
+       return 0;
 
     if (!(host->hostFlags & HCBREAK))
        return 0;               /* host is not flagged to notify */
@@ -1144,9 +1137,9 @@ MultiBreakVolumeCallBack_r(struct host *host, int isheld,
                                                 * later */
        host->hostFlags &= ~(RESETDONE|HCBREAK);        /* Do InitCallBackState when host returns */
        h_Unlock_r(host);
-       return 0;               /* parent will release hold */
+       return 0;
     }
-    assert(parms->ncbas <= MAX_CB_HOSTS);
+    osi_Assert(parms->ncbas <= MAX_CB_HOSTS);
 
     /* Do not call MultiBreakCallBack on the current host structure
      ** because it would prematurely release the hold on the host
@@ -1158,27 +1151,28 @@ MultiBreakVolumeCallBack_r(struct host *host, int isheld,
        tf.AFSCBFids_val = parms->fid;
 
        /* this releases all the hosts */
-       MultiBreakCallBack_r(parms->cba, parms->ncbas, &tf, 0 /* xhost */ );
+       MultiBreakCallBack_r(parms->cba, parms->ncbas, &tf);
 
        parms->ncbas = 0;
     }
     parms->cba[parms->ncbas].hp = host;
     parms->cba[(parms->ncbas)++].thead = parms->thead;
     host->hostFlags &= ~HCBREAK;
-    return 1;          /* parent shouldn't release hold, more work to do */
+
+    /* we have more work to do on this host, so make sure we keep a reference
+     * to it */
+    h_Hold_r(host);
+
+    return 0;
 }
 
-/*
-** isheld is 0 if the host is held in h_Enumerate
-** isheld is 1 if the host is held in BreakVolumeCallBacks
-*/
 static int
-MultiBreakVolumeLaterCallBack(struct host *host, int isheld, void *rock)
+MultiBreakVolumeLaterCallBack(struct host *host, void *rock)
 {
     struct VCBParams *parms = (struct VCBParams *)rock;
     int retval;
     H_LOCK;
-    retval = MultiBreakVolumeCallBack_r(host, isheld, parms, 0);
+    retval = MultiBreakVolumeCallBack_r(host, parms, 0);
     H_UNLOCK;
     return retval;
 }
@@ -1194,11 +1188,7 @@ MultiBreakVolumeLaterCallBack(struct host *host, int isheld, void *rock)
  * Now uses multi-RX for CallBack RPC in a different thread,
  * only marking them here.
  */
-#ifdef AFS_PTHREAD_ENV
 extern pthread_cond_t fsync_cond;
-#else
-extern char fsync_wait[];
-#endif
 
 int
 BreakVolumeCallBacksLater(afs_uint32 volume)
@@ -1237,13 +1227,9 @@ BreakVolumeCallBacksLater(afs_uint32 volume)
     }
 
     ViceLog(25, ("Fsync thread wakeup\n"));
-#ifdef AFS_PTHREAD_ENV
     FSYNC_LOCK;
-    assert(pthread_cond_broadcast(&fsync_cond) == 0);
+    CV_BROADCAST(&fsync_cond);
     FSYNC_UNLOCK;
-#else
-    LWP_NoYieldSignal(fsync_wait);
-#endif
     return 0;
 }
 
@@ -1339,7 +1325,7 @@ BreakLaterCallBacks(void)
            tf.AFSCBFids_len = 1;
            tf.AFSCBFids_val = &fid;
 
-           MultiBreakCallBack_r(henumParms.cba, henumParms.ncbas, &tf, 0);
+           MultiBreakCallBack_r(henumParms.cba, henumParms.ncbas, &tf);
            henumParms.ncbas = 0;
        }
     }
@@ -1445,7 +1431,7 @@ struct lih_params {
  * theory not give these to us anyway, but be paranoid.
  */
 static int
-lih0_r(struct host *host, int flags, void *rock)
+lih0_r(struct host *host, void *rock)
 {
     struct lih_params *params = (struct lih_params *)rock;
 
@@ -1463,12 +1449,12 @@ lih0_r(struct host *host, int flags, void *rock)
        h_Hold_r(host);
        params->lih = host;
     }
-    return flags;
+    return 0;
 }
 
 /* same as lih0_r, except we do not prevent held hosts from being selected. */
 static int
-lih1_r(struct host *host, int flags, void *rock)
+lih1_r(struct host *host, void *rock)
 {
     struct lih_params *params = (struct lih_params *)rock;
 
@@ -1484,7 +1470,7 @@ lih1_r(struct host *host, int flags, void *rock)
        h_Hold_r(host);
        params->lih = host;
     }
-    return flags;
+    return 0;
 }
 
 /* This could be upgraded to get more space each time */
@@ -1506,6 +1492,19 @@ GetSomeSpace_r(struct host *hostp, int locked)
     struct lih_params params;
     int i = 0;
 
+    if (cbstuff.GotSomeSpaces == 0) {
+       /* only log this once; if GSS is getting called constantly, that's not
+        * good but don't make things worse by spamming the log. */
+       ViceLog(0, ("We have run out of callback space; forcing callback revocation. "
+                   "This suggests the fileserver is configured with insufficient "
+                   "callbacks; you probably want to increase the -cb fileserver "
+                   "parameter (current setting: %u). The fileserver will continue "
+                   "to operate, but this may indicate a severe performance problem\n",
+                   cbstuff.nblks));
+       ViceLog(0, ("This message is logged at most once; for more information "
+                   "see the OpenAFS documentation and fileserver xstat collection 3\n"));
+    }
+
     cbstuff.GotSomeSpaces++;
     ViceLog(5,
            ("GSS: First looking for timed out call backs via CleanupCallBacks\n"));
@@ -2463,6 +2462,12 @@ cb_stateRestoreCBs(struct fs_dump_state * state, struct FileEntry * fe,
 
     for (idx = 0; idx < niovecs; idx++) {
        cbdsk = (struct CBDiskEntry *) iov[idx].iov_base;
+
+       if (cbdsk->cb.hhead < state->h_map.len &&
+           state->h_map.entries[cbdsk->cb.hhead].valid == FS_STATE_IDX_SKIPPED) {
+           continue;
+       }
+
        if ((cb = GetCB()) == NULL) {
            ViceLog(0, ("cb_stateRestoreCBs: ran out of free CallBack structures\n"));
            ret = 1;
@@ -2529,6 +2534,7 @@ cb_stateDiskEntryToFE(struct fs_dump_state * state,
        ret = 1;
        goto done;
     }
+    state->fe_map.entries[in->index].valid = FS_STATE_IDX_VALID;
     state->fe_map.entries[in->index].old_idx = in->index;
     state->fe_map.entries[in->index].new_idx = fetoi(out);
 
@@ -2559,6 +2565,7 @@ cb_stateDiskEntryToCB(struct fs_dump_state * state,
        ret = 1;
        goto done;
     }
+    state->cb_map.entries[in->index].valid = FS_STATE_IDX_VALID;
     state->cb_map.entries[in->index].old_idx = in->index;
     state->cb_map.entries[in->index].new_idx = cbtoi(out);
 
@@ -2593,7 +2600,8 @@ fe_OldToNew(struct fs_dump_state * state, afs_uint32 old, afs_uint32 * new)
     if (old >= state->fe_map.len) {
        ViceLog(0, ("fe_OldToNew: index %d is out of range\n", old));
        ret = 1;
-    } else if (state->fe_map.entries[old].old_idx != old) { /* sanity check */
+    } else if (state->fe_map.entries[old].valid != FS_STATE_IDX_VALID ||
+               state->fe_map.entries[old].old_idx != old) { /* sanity check */
        ViceLog(0, ("fe_OldToNew: index %d points to an invalid FileEntry record\n", old));
        ret = 1;
     } else {
@@ -2618,7 +2626,8 @@ cb_OldToNew(struct fs_dump_state * state, afs_uint32 old, afs_uint32 * new)
     if (old >= state->cb_map.len) {
        ViceLog(0, ("cb_OldToNew: index %d is out of range\n", old));
        ret = 1;
-    } else if (state->cb_map.entries[old].old_idx != old) { /* sanity check */
+    } else if (state->cb_map.entries[old].valid != FS_STATE_IDX_VALID ||
+               state->cb_map.entries[old].old_idx != old) { /* sanity check */
        ViceLog(0, ("cb_OldToNew: index %d points to an invalid CallBack record\n", old));
        ret = 1;
     } else {
@@ -2688,9 +2697,7 @@ ReadDump(char *file, int timebits)
     int fd, oflag;
     afs_uint32 magic, freelisthead;
     afs_uint32 now;
-#ifdef AFS_64BIT_ENV
     afs_int64 now64;
-#endif
 
     oflag = O_RDONLY;
 #ifdef AFS_NT40_ENV
@@ -2714,13 +2721,12 @@ ReadDump(char *file, int timebits)
            exit(1);
        }
     }
-#ifdef AFS_64BIT_ENV
     if (timebits == 64) {
        read(fd, &now64, sizeof(afs_int64));
        now = (afs_int32) now64;
     } else
-#endif
        read(fd, &now, sizeof(afs_int32));
+
     read(fd, &cbstuff, sizeof(cbstuff));
     read(fd, TimeOuts, sizeof(TimeOuts));
     read(fd, timeout, sizeof(timeout));
@@ -2800,9 +2806,7 @@ main(int argc, char **argv)
            argc--;
            timebits = atoi(*++argv);
            if ((timebits != 32)
-#ifdef AFS_64BIT_ENV
                && (timebits != 64)
-#endif
                )
                err++;
        } else if (!strcmp(*argv, "-volume")) {
@@ -2819,9 +2823,7 @@ main(int argc, char **argv)
     if (err || argc != 1) {
        fprintf(stderr,
                "Usage: cbd [-host cbid] [-fid volume vnode] [-stats] [-all] [-timebits 32"
-#ifdef AFS_64BIT_ENV
                "|64"
-#endif
                "] callbackdumpfile\n");
        fprintf(stderr,
                "[cbid is shown for each host in the hosts.dump file]\n");
@@ -2965,9 +2967,8 @@ MultiBreakCallBackAlternateAddress_r(struct host *host,
     interfaces = calloc(i, sizeof(struct AddrPort));
     conns = calloc(i, sizeof(struct rx_connection *));
     if (!interfaces || !conns) {
-       ViceLog(0,
-               ("Failed malloc in MultiBreakCallBackAlternateAddress_r\n"));
-       assert(0);
+       ViceLogThenPanic(0, ("Failed malloc in "
+                            "MultiBreakCallBackAlternateAddress_r\n"));
     }
 
     /* initialize alternate rx connections */
@@ -2986,7 +2987,7 @@ MultiBreakCallBackAlternateAddress_r(struct host *host,
        j++;
     }
 
-    assert(j);                 /* at least one alternate address */
+    osi_Assert(j);                     /* at least one alternate address */
     ViceLog(125,
            ("Starting multibreakcall back on all addr for host %p (%s:%d)\n",
              host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port)));
@@ -2999,10 +3000,12 @@ MultiBreakCallBackAlternateAddress_r(struct host *host,
            if (host->callback_rxcon)
                rx_DestroyConnection(host->callback_rxcon);
            host->callback_rxcon = conns[multi_i];
-            h_DeleteHostFromAddrHashTable_r(host->host, host->port, host);
+           /* add then remove */
+           addInterfaceAddr_r(host, interfaces[multi_i].addr,
+                                    interfaces[multi_i].port);
+           removeInterfaceAddr_r(host, host->host, host->port);
            host->host = interfaces[multi_i].addr;
            host->port = interfaces[multi_i].port;
-            h_AddHostToAddrHashTable_r(host->host, host->port, host);
            connSuccess = conns[multi_i];
            rx_SetConnDeadTime(host->callback_rxcon, 50);
            rx_SetConnHardDeadTime(host->callback_rxcon, AFS_HARDDEADTIME);
@@ -3061,8 +3064,8 @@ MultiProbeAlternateAddress_r(struct host *host)
     interfaces = calloc(i, sizeof(struct AddrPort));
     conns = calloc(i, sizeof(struct rx_connection *));
     if (!interfaces || !conns) {
-       ViceLog(0, ("Failed malloc in MultiProbeAlternateAddress_r\n"));
-       assert(0);
+       ViceLogThenPanic(0, ("Failed malloc in "
+                            "MultiProbeAlternateAddress_r\n"));
     }
 
     /* initialize alternate rx connections */
@@ -3081,7 +3084,7 @@ MultiProbeAlternateAddress_r(struct host *host)
        j++;
     }
 
-    assert(j);                 /* at least one alternate address */
+    osi_Assert(j);                     /* at least one alternate address */
     ViceLog(125,
            ("Starting multiprobe on all addr for host %p (%s:%d)\n",
              host, afs_inet_ntoa_r(host->host, hoststr),
@@ -3095,10 +3098,12 @@ MultiProbeAlternateAddress_r(struct host *host)
            if (host->callback_rxcon)
                rx_DestroyConnection(host->callback_rxcon);
            host->callback_rxcon = conns[multi_i];
-            h_DeleteHostFromAddrHashTable_r(host->host, host->port, host);
+           /* add then remove */
+           addInterfaceAddr_r(host, interfaces[multi_i].addr,
+                                    interfaces[multi_i].port);
+           removeInterfaceAddr_r(host, host->host, host->port);
            host->host = interfaces[multi_i].addr;
            host->port = interfaces[multi_i].port;
-            h_AddHostToAddrHashTable_r(host->host, host->port, host);
            connSuccess = conns[multi_i];
            rx_SetConnDeadTime(host->callback_rxcon, 50);
            rx_SetConnHardDeadTime(host->callback_rxcon, AFS_HARDDEADTIME);