OPENAFS-SA-2018-002 afs: prevent RXAFSCB_GetLock information leak
[openafs.git] / src / afs / afs_callback.c
index 215a694..2bad7c9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright 2000, International Business Machines Corporation and others.
  * All Rights Reserved.
- * 
+ *
  * This software has been released under the terms of the IBM Public
  * License.  For details, see the LICENSE file in the top-level source
  * directory or online at http://www.openafs.org/dl/license10.html
  *     the callback RPC interface.
  */
 
-#include "../afs/param.h"       /*Should be always first*/
-#include "../afs/sysincludes.h" /*Standard vendor system headers*/
-#include "../afs/afsincludes.h" /*AFS-based standard headers*/
-#include "../afs/afs_stats.h"  /*Cache Manager stats*/
-#include "../afs/afs_args.h"
-
-extern struct volume *afs_volumes[NVOLS];   /* volume hash table */
-extern void afs_DequeueCallback();
-extern void afs_ComputePAGStats();
-afs_int32 afs_allCBs   = 0;            /*Break callbacks on all objects */
-afs_int32 afs_oddCBs   = 0;            /*Break callbacks on dirs*/
-afs_int32 afs_evenCBs = 0;             /*Break callbacks received on files*/
-afs_int32 afs_allZaps = 0;             /*Objects entries deleted */
-afs_int32 afs_oddZaps = 0;             /*Dir cache entries deleted*/
-afs_int32 afs_evenZaps = 0;            /*File cache entries deleted*/
+#include <afsconfig.h>
+#include "afs/param.h"
+
+
+#include "afs/sysincludes.h"   /*Standard vendor system headers */
+#include "afsincludes.h"       /*AFS-based standard headers */
+#include "afs/afs_stats.h"     /*Cache Manager stats */
+#include "afs/afs_args.h"
+
+afs_int32 afs_allCBs = 0;      /*Break callbacks on all objects */
+afs_int32 afs_oddCBs = 0;      /*Break callbacks on dirs */
+afs_int32 afs_evenCBs = 0;     /*Break callbacks received on files */
+afs_int32 afs_allZaps = 0;     /*Objects entries deleted */
+afs_int32 afs_oddZaps = 0;     /*Dir cache entries deleted */
+afs_int32 afs_evenZaps = 0;    /*File cache entries deleted */
 afs_int32 afs_connectBacks = 0;
-extern struct rx_service *afs_server;
-
-extern afs_lock_t afs_xvcb, afs_xbrs, afs_xdcache;
-extern afs_rwlock_t afs_xvcache, afs_xserver,  afs_xcell,  afs_xuser;
-extern afs_rwlock_t afs_xvolume, afs_puttofileLock, afs_ftf, afs_xinterface;
-extern afs_rwlock_t afs_xconn;
-extern struct afs_lock afs_xaxs;
-extern afs_lock_t afs_xcbhash;
-extern struct srvAddr *afs_srvAddrs[NSERVERS];
-extern struct afs_q CellLRU;
-extern struct cm_initparams cm_initParams;
 
 /*
  * Some debugging aids.
@@ -47,25 +36,41 @@ extern struct cm_initparams cm_initParams;
 static struct ltable {
     char *name;
     char *addr;
-} ltable []= {
-    "afs_xvcache", (char *)&afs_xvcache,
-    "afs_xdcache", (char *)&afs_xdcache,
-    "afs_xserver", (char *)&afs_xserver,
-    "afs_xvcb",    (char *)&afs_xvcb,
-    "afs_xbrs",    (char *)&afs_xbrs,
-    "afs_xcell",   (char *)&afs_xcell,
-    "afs_xconn",   (char *)&afs_xconn,
-    "afs_xuser",   (char *)&afs_xuser,
-    "afs_xvolume", (char *)&afs_xvolume,
-    "puttofile",   (char *)&afs_puttofileLock,
-    "afs_ftf",     (char *)&afs_ftf,
-    "afs_xcbhash", (char *)&afs_xcbhash,
-    "afs_xaxs",    (char *)&afs_xaxs,
-    "afs_xinterface", (char *)&afs_xinterface,
+} ltable[] = {
+    {
+    "afs_xvcache", (char *)&afs_xvcache}, {
+    "afs_xdcache", (char *)&afs_xdcache}, {
+    "afs_xserver", (char *)&afs_xserver}, {
+    "afs_xvcb", (char *)&afs_xvcb}, {
+    "afs_xbrs", (char *)&afs_xbrs}, {
+    "afs_xcell", (char *)&afs_xcell}, {
+    "afs_xconn", (char *)&afs_xconn}, {
+    "afs_xuser", (char *)&afs_xuser}, {
+    "afs_xvolume", (char *)&afs_xvolume}, {
+    "puttofile", (char *)&afs_puttofileLock}, {
+    "afs_ftf", (char *)&afs_ftf}, {
+    "afs_xcbhash", (char *)&afs_xcbhash}, {
+    "afs_xaxs", (char *)&afs_xaxs}, {
+    "afs_xinterface", (char *)&afs_xinterface},
+#ifndef UKERNEL
+    {
+    "afs_xosi", (char *)&afs_xosi},
+#endif
+    {
+      "afs_xsrvAddr", (char *)&afs_xsrvAddr},
+    {
+      "afs_xvreclaim", (char *)&afs_xvreclaim},
+    { "afsdb_client_lock", (char *)&afsdb_client_lock},
+    { "afsdb_req_lock", (char *)&afsdb_req_lock},
+    { "afs_discon_lock", (char *)&afs_discon_lock},
+    { "afs_disconDirtyLock", (char *)&afs_disconDirtyLock},
+    { "afs_discon_vc_dirty", (char *)&afs_xvcdirty},
+    { "afs_dynrootDirLock", (char *)&afs_dynrootDirLock},
+    { "afs_dynSymlinkLock", (char *)&afs_dynSymlinkLock},
 };
-unsigned long  lastCallBack_vnode;
-unsigned int   lastCallBack_dv;
-osi_timeval_t  lastCallBack_time;
+unsigned long lastCallBack_vnode;
+unsigned int lastCallBack_dv;
+osi_timeval_t lastCallBack_time;
 
 /* these are for storing alternate interface addresses */
 struct interfaceAddr afs_cb_interface;
@@ -93,21 +98,17 @@ struct interfaceAddr afs_cb_interface;
  *     As advertised.
  *------------------------------------------------------------------------*/
 
-int SRXAFSCB_GetCE(a_call, a_index, a_result)
-    struct rx_call *a_call;
-    afs_int32 a_index;
-    struct AFSDBCacheEntry *a_result;
-
-{ /*SRXAFSCB_GetCE*/
+int
+SRXAFSCB_GetCE(struct rx_call *a_call, afs_int32 a_index,
+              struct AFSDBCacheEntry *a_result)
+{
 
-    register int i;                    /*Loop variable*/
-    register struct vcache *tvc;       /*Ptr to current cache entry*/
-    int code;                          /*Return code*/
+    int i;             /*Loop variable */
+    struct vcache *tvc;        /*Ptr to current cache entry */
+    int code;                  /*Return code */
     XSTATS_DECLS;
 
-#ifdef RX_ENABLE_LOCKS
-    AFS_GLOCK();
-#endif /* RX_ENABLE_LOCKS */
+    RX_AFS_GLOCK();
 
     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETCE);
 
@@ -117,12 +118,12 @@ int SRXAFSCB_GetCE(a_call, a_index, a_result)
            if (a_index == 0)
                goto searchDone;
            a_index--;
-       } /*Zip through current hash chain*/
-    } /*Zip through hash chains*/
+       }                       /*Zip through current hash chain */
+    }                          /*Zip through hash chains */
 
   searchDone:
-    if (tvc == (struct vcache *) 0) {
-       /*Past EOF*/
+    if (tvc == NULL) {
+       /*Past EOF */
        code = 1;
        goto fcnDone;
     }
@@ -131,48 +132,140 @@ int SRXAFSCB_GetCE(a_call, a_index, a_result)
      * Copy out the located entry.
      */
     a_result->addr = afs_data_pointer_to_int32(tvc);
-    a_result->cell = tvc->fid.Cell;
-    a_result->netFid.Volume = tvc->fid.Fid.Volume;
-    a_result->netFid.Vnode = tvc->fid.Fid.Vnode;
-    a_result->netFid.Unique = tvc->fid.Fid.Unique;
+    a_result->cell = tvc->f.fid.Cell;
+    a_result->netFid.Volume = tvc->f.fid.Fid.Volume;
+    a_result->netFid.Vnode = tvc->f.fid.Fid.Vnode;
+    a_result->netFid.Unique = tvc->f.fid.Fid.Unique;
     a_result->lock.waitStates = tvc->lock.wait_states;
     a_result->lock.exclLocked = tvc->lock.excl_locked;
     a_result->lock.readersReading = tvc->lock.readers_reading;
     a_result->lock.numWaiting = tvc->lock.num_waiting;
 #if defined(INSTRUMENT_LOCKS)
-    a_result->lock.pid_last_reader = tvc->lock.pid_last_reader;
-    a_result->lock.pid_writer = tvc->lock.pid_writer;
+    a_result->lock.pid_last_reader = MyPidxx2Pid(tvc->lock.pid_last_reader);
+    a_result->lock.pid_writer = MyPidxx2Pid(tvc->lock.pid_writer);
     a_result->lock.src_indicator = tvc->lock.src_indicator;
 #else
     /* On osf20 , the vcache does not maintain these three fields */
     a_result->lock.pid_last_reader = 0;
     a_result->lock.pid_writer = 0;
     a_result->lock.src_indicator = 0;
-#endif /* AFS_OSF20_ENV */
-    a_result->Length = tvc->m.Length;
-    a_result->DataVersion = hgetlo(tvc->m.DataVersion);
-    a_result->callback = afs_data_pointer_to_int32(tvc->callback);             /* XXXX Now a pointer; change it XXXX */
+#endif /* INSTRUMENT_LOCKS */
+#ifdef AFS_64BIT_CLIENT
+    a_result->Length = (afs_int32) tvc->f.m.Length & 0xffffffff;
+#else /* AFS_64BIT_CLIENT */
+    a_result->Length = tvc->f.m.Length;
+#endif /* AFS_64BIT_CLIENT */
+    a_result->DataVersion = hgetlo(tvc->f.m.DataVersion);
+    a_result->callback = afs_data_pointer_to_int32(tvc->callback);     /* XXXX Now a pointer; change it XXXX */
     a_result->cbExpires = tvc->cbExpires;
-    a_result->refCount = tvc->vrefCount;
+    if (tvc->f.states & CVInit) {
+        a_result->refCount = 1;
+    } else {
+#ifdef AFS_DARWIN80_ENV
+    a_result->refCount = vnode_isinuse(AFSTOV(tvc),0)?1:0; /* XXX fix */
+#else
+    a_result->refCount = VREFCOUNT(tvc);
+#endif
+    }
     a_result->opens = tvc->opens;
     a_result->writers = tvc->execsOrWriters;
     a_result->mvstat = tvc->mvstat;
-    a_result->states = tvc->states;
+    a_result->states = tvc->f.states;
     code = 0;
 
     /*
      * Return our results.
      */
-fcnDone:
+  fcnDone:
     XSTATS_END_TIME;
 
-#ifdef RX_ENABLE_LOCKS
-    AFS_GUNLOCK();
-#endif /* RX_ENABLE_LOCKS */
+    RX_AFS_GUNLOCK();
 
-    return(code);
+    return (code);
+
+}                              /*SRXAFSCB_GetCE */
+
+int
+SRXAFSCB_GetCE64(struct rx_call *a_call, afs_int32 a_index,
+                struct AFSDBCacheEntry64 *a_result)
+{
+    int i;             /*Loop variable */
+    struct vcache *tvc;        /*Ptr to current cache entry */
+    int code;                  /*Return code */
+    XSTATS_DECLS;
+
+    RX_AFS_GLOCK();
+
+    XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETCE);
+
+    AFS_STATCNT(SRXAFSCB_GetCE64);
+    for (i = 0; i < VCSIZE; i++) {
+       for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
+           if (a_index == 0)
+               goto searchDone;
+           a_index--;
+       }                       /*Zip through current hash chain */
+    }                          /*Zip through hash chains */
+
+  searchDone:
+    if (tvc == NULL) {
+       /*Past EOF */
+       code = 1;
+       goto fcnDone;
+    }
+
+    /*
+     * Copy out the located entry.
+     */
+    a_result->addr = afs_data_pointer_to_int32(tvc);
+    a_result->cell = tvc->f.fid.Cell;
+    a_result->netFid.Volume = tvc->f.fid.Fid.Volume;
+    a_result->netFid.Vnode = tvc->f.fid.Fid.Vnode;
+    a_result->netFid.Unique = tvc->f.fid.Fid.Unique;
+    a_result->lock.waitStates = tvc->lock.wait_states;
+    a_result->lock.exclLocked = tvc->lock.excl_locked;
+    a_result->lock.readersReading = tvc->lock.readers_reading;
+    a_result->lock.numWaiting = tvc->lock.num_waiting;
+#if defined(INSTRUMENT_LOCKS)
+    a_result->lock.pid_last_reader = MyPidxx2Pid(tvc->lock.pid_last_reader);
+    a_result->lock.pid_writer = MyPidxx2Pid(tvc->lock.pid_writer);
+    a_result->lock.src_indicator = tvc->lock.src_indicator;
+#else
+    /* On osf20 , the vcache does not maintain these three fields */
+    a_result->lock.pid_last_reader = 0;
+    a_result->lock.pid_writer = 0;
+    a_result->lock.src_indicator = 0;
+#endif /* INSTRUMENT_LOCKS */
+    a_result->Length = tvc->f.m.Length;
+    a_result->DataVersion = hgetlo(tvc->f.m.DataVersion);
+    a_result->callback = afs_data_pointer_to_int32(tvc->callback);     /* XXXX Now a pointer; change it XXXX */
+    a_result->cbExpires = tvc->cbExpires;
+    if (tvc->f.states & CVInit) {
+        a_result->refCount = 1;
+    } else {
+#ifdef AFS_DARWIN80_ENV
+    a_result->refCount = vnode_isinuse(AFSTOV(tvc),0)?1:0; /* XXX fix */
+#else
+    a_result->refCount = VREFCOUNT(tvc);
+#endif
+    }
+    a_result->opens = tvc->opens;
+    a_result->writers = tvc->execsOrWriters;
+    a_result->mvstat = tvc->mvstat;
+    a_result->states = tvc->f.states;
+    code = 0;
+
+    /*
+     * Return our results.
+     */
+  fcnDone:
+    XSTATS_END_TIME;
+
+    RX_AFS_GUNLOCK();
+
+    return (code);
 
-} /*SRXAFSCB_GetCE*/
+}                              /*SRXAFSCB_GetCE64 */
 
 
 /*------------------------------------------------------------------------
@@ -199,57 +292,87 @@ fcnDone:
  *     As advertised.
  *------------------------------------------------------------------------*/
 
-int SRXAFSCB_GetLock (a_call, a_index, a_result)
-    struct rx_call *a_call;
-    afs_int32 a_index;
-    struct AFSDBLock *a_result;
-
-{ /*SRXAFSCB_GetLock*/
-
-    struct ltable *tl;         /*Ptr to lock table entry*/
-    int nentries;              /*Num entries in table*/
-    int code;                  /*Return code*/
+int
+SRXAFSCB_GetLock(struct rx_call *a_call, afs_int32 a_index,
+                struct AFSDBLock *a_result)
+{
+    struct ltable *tl;         /*Ptr to lock table entry */
+    int nentries;              /*Num entries in table */
+    int code;                  /*Return code */
     XSTATS_DECLS;
 
-#ifdef RX_ENABLE_LOCKS
-    AFS_GLOCK();
-#endif /* RX_ENABLE_LOCKS */
+    RX_AFS_GLOCK();
 
     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETLOCK);
-    
+
     AFS_STATCNT(SRXAFSCB_GetLock);
-    nentries = sizeof(ltable)/sizeof(struct ltable);
-    if (a_index < 0 || a_index >= nentries) {
+    memset(a_result, 0, sizeof(*a_result));
+    nentries = sizeof(ltable) / sizeof(struct ltable);
+    if (a_index < 0 || a_index >= nentries+afs_cellindex) {
        /*
-         * Past EOF
-         */
+        * Past EOF
+        */
        code = 1;
-    }
-    else {
+    } else if (a_index >= nentries) {
+       struct cell *tc = afs_GetCellByIndex(a_index-nentries, 0);
+       strcpy(a_result->name, tc->cellName);
+       a_result->lock.waitStates =
+           ((struct afs_lock *)&(tc->lock))->wait_states;
+       a_result->lock.exclLocked =
+           ((struct afs_lock *)&(tc->lock))->excl_locked;
+       a_result->lock.readersReading =
+           ((struct afs_lock *)&(tc->lock))->readers_reading;
+       a_result->lock.numWaiting =
+           ((struct afs_lock *)&(tc->lock))->num_waiting;
+#ifdef INSTRUMENT_LOCKS
+       a_result->lock.pid_last_reader =
+           MyPidxx2Pid(((struct afs_lock *)&(tc->lock))->pid_last_reader);
+       a_result->lock.pid_writer =
+           MyPidxx2Pid(((struct afs_lock *)&(tc->lock))->pid_writer);
+       a_result->lock.src_indicator =
+           ((struct afs_lock *)&(tc->lock))->src_indicator;
+#else
+       a_result->lock.pid_last_reader = 0;
+       a_result->lock.pid_writer = 0;
+       a_result->lock.src_indicator = 0;
+#endif
+       code = 0;
+    } else {
        /*
         * Found it - copy out its contents.
         */
        tl = &ltable[a_index];
        strcpy(a_result->name, tl->name);
-       a_result->lock.waitStates = ((struct afs_lock *)(tl->addr))->wait_states;
-       a_result->lock.exclLocked = ((struct afs_lock *)(tl->addr))->excl_locked;
-       a_result->lock.readersReading = ((struct afs_lock *)(tl->addr))->readers_reading;
-       a_result->lock.numWaiting = ((struct afs_lock *)(tl->addr))->num_waiting;
-       a_result->lock.pid_last_reader = ((struct afs_lock *)(tl->addr))->pid_last_reader;
-       a_result->lock.pid_writer = ((struct afs_lock *)(tl->addr))->pid_writer;
-       a_result->lock.src_indicator = ((struct afs_lock *)(tl->addr))->src_indicator;
+       a_result->lock.waitStates =
+           ((struct afs_lock *)(tl->addr))->wait_states;
+       a_result->lock.exclLocked =
+           ((struct afs_lock *)(tl->addr))->excl_locked;
+       a_result->lock.readersReading =
+           ((struct afs_lock *)(tl->addr))->readers_reading;
+       a_result->lock.numWaiting =
+           ((struct afs_lock *)(tl->addr))->num_waiting;
+#ifdef INSTRUMENT_LOCKS
+       a_result->lock.pid_last_reader =
+           MyPidxx2Pid(((struct afs_lock *)(tl->addr))->pid_last_reader);
+       a_result->lock.pid_writer =
+           MyPidxx2Pid(((struct afs_lock *)(tl->addr))->pid_writer);
+       a_result->lock.src_indicator =
+           ((struct afs_lock *)(tl->addr))->src_indicator;
+#else
+       a_result->lock.pid_last_reader = 0;
+       a_result->lock.pid_writer = 0;
+       a_result->lock.src_indicator = 0;
+#endif
        code = 0;
     }
 
     XSTATS_END_TIME;
 
-#ifdef RX_ENABLE_LOCKS
-    AFS_GUNLOCK();
-#endif /* RX_ENABLE_LOCKS */
+    RX_AFS_GUNLOCK();
 
-    return(code);
+    return (code);
 
-}  /*SRXAFSCB_GetLock*/
+}                              /*SRXAFSCB_GetLock */
 
 
 /*------------------------------------------------------------------------
@@ -257,7 +380,7 @@ int SRXAFSCB_GetLock (a_call, a_index, a_result)
  *
  * Description:
  *     Clear out callback information for the specified file, or
- *     even a whole volume.  Used to worry about callback was from 
+ *     even a whole volume.  Used to worry about callback was from
  *      within the particular cell or not.  Now we don't bother with
  *      that anymore; it's not worth the time.
  *
@@ -273,21 +396,27 @@ int SRXAFSCB_GetLock (a_call, a_index, a_result)
  *
  * Side Effects:
  *     As advertised.
- *------------------------------------------------------------------------*/
 
-static ClearCallBack(a_conn, a_fid)
-    register struct rx_connection *a_conn;
-    register struct AFSFid *a_fid;
+Appears to need to be called with GLOCK held, as the icl_Event4 stuff asserts otherwise
 
-{ /*ClearCallBack*/
+ *------------------------------------------------------------------------*/
 
-    register struct vcache *tvc;
-    register int i;
+static int
+ClearCallBack(struct rx_connection *a_conn,
+             struct AFSFid *a_fid)
+{
+    struct vcache *tvc;
+    int i;
     struct VenusFid localFid;
-    struct volume * tv;
+    struct volume *tv;
+#ifdef AFS_DARWIN80_ENV
+    vnode_t vp;
+#endif
 
     AFS_STATCNT(ClearCallBack);
 
+    AFS_ASSERT_GLOCK();
+
     /*
      * XXXX Don't hold any server locks here because of callback protocol XXX
      */
@@ -297,96 +426,165 @@ static ClearCallBack(a_conn, a_fid)
     localFid.Fid.Unique = a_fid->Unique;
 
     /*
-      * Volume ID of zero means don't do anything.
-      */
+     * Volume ID of zero means don't do anything.
+     */
     if (a_fid->Volume != 0) {
        if (a_fid->Vnode == 0) {
+               struct afs_q *tq, *uq;
            /*
             * Clear callback for the whole volume.  Zip through the
             * hash chain, nullifying entries whose volume ID matches.
             */
-           for (i = 0; i < VCSIZE; i++)
-               for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
-                   if (tvc->fid.Fid.Volume == a_fid->Volume) {
-                       tvc->callback = (struct server *)0;
-                       tvc->quick.stamp = 0; 
+loop1:
+               ObtainReadLock(&afs_xvcache);
+               i = VCHashV(&localFid);
+               for (tq = afs_vhashTV[i].prev; tq != &afs_vhashTV[i]; tq = uq) {
+                   uq = QPrev(tq);
+                   tvc = QTOVH(tq);
+                   if (tvc->f.fid.Fid.Volume == a_fid->Volume) {
+                       tvc->callback = NULL;
                        if (!localFid.Cell)
-                           localFid.Cell = tvc->fid.Cell;
-                       tvc->h1.dchint = NULL; /* invalidate hints */
-                       ObtainWriteLock(&afs_xcbhash, 449);
-                       afs_DequeueCallback(tvc);
-                       tvc->states &= ~(CStatd | CUnique | CBulkFetching);
+                           localFid.Cell = tvc->f.fid.Cell;
+                       tvc->dchint = NULL;     /* invalidate hints */
+                       if (tvc->f.states & CVInit) {
+                           ReleaseReadLock(&afs_xvcache);
+                           afs_osi_Sleep(&tvc->f.states);
+                           goto loop1;
+                       }
+#if     defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)  || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
+                       AFS_FAST_HOLD(tvc);
+#else
+#ifdef AFS_DARWIN80_ENV
+                       if (tvc->f.states & CDeadVnode) {
+                           ReleaseReadLock(&afs_xvcache);
+                           afs_osi_Sleep(&tvc->f.states);
+                           goto loop1;
+                       }
+                       vp = AFSTOV(tvc);
+                       if (vnode_get(vp))
+                           continue;
+                       if (vnode_ref(vp)) {
+                           AFS_GUNLOCK();
+                           vnode_put(vp);
+                           AFS_GLOCK();
+                           continue;
+                       }
+#else
+                       AFS_FAST_HOLD(tvc);
+#endif
+#endif
+                       ReleaseReadLock(&afs_xvcache);
+                       afs_StaleVCacheFlags(tvc, 0, CUnique | CBulkFetching);
                        afs_allCBs++;
-                       if (tvc->fid.Fid.Vnode & 1)
-                         afs_oddCBs++; 
+                       if (tvc->f.fid.Fid.Vnode & 1)
+                           afs_oddCBs++;
                        else
-                         afs_evenCBs++; 
-                       ReleaseWriteLock(&afs_xcbhash);
-                       if (tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
-                           osi_dnlc_purgedp(tvc);
+                           afs_evenCBs++;
                        afs_Trace3(afs_iclSetp, CM_TRACE_CALLBACK,
-                                  ICL_TYPE_POINTER, tvc, 
-                                  ICL_TYPE_INT32, tvc->states,
-                                  ICL_TYPE_INT32, a_fid->Volume);
-                   } else if ((tvc->states & CMValid) && (tvc->mvid->Fid.Volume == a_fid->Volume)) {
-                       tvc->states &= ~CMValid;
+                                  ICL_TYPE_POINTER, tvc, ICL_TYPE_INT32,
+                                  tvc->f.states, ICL_TYPE_INT32,
+                                  a_fid->Volume);
+#ifdef AFS_DARWIN80_ENV
+                       vnode_put(AFSTOV(tvc));
+#endif
+                       ObtainReadLock(&afs_xvcache);
+                       uq = QPrev(tq);
+                       AFS_FAST_RELE(tvc);
+                   } else if ((tvc->f.states & CMValid)
+                              && (tvc->mvid.target_root->Fid.Volume == a_fid->Volume)) {
+                       tvc->f.states &= ~CMValid;
                        if (!localFid.Cell)
-                           localFid.Cell = tvc->mvid->Cell;
+                           localFid.Cell = tvc->mvid.target_root->Cell;
                    }
                }
+               ReleaseReadLock(&afs_xvcache);
 
            /*
             * XXXX Don't hold any locks here XXXX
             */
            tv = afs_FindVolume(&localFid, 0);
            if (tv) {
-             afs_ResetVolumeInfo(tv);
-             afs_PutVolume(tv, 0);
-             /* invalidate mtpoint? */
+               afs_ResetVolumeInfo(tv);
+               afs_PutVolume(tv, 0);
+               /* invalidate mtpoint? */
            }
-       } /*Clear callbacks for whole volume*/
+       } /*Clear callbacks for whole volume */
        else {
            /*
             * Clear callbacks just for the one file.
             */
+           struct vcache *uvc;
            afs_allCBs++;
            if (a_fid->Vnode & 1)
-               afs_oddCBs++;   /*Could do this on volume basis, too*/
+               afs_oddCBs++;   /*Could do this on volume basis, too */
            else
-               afs_evenCBs++; /*A particular fid was specified*/
+               afs_evenCBs++;  /*A particular fid was specified */
+loop2:
+           ObtainReadLock(&afs_xvcache);
            i = VCHash(&localFid);
-           for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
-               if (tvc->fid.Fid.Vnode == a_fid->Vnode
-                   && tvc->fid.Fid.Volume == a_fid->Volume
-                   && tvc->fid.Fid.Unique == a_fid->Unique ) {
-                   tvc->callback = (struct server *)0;
-                   tvc->quick.stamp = 0; 
-                   tvc->h1.dchint = NULL; /* invalidate hints */
-                   ObtainWriteLock(&afs_xcbhash, 450);
-                   afs_DequeueCallback(tvc);
-                   tvc->states &= ~(CStatd | CUnique | CBulkFetching);
-                   ReleaseWriteLock(&afs_xcbhash);
-                   if (a_fid->Vnode & 1 || (vType(tvc) == VDIR))
-                       osi_dnlc_purgedp(tvc);
+           for (tvc = afs_vhashT[i]; tvc; tvc = uvc) {
+               uvc = tvc->hnext;
+               if (tvc->f.fid.Fid.Vnode == a_fid->Vnode
+                   && tvc->f.fid.Fid.Volume == a_fid->Volume
+                   && tvc->f.fid.Fid.Unique == a_fid->Unique) {
+                   tvc->callback = NULL;
+                   tvc->dchint = NULL; /* invalidate hints */
+                   if (tvc->f.states & CVInit) {
+                       ReleaseReadLock(&afs_xvcache);
+                       afs_osi_Sleep(&tvc->f.states);
+                       goto loop2;
+                   }
+#if     defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)  || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
+                   AFS_FAST_HOLD(tvc);
+#else
+#ifdef AFS_DARWIN80_ENV
+                   if (tvc->f.states & CDeadVnode) {
+                       ReleaseReadLock(&afs_xvcache);
+                       afs_osi_Sleep(&tvc->f.states);
+                       goto loop2;
+                   }
+                   vp = AFSTOV(tvc);
+                   if (vnode_get(vp))
+                       continue;
+                   if (vnode_ref(vp)) {
+                       AFS_GUNLOCK();
+                       vnode_put(vp);
+                       AFS_GLOCK();
+                       continue;
+                   }
+#else
+                   AFS_FAST_HOLD(tvc);
+#endif
+#endif
+                   ReleaseReadLock(&afs_xvcache);
+                   afs_StaleVCacheFlags(tvc, 0, CUnique | CBulkFetching);
                    afs_Trace3(afs_iclSetp, CM_TRACE_CALLBACK,
-                              ICL_TYPE_POINTER, tvc, 
-                              ICL_TYPE_INT32, tvc->states, ICL_TYPE_LONG, 0);
+                              ICL_TYPE_POINTER, tvc, ICL_TYPE_INT32,
+                              tvc->f.states, ICL_TYPE_LONG, 0);
 #ifdef CBDEBUG
                    lastCallBack_vnode = afid->Vnode;
                    lastCallBack_dv = tvc->mstat.DataVersion.low;
                    osi_GetuTime(&lastCallBack_time);
 #endif /* CBDEBUG */
+#ifdef AFS_DARWIN80_ENV
+                   vnode_put(AFSTOV(tvc));
+#endif
+                   ObtainReadLock(&afs_xvcache);
+                   uvc = tvc->hnext;
+                   AFS_FAST_RELE(tvc);
                }
-           } /*Walk through hash table*/
-       } /*Clear callbacks for one file*/
-    } /*Fid has non-zero volume ID*/
+           }                   /*Walk through hash table */
+           ReleaseReadLock(&afs_xvcache);
+       }                       /*Clear callbacks for one file */
+    }
 
+    /*Fid has non-zero volume ID */
     /*
      * Always return a predictable value.
      */
-    return(0);
+    return (0);
 
-} /*ClearCallBack*/
+}                              /*ClearCallBack */
 
 
 /*------------------------------------------------------------------------
@@ -412,45 +610,39 @@ static ClearCallBack(a_conn, a_fid)
  *     As advertised.
  *------------------------------------------------------------------------*/
 
-int SRXAFSCB_CallBack(a_call, a_fids, a_callbacks)
-    struct rx_call *a_call;
-    register struct AFSCBFids *a_fids;
-    struct AFSCBs *a_callbacks;
-    
-{ /*SRXAFSCB_CallBack*/
-
-    register int i;                        /*Loop variable*/
-    struct AFSFid *tfid;                   /*Ptr to current fid*/
-    register struct rx_connection *tconn;   /*Call's connection*/
-    int code=0;
+int
+SRXAFSCB_CallBack(struct rx_call *a_call, struct AFSCBFids *a_fids,
+                 struct AFSCBs *a_callbacks)
+{
+    int i;             /*Loop variable */
+    struct AFSFid *tfid;       /*Ptr to current fid */
+    struct rx_connection *tconn;       /*Call's connection */
+    int code = 0;
     XSTATS_DECLS;
 
-#ifdef RX_ENABLE_LOCKS
-    AFS_GLOCK();
-#endif /* RX_ENABLE_LOCKS */
+    RX_AFS_GLOCK();
 
     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_CALLBACK);
 
     AFS_STATCNT(SRXAFSCB_CallBack);
-    if (!(tconn = rx_ConnectionOf(a_call))) return;
-    tfid = (struct AFSFid *) a_fids->AFSCBFids_val;
-    
+    if (!(tconn = rx_ConnectionOf(a_call)))
+       return (0);
+    tfid = (struct AFSFid *)a_fids->AFSCBFids_val;
+
     /*
      * For now, we ignore callbacks, since the File Server only *breaks*
      * callbacks at present.
      */
-    for (i = 0; i < a_fids->AFSCBFids_len; i++) 
+    for (i = 0; i < a_fids->AFSCBFids_len; i++)
        ClearCallBack(tconn, &tfid[i]);
 
     XSTATS_END_TIME;
 
-#ifdef RX_ENABLE_LOCKS
-    AFS_GUNLOCK();
-#endif /* RX_ENABLE_LOCKS */
-    
-    return(0);
+    RX_AFS_GUNLOCK();
 
-} /*SRXAFSCB_CallBack*/
+    return (0);
+
+}                              /*SRXAFSCB_CallBack */
 
 
 /*------------------------------------------------------------------------
@@ -474,28 +666,23 @@ int SRXAFSCB_CallBack(a_call, a_fids, a_callbacks)
  *     As advertised.
  *------------------------------------------------------------------------*/
 
-int SRXAFSCB_Probe(a_call)
-    struct rx_call *a_call;
-
-{ /*SRXAFSCB_Probe*/
+int
+SRXAFSCB_Probe(struct rx_call *a_call)
+{
     int code = 0;
     XSTATS_DECLS;
 
-#ifdef RX_ENABLE_LOCKS
-    AFS_GLOCK();
-#endif /* RX_ENABLE_LOCKS */
+    RX_AFS_GLOCK();
     AFS_STATCNT(SRXAFSCB_Probe);
 
     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_PROBE);
     XSTATS_END_TIME;
 
-#ifdef RX_ENABLE_LOCKS
-    AFS_GUNLOCK();
-#endif /* RX_ENABLE_LOCKS */
+    RX_AFS_GUNLOCK();
 
-    return(0);
+    return (0);
 
-} /*SRXAFSCB_Probe*/
+}                              /*SRXAFSCB_Probe */
 
 
 /*------------------------------------------------------------------------
@@ -518,23 +705,18 @@ int SRXAFSCB_Probe(a_call)
  *     As advertised.
  *------------------------------------------------------------------------*/
 
-int SRXAFSCB_InitCallBackState(a_call)
-    struct rx_call *a_call;
-
-{ /*SRXAFSCB_InitCallBackState*/
-
-    register int i;
-    register struct vcache *tvc;
-    register struct rx_connection *tconn;
-    register struct rx_peer *peer;
+int
+SRXAFSCB_InitCallBackState(struct rx_call *a_call)
+{
+    int i;
+    struct vcache *tvc;
+    struct rx_connection *tconn;
+    struct rx_peer *peer;
     struct server *ts;
     int code = 0;
-    extern int osi_dnlc_purge();
     XSTATS_DECLS;
 
-#ifdef RX_ENABLE_LOCKS
-    AFS_GLOCK();
-#endif /* RX_ENABLE_LOCKS */
+    RX_AFS_GLOCK();
 
     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_INITCALLBACKSTATE);
     AFS_STATCNT(SRXAFSCB_InitCallBackState);
@@ -545,49 +727,49 @@ int SRXAFSCB_InitCallBackState(a_call)
     if ((tconn = rx_ConnectionOf(a_call)) && (peer = rx_PeerOf(tconn))) {
 
        afs_allCBs++;
-       afs_oddCBs++;   /*Including any missed via create race*/
-       afs_evenCBs++;  /*Including any missed via create race*/
+       afs_oddCBs++;           /*Including any missed via create race */
+       afs_evenCBs++;          /*Including any missed via create race */
 
-       ts = afs_FindServer(rx_HostOf(peer), rx_PortOf(peer), (afsUUID *)0, 0);
+       ts = afs_FindServer(rx_HostOf(peer), rx_PortOf(peer), (afsUUID *) 0,
+                           0);
        if (ts) {
            for (i = 0; i < VCSIZE; i++)
                for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
                    if (tvc->callback == ts) {
-                       ObtainWriteLock(&afs_xcbhash, 451);
-                       afs_DequeueCallback(tvc);
-                       tvc->callback = (struct server *)0;
-                       tvc->states &= ~(CStatd | CUnique | CBulkFetching);
-                       ReleaseWriteLock(&afs_xcbhash);
+                       afs_StaleVCacheFlags(tvc, AFS_STALEVC_NODNLC |
+                                                 AFS_STALEVC_CLEARCB,
+                                            CUnique | CBulkFetching);
                    }
                }
+
+           /* capabilities need be requested again */
+           ts->flags &= ~SCAPS_KNOWN;
        }
 
-      
+
+
        /* find any volumes residing on this server and flush their state */
        {
-           register struct volume *tv;
-           register int j;
-        
-           for (i=0;i<NVOLS;i++) 
-               for (tv = afs_volumes[i]; tv; tv=tv->next) {
-                   for (j=0; j<MAXHOSTS; j++)
+           struct volume *tv;
+           int j;
+
+           for (i = 0; i < NVOLS; i++)
+               for (tv = afs_volumes[i]; tv; tv = tv->next) {
+                   for (j = 0; j < AFS_MAXHOSTS; j++)
                        if (tv->serverHost[j] == ts)
                            afs_ResetVolumeInfo(tv);
                }
        }
-       osi_dnlc_purge(); /* may be a little bit extreme */
+       osi_dnlc_purge();       /* may be a little bit extreme */
     }
 
     XSTATS_END_TIME;
 
-#ifdef RX_ENABLE_LOCKS
-    AFS_GUNLOCK();
-#endif /* RX_ENABLE_LOCKS */
+    RX_AFS_GUNLOCK();
 
-    return(0);
+    return (0);
 
-} /*SRXAFSCB_InitCallBackState*/
+}                              /*SRXAFSCB_InitCallBackState */
 
 
 /*------------------------------------------------------------------------
@@ -611,30 +793,24 @@ int SRXAFSCB_InitCallBackState(a_call)
  *     As advertised.
  *------------------------------------------------------------------------*/
 
-int SRXAFSCB_XStatsVersion(a_call, a_versionP)
-    struct rx_call *a_call;
-    afs_int32 *a_versionP;
-
-{ /*SRXAFSCB_XStatsVersion*/
-   int code=0;
+int
+SRXAFSCB_XStatsVersion(struct rx_call *a_call, afs_int32 * a_versionP)
+{
+    int code = 0;
 
     XSTATS_DECLS;
 
-#ifdef RX_ENABLE_LOCKS
-    AFS_GLOCK();
-#endif /* RX_ENABLE_LOCKS */
+    RX_AFS_GLOCK();
     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_XSTATSVERSION);
 
     *a_versionP = AFSCB_XSTAT_VERSION;
 
     XSTATS_END_TIME;
 
-#ifdef RX_ENABLE_LOCKS
-    AFS_GUNLOCK();
-#endif /* RX_ENABLE_LOCKS */
+    RX_AFS_GUNLOCK();
 
-    return(0);
-}  /*SRXAFSCB_XStatsVersion*/
+    return (0);
+}                              /*SRXAFSCB_XStatsVersion */
 
 
 /*------------------------------------------------------------------------
@@ -664,24 +840,17 @@ int SRXAFSCB_XStatsVersion(a_call, a_versionP)
  *     As advertised.
  *------------------------------------------------------------------------*/
 
-int SRXAFSCB_GetXStats(a_call, a_clientVersionNum, a_collectionNumber, a_srvVersionNumP, a_timeP, a_dataP)
-    struct rx_call *a_call;
-    afs_int32 a_clientVersionNum;
-    afs_int32 a_collectionNumber;
-    afs_int32 *a_srvVersionNumP;
-    afs_int32 *a_timeP;
-    AFSCB_CollData *a_dataP;
-
-{ /*SRXAFSCB_GetXStats*/
-
-    register int code;         /*Return value*/
-    afs_int32 *dataBuffP;              /*Ptr to data to be returned*/
-    afs_int32 dataBytes;               /*Bytes in data buffer*/
+int
+SRXAFSCB_GetXStats(struct rx_call *a_call, afs_int32 a_clientVersionNum,
+                  afs_int32 a_collectionNumber, afs_int32 * a_srvVersionNumP,
+                  afs_int32 * a_timeP, AFSCB_CollData * a_dataP)
+{
+    int code;          /*Return value */
+    afs_int32 *dataBuffP;      /*Ptr to data to be returned */
+    afs_int32 dataBytes;       /*Bytes in data buffer */
     XSTATS_DECLS;
 
-#ifdef RX_ENABLE_LOCKS
-    AFS_GLOCK();
-#endif /* RX_ENABLE_LOCKS */
+    RX_AFS_GLOCK();
 
     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETXSTATS);
 
@@ -702,10 +871,10 @@ int SRXAFSCB_GetXStats(a_call, a_clientVersionNum, a_collectionNumber, a_srvVers
      * no data.
      */
     a_dataP->AFSCB_CollData_len = 0;
-    a_dataP->AFSCB_CollData_val = (afs_int32 *)0;
+    a_dataP->AFSCB_CollData_val = NULL;
 #else
-    switch(a_collectionNumber) {
-      case AFSCB_XSTATSCOLL_CALL_INFO:
+    switch (a_collectionNumber) {
+    case AFSCB_XSTATSCOLL_CALL_INFO:
        /*
         * Pass back all the call-count-related data.
         *
@@ -714,13 +883,14 @@ int SRXAFSCB_GetXStats(a_call, a_clientVersionNum, a_collectionNumber, a_srvVers
         * >>> will be freed at the tail end of the server stub code.
         */
        dataBytes = sizeof(struct afs_CMStats);
-       dataBuffP = (afs_int32 *)afs_osi_Alloc(dataBytes);
-       bcopy((char *)&afs_cmstats, (char *)dataBuffP, dataBytes);
-       a_dataP->AFSCB_CollData_len = dataBytes>>2;
+       dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
+       osi_Assert(dataBuffP != NULL);
+       memcpy((char *)dataBuffP, (char *)&afs_cmstats, dataBytes);
+       a_dataP->AFSCB_CollData_len = dataBytes >> 2;
        a_dataP->AFSCB_CollData_val = dataBuffP;
        break;
 
-      case AFSCB_XSTATSCOLL_PERF_INFO:
+    case AFSCB_XSTATSCOLL_PERF_INFO:
        /*
         * Update and then pass back all the performance-related data.
         * Note: the only performance fields that need to be computed
@@ -734,13 +904,14 @@ int SRXAFSCB_GetXStats(a_call, a_clientVersionNum, a_collectionNumber, a_srvVers
        afs_stats_cmperf.numPerfCalls++;
        afs_CountServers();
        dataBytes = sizeof(afs_stats_cmperf);
-       dataBuffP = (afs_int32 *)afs_osi_Alloc(dataBytes);
-       bcopy((char *)&afs_stats_cmperf, (char *)dataBuffP, dataBytes);
-       a_dataP->AFSCB_CollData_len = dataBytes>>2;
+       dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
+       osi_Assert(dataBuffP != NULL);
+       memcpy((char *)dataBuffP, (char *)&afs_stats_cmperf, dataBytes);
+       a_dataP->AFSCB_CollData_len = dataBytes >> 2;
        a_dataP->AFSCB_CollData_val = dataBuffP;
        break;
 
-      case AFSCB_XSTATSCOLL_FULL_PERF_INFO:
+    case AFSCB_XSTATSCOLL_FULL_PERF_INFO:
        /*
         * Pass back the full range of performance and statistical
         * data available.  We have to bring the normal performance
@@ -753,37 +924,35 @@ int SRXAFSCB_GetXStats(a_call, a_clientVersionNum, a_collectionNumber, a_srvVers
         */
        afs_stats_cmperf.numPerfCalls++;
        afs_CountServers();
-       bcopy((char *)(&afs_stats_cmperf),
-             (char *)(&(afs_stats_cmfullperf.perf)),
-             sizeof(struct afs_stats_CMPerf));
+       memcpy((char *)(&(afs_stats_cmfullperf.perf)),
+              (char *)(&afs_stats_cmperf), sizeof(struct afs_stats_CMPerf));
        afs_stats_cmfullperf.numFullPerfCalls++;
 
        dataBytes = sizeof(afs_stats_cmfullperf);
-       dataBuffP = (afs_int32 *)afs_osi_Alloc(dataBytes);
-       bcopy((char *)(&afs_stats_cmfullperf), (char *)dataBuffP, dataBytes);
-       a_dataP->AFSCB_CollData_len = dataBytes>>2;
+       dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
+       osi_Assert(dataBuffP != NULL);
+       memcpy((char *)dataBuffP, (char *)(&afs_stats_cmfullperf), dataBytes);
+       a_dataP->AFSCB_CollData_len = dataBytes >> 2;
        a_dataP->AFSCB_CollData_val = dataBuffP;
        break;
 
-      default:
+    default:
        /*
         * Illegal collection number.
         */
        a_dataP->AFSCB_CollData_len = 0;
-       a_dataP->AFSCB_CollData_val = (afs_int32 *)0;
+       a_dataP->AFSCB_CollData_val = NULL;
        code = 1;
-    } /*Switch on collection number*/
+    }                          /*Switch on collection number */
 #endif /* AFS_NOSTATS */
 
     XSTATS_END_TIME;
 
-#ifdef RX_ENABLE_LOCKS
-    AFS_GUNLOCK();
-#endif /* RX_ENABLE_LOCKS */
+    RX_AFS_GUNLOCK();
 
-    return(code);
+    return (code);
 
-} /*SRXAFSCB_GetXStats*/
+}                              /*SRXAFSCB_GetXStats */
 
 
 /*------------------------------------------------------------------------
@@ -805,9 +974,9 @@ int SRXAFSCB_GetXStats(a_call, a_clientVersionNum, a_collectionNumber, a_srvVers
  *     As advertised.
  *------------------------------------------------------------------------*/
 
-int afs_RXCallBackServer()
-
-{ /*afs_RXCallBackServer*/
+int
+afs_RXCallBackServer(void)
+{
     AFS_STATCNT(afs_RXCallBackServer);
 
     while (1) {
@@ -819,10 +988,10 @@ int afs_RXCallBackServer()
     /*
      * Donate this process to Rx.
      */
-    rx_ServerProc();
-    return(0);
+    rx_ServerProc(NULL);
+    return (0);
 
-} /*afs_RXCallBackServer*/
+}                              /*afs_RXCallBackServer */
 
 
 /*------------------------------------------------------------------------
@@ -844,22 +1013,19 @@ int afs_RXCallBackServer()
  *     As advertised.
  *------------------------------------------------------------------------*/
 
-int shutdown_CB() 
-
-{ /*shutdown_CB*/
-
-  extern int afs_cold_shutdown;
-
-  AFS_STATCNT(shutdown_CB);
+int
+shutdown_CB(void)
+{
+    AFS_STATCNT(shutdown_CB);
 
-  if (afs_cold_shutdown) {
-    afs_oddCBs = afs_evenCBs = afs_allCBs = afs_allZaps = afs_oddZaps = afs_evenZaps =
-       afs_connectBacks = 0;
-  }
+    if (afs_cold_shutdown) {
+       afs_oddCBs = afs_evenCBs = afs_allCBs = afs_allZaps = afs_oddZaps =
+           afs_evenZaps = afs_connectBacks = 0;
+    }
 
-  return(0);
+    return (0);
 
-} /*shutdown_CB*/
+}                              /*shutdown_CB */
 
 /*------------------------------------------------------------------------
  * EXPORTED SRXAFSCB_InitCallBackState2
@@ -872,7 +1038,7 @@ int shutdown_CB()
  *      a_call : Ptr to Rx call on which this request came in.
  *
  * Returns:
- *      RXGEN_OPCODE (always). 
+ *      RXGEN_OPCODE (always).
  *
  * Environment:
  *      Nothing interesting.
@@ -881,11 +1047,11 @@ int shutdown_CB()
  *      None
  *------------------------------------------------------------------------*/
 
-int SRXAFSCB_InitCallBackState2(a_call, addr)
-struct rx_call *a_call;
-struct interfaceAddr * addr;
+int
+SRXAFSCB_InitCallBackState2(struct rx_call *a_call,
+                           struct interfaceAddr *addr)
 {
-       return RXGEN_OPCODE;
+    return RXGEN_OPCODE;
 }
 
 /*------------------------------------------------------------------------
@@ -912,26 +1078,24 @@ struct interfaceAddr * addr;
  *      As advertised.
  *------------------------------------------------------------------------*/
 
-int SRXAFSCB_WhoAreYou(a_call, addr)
-struct rx_call *a_call;
-struct interfaceAddr *addr;
+int
+SRXAFSCB_WhoAreYou(struct rx_call *a_call, struct interfaceAddr *addr)
 {
     int i;
     int code = 0;
-    XSTATS_DECLS;
 
-#ifdef RX_ENABLE_LOCKS
-    AFS_GLOCK();
-#endif /* RX_ENABLE_LOCKS */
+    RX_AFS_GLOCK();
 
     AFS_STATCNT(SRXAFSCB_WhoAreYou);
 
+    memset(addr, 0, sizeof(*addr));
+
     ObtainReadLock(&afs_xinterface);
 
     /* return all network interface addresses */
     addr->numberOfInterfaces = afs_cb_interface.numberOfInterfaces;
     addr->uuid = afs_cb_interface.uuid;
-    for ( i=0; i < afs_cb_interface.numberOfInterfaces; i++) {
+    for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
        addr->addr_in[i] = ntohl(afs_cb_interface.addr_in[i]);
        addr->subnetmask[i] = ntohl(afs_cb_interface.subnetmask[i]);
        addr->mtu[i] = ntohl(afs_cb_interface.mtu[i]);
@@ -939,9 +1103,7 @@ struct interfaceAddr *addr;
 
     ReleaseReadLock(&afs_xinterface);
 
-#ifdef RX_ENABLE_LOCKS
-    AFS_GUNLOCK();
-#endif /* RX_ENABLE_LOCKS */
+    RX_AFS_GUNLOCK();
 
     return code;
 }
@@ -967,9 +1129,8 @@ struct interfaceAddr *addr;
  *     As advertised.
  *------------------------------------------------------------------------*/
 
-int SRXAFSCB_InitCallBackState3(a_call, a_uuid)
-struct rx_call *a_call;
-afsUUID *a_uuid;
+int
+SRXAFSCB_InitCallBackState3(struct rx_call *a_call, afsUUID * a_uuid)
 {
     int code;
 
@@ -980,7 +1141,7 @@ afsUUID *a_uuid;
 
     return code;
 }
+
 
 /*------------------------------------------------------------------------
  * EXPORTED SRXAFSCB_ProbeUuid
@@ -1005,30 +1166,25 @@ afsUUID *a_uuid;
  *     As advertised.
  *------------------------------------------------------------------------*/
 
-int SRXAFSCB_ProbeUuid(a_call, a_uuid)
-struct rx_call *a_call;
-afsUUID *a_uuid;
+int
+SRXAFSCB_ProbeUuid(struct rx_call *a_call, afsUUID * a_uuid)
 {
     int code = 0;
     XSTATS_DECLS;
 
-#ifdef RX_ENABLE_LOCKS
-    AFS_GLOCK();
-#endif /* RX_ENABLE_LOCKS */
+    RX_AFS_GLOCK();
     AFS_STATCNT(SRXAFSCB_Probe);
 
     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_PROBE);
     if (!afs_uuid_equal(a_uuid, &afs_cb_interface.uuid))
-       code = 1; /* failure */
+       code = 1;               /* failure */
     XSTATS_END_TIME;
 
-#ifdef RX_ENABLE_LOCKS
-    AFS_GUNLOCK();
-#endif /* RX_ENABLE_LOCKS */
+    RX_AFS_GUNLOCK();
 
     return code;
 }
+
 
 /*------------------------------------------------------------------------
  * EXPORTED SRXAFSCB_GetServerPrefs
@@ -1053,18 +1209,14 @@ afsUUID *a_uuid;
  *     As advertised.
  *------------------------------------------------------------------------*/
 
-int SRXAFSCB_GetServerPrefs(
-    struct rx_call *a_call,
-    afs_int32 a_index,
-    afs_int32 *a_srvr_addr,
-    afs_int32 *a_srvr_rank)
+int
+SRXAFSCB_GetServerPrefs(struct rx_call *a_call, afs_int32 a_index,
+                       afs_int32 * a_srvr_addr, afs_int32 * a_srvr_rank)
 {
     int i, j;
     struct srvAddr *sa;
 
-#ifdef RX_ENABLE_LOCKS
-    AFS_GLOCK();
-#endif /* RX_ENABLE_LOCKS */
+    RX_AFS_GLOCK();
     AFS_STATCNT(SRXAFSCB_GetServerPrefs);
 
     ObtainReadLock(&afs_xserver);
@@ -1072,7 +1224,7 @@ int SRXAFSCB_GetServerPrefs(
     /* Search the hash table for the server with this index */
     *a_srvr_addr = 0xffffffff;
     *a_srvr_rank = 0xffffffff;
-    for (i=0, j=0; j < NSERVERS && i <= a_index; j++) {
+    for (i = 0, j = 0; j < NSERVERS && i <= a_index; j++) {
        for (sa = afs_srvAddrs[j]; sa && i <= a_index; sa = sa->next_bkt, i++) {
            if (i == a_index) {
                *a_srvr_addr = ntohl(sa->sa_ip);
@@ -1083,13 +1235,11 @@ int SRXAFSCB_GetServerPrefs(
 
     ReleaseReadLock(&afs_xserver);
 
-#ifdef RX_ENABLE_LOCKS
-    AFS_GUNLOCK();
-#endif /* RX_ENABLE_LOCKS */
+    RX_AFS_GUNLOCK();
 
     return 0;
 }
+
 
 /*------------------------------------------------------------------------
  * EXPORTED SRXAFSCB_GetCellServDB
@@ -1113,55 +1263,54 @@ int SRXAFSCB_GetServerPrefs(
  *     As advertised.
  *------------------------------------------------------------------------*/
 
-int SRXAFSCB_GetCellServDB(
-    struct rx_call *a_call,
-    afs_int32 a_index,
-    char **a_name,
-    afs_int32 *a_hosts)
+int
+SRXAFSCB_GetCellServDB(struct rx_call *a_call, afs_int32 a_index,
+                      char **a_name, serverList * a_hosts)
 {
-    afs_int32 i, j;
+    afs_int32 i, j = 0;
     struct cell *tcell;
-    struct afs_q *cq, *tq;
-    char *t_name;
+    char *t_name, *p_name = NULL;
 
-#ifdef RX_ENABLE_LOCKS
-    AFS_GLOCK();
-#endif /* RX_ENABLE_LOCKS */
+    RX_AFS_GLOCK();
     AFS_STATCNT(SRXAFSCB_GetCellServDB);
 
-    t_name = (char *)rxi_Alloc(AFSNAMEMAX);
+    tcell = afs_GetCellByIndex(a_index, READ_LOCK);
+
+    if (!tcell) {
+       i = 0;
+       a_hosts->serverList_val = 0;
+       a_hosts->serverList_len = 0;
+    } else {
+       p_name = tcell->cellName;
+       for (j = 0; j < AFSMAXCELLHOSTS && tcell->cellHosts[j]; j++);
+       i = strlen(p_name);
+       a_hosts->serverList_val = afs_osi_Alloc(j * sizeof(afs_int32));
+       osi_Assert(a_hosts->serverList_val != NULL);
+       a_hosts->serverList_len = j;
+       for (j = 0; j < AFSMAXCELLHOSTS && tcell->cellHosts[j]; j++)
+           a_hosts->serverList_val[j] =
+               ntohl(tcell->cellHosts[j]->addr->sa_ip);
+       afs_PutCell(tcell, READ_LOCK);
+    }
+
+    t_name = afs_osi_Alloc(i + 1);
     if (t_name == NULL) {
-#ifdef RX_ENABLE_LOCKS
-       AFS_GUNLOCK();
-#endif /* RX_ENABLE_LOCKS */
+       if (tcell != NULL)
+           afs_osi_Free(a_hosts->serverList_val, (j * sizeof(afs_int32)));
+       RX_AFS_GUNLOCK();
        return ENOMEM;
     }
 
-    t_name[0] = '\0';
-    bzero(a_hosts, AFSMAXCELLHOSTS * sizeof(afs_int32));
-
-    /* search the list for the cell with this index */
-    ObtainReadLock(&afs_xcell);
-    for (i=0, cq = CellLRU.next; cq != &CellLRU && i<= a_index; cq = tq, i++) {
-        tq = QNext(cq);
-       if (i == a_index) {
-           tcell = QTOC(cq);
-           strcpy(t_name, tcell->cellName);
-           for (j = 0 ; j < AFSMAXCELLHOSTS && tcell->cellHosts[j] ; j++) {
-               a_hosts[j] = ntohl(tcell->cellHosts[j]->addr->sa_ip);
-           }
-       }
-    }
-    ReleaseReadLock(&afs_xcell);
+    t_name[i] = '\0';
+    if (p_name)
+       memcpy(t_name, p_name, i);
 
-#ifdef RX_ENABLE_LOCKS
-    AFS_GUNLOCK();
-#endif /* RX_ENABLE_LOCKS */
+    RX_AFS_GUNLOCK();
 
     *a_name = t_name;
     return 0;
 }
+
 
 /*------------------------------------------------------------------------
  * EXPORTED SRXAFSCB_GetLocalCell
@@ -1183,51 +1332,43 @@ int SRXAFSCB_GetCellServDB(
  *     As advertised.
  *------------------------------------------------------------------------*/
 
-int SRXAFSCB_GetLocalCell(
-    struct rx_call *a_call,
-    char **a_name)
+int
+SRXAFSCB_GetLocalCell(struct rx_call *a_call, char **a_name)
 {
+    int plen;
     struct cell *tcell;
-    struct afs_q *cq, *tq;
-    char *t_name;
+    char *t_name, *p_name = NULL;
 
-#ifdef RX_ENABLE_LOCKS
-    AFS_GLOCK();
-#endif /* RX_ENABLE_LOCKS */
+    RX_AFS_GLOCK();
     AFS_STATCNT(SRXAFSCB_GetLocalCell);
 
-    t_name = (char *)rxi_Alloc(AFSNAMEMAX);
-    if (t_name == NULL) {
-#ifdef RX_ENABLE_LOCKS
-       AFS_GUNLOCK();
-#endif /* RX_ENABLE_LOCKS */
-       return ENOMEM;
-    }
-
-    t_name[0] = '\0';
-
     /* Search the list for the primary cell. Cell number 1 is only
      * the primary cell is when no other cell is explicitly marked as
      * the primary cell.  */
-    ObtainReadLock(&afs_xcell);
-    for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
-        tq = QNext(cq);
-       tcell = QTOC(cq);
-       if (tcell->states & CPrimary) {
-           strcpy(t_name, tcell->cellName);
-           break;
-       }
-        if (tcell->cell == 1) {
-           strcpy(t_name, tcell->cellName);
-       }
+    tcell = afs_GetPrimaryCell(READ_LOCK);
+    if (tcell)
+       p_name = tcell->cellName;
+    if (p_name)
+       plen = strlen(p_name);
+    else
+       plen = 0;
+    t_name = afs_osi_Alloc(plen + 1);
+    if (t_name == NULL) {
+       if (tcell)
+           afs_PutCell(tcell, READ_LOCK);
+       RX_AFS_GUNLOCK();
+       return ENOMEM;
     }
-    ReleaseReadLock(&afs_xcell);
 
-#ifdef RX_ENABLE_LOCKS
-    AFS_GUNLOCK();
-#endif /* RX_ENABLE_LOCKS */
+    t_name[plen] = '\0';
+    if (p_name)
+       memcpy(t_name, p_name, plen);
+
+    RX_AFS_GUNLOCK();
 
     *a_name = t_name;
+    if (tcell)
+       afs_PutCell(tcell, READ_LOCK);
     return 0;
 }
 
@@ -1247,10 +1388,9 @@ int SRXAFSCB_GetLocalCell(
  *
  * Returns void.
  */
-static void afs_MarshallCacheConfig(
-    afs_uint32 callerVersion,
-    cm_initparams_v1 *config,
-    afs_uint32 *ptr)
+static void
+afs_MarshallCacheConfig(afs_uint32 callerVersion, cm_initparams_v1 * config,
+                       afs_uint32 * ptr)
 {
     AFS_STATCNT(afs_MarshallCacheConfig);
     /*
@@ -1265,9 +1405,8 @@ static void afs_MarshallCacheConfig(
     *(ptr++) = config->cacheSize;
     *(ptr++) = config->setTime;
     *(ptr++) = config->memCache;
-
 }
+
 
 /*------------------------------------------------------------------------
  * EXPORTED SRXAFSCB_GetCacheConfig
@@ -1294,31 +1433,25 @@ static void afs_MarshallCacheConfig(
  *     As advertised.
  *------------------------------------------------------------------------*/
 
-int SRXAFSCB_GetCacheConfig(
-    struct rx_call *a_call,
-    afs_uint32 callerVersion,
-    afs_uint32 *serverVersion,
-    afs_uint32 *configCount,
-    cacheConfig *config)
+int
+SRXAFSCB_GetCacheConfig(struct rx_call *a_call, afs_uint32 callerVersion,
+                       afs_uint32 * serverVersion, afs_uint32 * configCount,
+                       cacheConfig * config)
 {
     afs_uint32 *t_config;
     size_t allocsize;
     cm_initparams_v1 cm_config;
 
-#ifdef RX_ENABLE_LOCKS
-    AFS_GLOCK();
-#endif /* RX_ENABLE_LOCKS */
+    RX_AFS_GLOCK();
     AFS_STATCNT(SRXAFSCB_GetCacheConfig);
 
     /*
      * Currently only support version 1
      */
     allocsize = sizeof(cm_initparams_v1);
-    t_config = (afs_uint32 *)rxi_Alloc(allocsize);
+    t_config = afs_osi_Alloc(allocsize);
     if (t_config == NULL) {
-#ifdef RX_ENABLE_LOCKS
-       AFS_GUNLOCK();
-#endif /* RX_ENABLE_LOCKS */
+       RX_AFS_GUNLOCK();
        return ENOMEM;
     }
 
@@ -1337,11 +1470,307 @@ int SRXAFSCB_GetCacheConfig(
     *serverVersion = AFS_CLIENT_RETRIEVAL_FIRST_EDITION;
     *configCount = allocsize;
     config->cacheConfig_val = t_config;
-    config->cacheConfig_len = allocsize/sizeof(afs_uint32);
+    config->cacheConfig_len = allocsize / sizeof(afs_uint32);
+
+    RX_AFS_GUNLOCK();
+
+    return 0;
+}
+
+/*------------------------------------------------------------------------
+ * EXPORTED SRXAFSCB_FetchData
+ *
+ * Description:
+ *      Routine to do third party move from a remioserver to the original
+ *      issuer of an ArchiveData request. Presently supported only by the
+ *      "fs" command, not by the AFS client.
+ *
+ * Arguments:
+ *      rxcall:        Ptr to Rx call on which this request came in.
+ *      Fid:           pointer to AFSFid structure.
+ *      Fd:            File descriptor inside fs command.
+ *      Position:      Offset in the file.
+ *      Length:        Data length to transfer.
+ *      TotalLength:   Pointer to total file length field
+ *
+ * Returns:
+ *      0 on success
+ *
+ * Environment:
+ *      Nothing interesting.
+ *
+ * Side Effects:
+ *------------------------------------------------------------------------*/
+int
+SRXAFSCB_FetchData(struct rx_call *rxcall, struct AFSFid *Fid, afs_int32 Fd,
+                  afs_int64 Position, afs_int64 Length,
+                  afs_int64 * TotalLength)
+{
+    return ENOSYS;
+}
+
+/*------------------------------------------------------------------------
+ * EXPORTED SRXAFSCB_StoreData
+ *
+ * Description:
+ *      Routine to do third party move from a remioserver to the original
+ *      issuer of a RetrieveData request. Presently supported only by the
+ *      "fs" command, not by the AFS client.
+ *
+ * Arguments:
+ *      rxcall:        Ptr to Rx call on which this request came in.
+ *      Fid:           pointer to AFSFid structure.
+ *      Fd:            File descriptor inside fs command.
+ *      Position:      Offset in the file.
+ *      Length:        Data length to transfer.
+ *      TotalLength:   Pointer to total file length field
+ *
+ * Returns:
+ *      0 on success
+ *
+ * Environment:
+ *      Nothing interesting.
+ *
+ * Side Effects:
+ *      As advertised.
+ *------------------------------------------------------------------------*/
+int
+SRXAFSCB_StoreData(struct rx_call *rxcall, struct AFSFid *Fid, afs_int32 Fd,
+                  afs_int64 Position, afs_int64 Length,
+                  afs_int64 * TotalLength)
+{
+    return ENOSYS;
+}
+
+/*------------------------------------------------------------------------
+ * EXPORTED SRXAFSCB_GetCellByNum
+ *
+ * Description:
+ *     Routine to get information about a cell specified by its
+ *     cell number (returned by GetCE/GetCE64).
+ *
+ * Arguments:
+ *     a_call    : Ptr to Rx call on which this request came in.
+ *     a_cellnum : Input cell number
+ *     a_name    : Output cell name (one zero byte when no such cell).
+ *     a_hosts   : Output cell database servers in host byte order.
+ *
+ * Returns:
+ *     0 on success
+ *
+ * Environment:
+ *     Nothing interesting.
+ *
+ * Side Effects:
+ *     As advertised.
+ *------------------------------------------------------------------------*/
+
+int
+SRXAFSCB_GetCellByNum(struct rx_call *a_call, afs_int32 a_cellnum,
+                     char **a_name, serverList * a_hosts)
+{
+    afs_int32 i, sn;
+    struct cell *tcell;
+
+    RX_AFS_GLOCK();
+    AFS_STATCNT(SRXAFSCB_GetCellByNum);
+
+    a_hosts->serverList_val = 0;
+    a_hosts->serverList_len = 0;
+
+    tcell = afs_GetCellStale(a_cellnum, READ_LOCK);
+    if (!tcell) {
+       *a_name = afs_strdup("");
+       RX_AFS_GUNLOCK();
+       return 0;
+    }
+
+    ObtainReadLock(&tcell->lock);
+    *a_name = afs_strdup(tcell->cellName);
+
+    for (sn = 0; sn < AFSMAXCELLHOSTS && tcell->cellHosts[sn]; sn++);
+    a_hosts->serverList_len = sn;
+    a_hosts->serverList_val = afs_osi_Alloc(sn * sizeof(afs_int32));
+    osi_Assert(a_hosts->serverList_val != NULL);
+
+    for (i = 0; i < sn; i++)
+       a_hosts->serverList_val[i] = ntohl(tcell->cellHosts[i]->addr->sa_ip);
+    ReleaseReadLock(&tcell->lock);
+    afs_PutCell(tcell, READ_LOCK);
+
+    RX_AFS_GUNLOCK();
+    return 0;
+}
+
+int
+SRXAFSCB_TellMeAboutYourself(struct rx_call *a_call,
+                            struct interfaceAddr *addr,
+                            Capabilities * capabilities)
+{
+    int i;
+    int code = 0;
+    afs_uint32 *dataBuffP;
+    afs_int32 dataBytes;
+
+    RX_AFS_GLOCK();
+
+    AFS_STATCNT(SRXAFSCB_WhoAreYou);
+
+    ObtainReadLock(&afs_xinterface);
+
+    /* return all network interface addresses */
+    addr->numberOfInterfaces = afs_cb_interface.numberOfInterfaces;
+    addr->uuid = afs_cb_interface.uuid;
+    for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
+       addr->addr_in[i] = ntohl(afs_cb_interface.addr_in[i]);
+       addr->subnetmask[i] = ntohl(afs_cb_interface.subnetmask[i]);
+       addr->mtu[i] = ntohl(afs_cb_interface.mtu[i]);
+    }
+
+    ReleaseReadLock(&afs_xinterface);
+
+    RX_AFS_GUNLOCK();
+
+    dataBytes = 1 * sizeof(afs_uint32);
+    dataBuffP = afs_osi_Alloc(dataBytes);
+    osi_Assert(dataBuffP != NULL);
+    dataBuffP[0] = CLIENT_CAPABILITY_ERRORTRANS;
+    capabilities->Capabilities_len = dataBytes / sizeof(afs_uint32);
+    capabilities->Capabilities_val = dataBuffP;
+
+    return code;
+}
+
+
+#if 0 && defined(AFS_LINUX24_ENV)
+extern struct vcache *afs_globalVp;
+
+int recurse_dcache_parent(parent, a_index, addr, inode, flags, time, fileName)
+     struct dentry * parent;
+    afs_int32 a_index;
+    afs_int32 *addr;
+    afs_int32 *inode;
+    afs_int32 *flags;
+    afs_int32 *time;
+    char ** fileName;
+{
+       struct dentry *this_parent = parent;
+       struct list_head *next;
+       int found = 0;
+       struct dentry *dentry;
+
+repeat:
+       next = this_parent->d_subdirs.next;
+resume:
+       while (next != &this_parent->d_subdirs) {
+               struct list_head *tmp = next;
+               dentry = list_entry(tmp, struct dentry, d_child);
+               if (a_index == 0)
+                 goto searchdone3;
+               a_index--;
+               next = tmp->next;
+               /*
+                * Descend a level if the d_subdirs list is non-empty.
+                */
+               if (!list_empty(&dentry->d_subdirs)) {
+                       this_parent = dentry;
+                       goto repeat;
+               }
+       }
+       /*
+        * All done at this level ... ascend and resume the search.
+        */
+       if (this_parent != parent) {
+               next = this_parent->d_child.next;
+               this_parent = this_parent->d_parent;
+               goto resume;
+       }
+       goto ret;
+
+ searchdone3:
+    if (d_unhashed(dentry))
+      *flags = 1;
+    else
+      *flags = 0;
+
+    *fileName = afs_strdup(dentry->d_name.name?dentry->d_name.name:"");
+    *inode = ITOAFS(dentry->d_inode);
+    *addr = atomic_read(&(dentry)->d_count);
+    *time = dentry->d_time;
+
+    return 0;
+ ret:
+    return 1;
+}
+#endif
+
+int
+SRXAFSCB_GetDE(struct rx_call *a_call, afs_int32 a_index, afs_int32 *addr,
+              afs_int32 *inode, afs_int32 *flags, afs_int32 *time,
+              char ** fileName)
+{ /*SRXAFSCB_GetDE*/
+    int code = 0;                              /*Return code*/
+#if 0 && defined(AFS_LINUX24_ENV)
+    int i;                     /*Loop variable*/
+    struct vcache *tvc = afs_globalVp;
+    struct dentry *dentry;
+    struct list_head *cur, *head = &(AFSTOI(tvc))->i_dentry;
+
+#ifdef RX_ENABLE_LOCKS
+    AFS_GLOCK();
+#endif /* RX_ENABLE_LOCKS */
+
+#if defined(AFS_LINUX24_ENV)
+    spin_lock(&dcache_lock);
+#endif
+
+    cur = head;
+    while ((cur = cur->next) != head) {
+      dentry = list_entry(cur, struct dentry, d_alias);
+
+      dget_locked(dentry);
+
+#if defined(AFS_LINUX24_ENV)
+      spin_unlock(&dcache_lock);
+#endif
+      if (a_index == 0)
+       goto searchdone2;
+      a_index--;
+
+      if (recurse_dcache_parent(dentry, a_index, addr, inode, flags, time, fileName) == 0) {
+       dput(dentry);
+       code = 0;
+       goto fcnDone;
+      }
+      dput(dentry);
+    }
+ searchdone2:
+    if (cur == head) {
+       /*Past EOF*/
+       code = 1;
+       *fileName = afs_strdup("");
+       goto fcnDone;
+    }
+
+    if (d_unhashed(dentry))
+      *flags = 1;
+    else
+      *flags = 0;
+
+    *fileName = afs_strdup(dentry->d_name.name?dentry->d_name.name:"");
+    *inode = ITOAFS(dentry->d_inode);
+    *addr = atomic_read(&(dentry)->d_count);
+    *time = dentry->d_time;
+
+    dput(dentry);
+    code = 0;
+
+fcnDone:
 
 #ifdef RX_ENABLE_LOCKS
     AFS_GUNLOCK();
 #endif /* RX_ENABLE_LOCKS */
+#endif
+    return(code);
 
-    return 0;
-}
+} /*SRXAFSCB_GetDE*/