]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
DEVEL15-windows-give-up-callbacks-20070627
authorJeffrey Altman <jaltman@secure-endpoints.com>
Thu, 28 Jun 2007 05:05:20 +0000 (05:05 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Thu, 28 Jun 2007 05:05:20 +0000 (05:05 +0000)
This large patch adds support for giving up callbacks in response to three
events:

 1. power management suspend

 2. power management shutdown

 3. stat cache object recycling

The third item is submitted as a condition compilation if GIVE_UP_CALLBACKS
is defined.  Properly handing callback give ups and the associated race
conditions with revokes and fetch status requests requires a great deal of
over head.  The first attempt used one GiveUpCallBacks RPC for each callback
that was being dropped as the stat cache object was recycled.  This resulted
in a 27% performance drop in the MIT stress test.  The code that is being
committed maintains a callback give up list on each server object.  The
callback is added to the list as the callbacks are dropped and then they
are sent to the server in bulk by the background daemon thread if the
server is known to be UP after a ping.  Logic is added to the
EndCallbackRequest and CallbackRevoke operations to ensure that race
conditions are addressed.  With all of this, there is a 17% performance drop
in the MIT stress test.

As a result, it is my conclusion that the client side costs associated with
optimizing the load on the server are simply too high.  I am committing this
code to ensure that it is not lost.  I will remove this support in the next
patch while leaving the support for giving up all callbacks in response
to suspend and shutdown events.

(cherry picked from commit 61e6f04009bba3ac13a8eda4a6663f4b6508dbc9)

src/WINNT/afsd/afsd_service.c
src/WINNT/afsd/cm_callback.c
src/WINNT/afsd/cm_callback.h
src/WINNT/afsd/cm_scache.c
src/WINNT/afsd/cm_scache.h
src/WINNT/afsd/cm_server.c
src/WINNT/afsd/cm_server.h

index 9b0fad485d59edb51aae7927227905c7592f95c2..20fc69de4e908e16246b422ec1ecbb93a51b6740 100644 (file)
@@ -311,16 +311,20 @@ afsd_ServiceControlHandlerEx(
                 case PBT_APMQUERYSUSPEND:       
                     afsi_log("SERVICE_CONTROL_APMQUERYSUSPEND"); 
                     /* Write all dirty buffers back to server */
-                   if ( !lana_OnlyLoopback() )
+                   if ( !lana_OnlyLoopback() ) {
                        buf_CleanAndReset();
+                        cm_SuspendSCache();
+                    }
                     afsi_log("SERVICE_CONTROL_APMQUERYSUSPEND buf_CleanAndReset complete"); 
                     dwRet = NO_ERROR;                       
                     break;                                  
                 case PBT_APMQUERYSTANDBY:                                                         
                     afsi_log("SERVICE_CONTROL_APMQUERYSTANDBY"); 
                     /* Write all dirty buffers back to server */
-                   if ( !lana_OnlyLoopback() ) 
+                   if ( !lana_OnlyLoopback() ) {
                        buf_CleanAndReset();
+                        cm_SuspendSCache();
+                    }
                     afsi_log("SERVICE_CONTROL_APMQUERYSTANDBY buf_CleanAndReset complete"); 
                     dwRet = NO_ERROR;                                                             
                     break;                                                                        
@@ -329,15 +333,19 @@ afsd_ServiceControlHandlerEx(
                 case PBT_APMSUSPEND:                         
                     afsi_log("SERVICE_CONTROL_APMSUSPEND");
                    powerStateSuspended = 1;
-                   if (osVersion.dwMajorVersion >= 6)
+                   if (osVersion.dwMajorVersion >= 6) {
+                        cm_SuspendSCache();
                        smb_StopListeners();
+                    }
                     dwRet = NO_ERROR;                       
                     break;                                  
                 case PBT_APMSTANDBY:                  
                     afsi_log("SERVICE_CONTROL_APMSTANDBY"); 
                    powerStateSuspended = 1;
-                   if (osVersion.dwMajorVersion >= 6)
+                   if (osVersion.dwMajorVersion >= 6) {
+                        cm_SuspendSCache();
                        smb_StopListeners();
+                    }
                     dwRet = NO_ERROR;                       
                     break;                                  
                 case PBT_APMRESUMECRITICAL:             
index 72b8bba5be10aa85627ddac99b750f8550909219..97081087359c3a6a9ff186b14879fedad61478bd 100644 (file)
@@ -207,10 +207,19 @@ void cm_RevokeCallback(struct rx_call *callp, cm_cell_t * cellp, AFSFid *fidp)
             lock_ReleaseWrite(&cm_scacheLock);
             osi_Log4(afsd_logp, "RevokeCallback Discarding SCache scp 0x%p vol %u vn %u uniq %u", 
                      scp, scp->fid.volume, scp->fid.vnode, scp->fid.unique);
+
+#ifdef GIVE_UP_CALLBACKS
+            lock_ObtainMutex(&scp->cbServerp->mx);
+            cm_RemoveFidFromGiveUpCallBackList(scp->cbServerp, &scp->fid);
+            lock_ReleaseMutex(&scp->cbServerp->mx);
+#endif /* GIVE_UP_CALLBACKS */
+
             lock_ObtainMutex(&scp->mx);
             cm_DiscardSCache(scp);
             lock_ReleaseMutex(&scp->mx);
+
             cm_CallbackNotifyChange(scp);
+            
             lock_ObtainWrite(&cm_scacheLock);
             cm_ReleaseSCacheNoLock(scp);
         }
@@ -243,7 +252,6 @@ void cm_RevokeVolumeCallback(struct rx_call *callp, cm_cell_t *cellp, AFSFid *fi
     tfid.volume = fidp->Volume;
     cm_RecordRacingRevoke(&tfid, CM_RACINGFLAG_CANCELVOL);
 
-
     lock_ObtainWrite(&cm_scacheLock);
     for (hash = 0; hash < cm_data.scacheHashTableSize; hash++) {
         for(scp=cm_data.scacheHashTablep[hash]; scp; scp=scp->nextp) {
@@ -253,11 +261,19 @@ void cm_RevokeVolumeCallback(struct rx_call *callp, cm_cell_t *cellp, AFSFid *fi
                  scp->cbServerp != NULL) {
                 cm_HoldSCacheNoLock(scp);
                 lock_ReleaseWrite(&cm_scacheLock);
+
+#ifdef GIVE_UP_CALLBACKS
+                lock_ObtainMutex(&scp->cbServerp->mx);
+                cm_RemoveFidFromGiveUpCallBackList(scp->cbServerp, &scp->fid);
+                lock_ReleaseMutex(&scp->cbServerp->mx);
+#endif /* GIVE_UP_CALLBACKS */
+
                 lock_ObtainMutex(&scp->mx);
                 osi_Log4(afsd_logp, "RevokeVolumeCallback Discarding SCache scp 0x%p vol %u vn %u uniq %u", 
                           scp, scp->fid.volume, scp->fid.vnode, scp->fid.unique);
                 cm_DiscardSCache(scp);
                 lock_ReleaseMutex(&scp->mx);
+
                 cm_CallbackNotifyChange(scp);
                 lock_ObtainWrite(&cm_scacheLock);
                 cm_ReleaseSCacheNoLock(scp);
@@ -354,7 +370,7 @@ SRXAFSCB_CallBack(struct rx_call *callp, AFSCBFids *fidsArrayp, AFSCBs *cbsArray
         host = rx_HostOf(peerp);
         port = rx_PortOf(peerp);
 
-        tsp = cm_FindServerByIP(host);
+        tsp = cm_FindServerByIP(host, CM_SERVER_FILE);
         if (tsp)
             cellp = tsp->cellp;
     }
@@ -488,9 +504,24 @@ SRXAFSCB_InitCallBackState(struct rx_call *callp)
            cm_SetServerNo64Bit(tsp, 0);
            cm_SetServerNoInlineBulk(tsp, 0);
 
+#ifdef GIVE_UP_CALLBACKS
+            /* Clear the callbacks list */
+            lock_ObtainMutex(&tsp->mx);
+            cm_FreeGiveUpCallBackList(tsp);
+            lock_ReleaseMutex(&tsp->mx);
+#endif /* GIVE_UP_CALLBACKS */
+
            /* we're done with the server structure */
             cm_PutServer(tsp);
-       }
+       } 
+#ifdef GIVE_UP_CALLBACKS        
+        else {
+            /* if we didn't recognize the server, we cleared all callbacks 
+             * on all stat scache objects.  So we must clear all of the 
+             * Give Up CallBack lists */
+            cm_FreeAllGiveUpCallBackLists();
+        }
+#endif /* GIVE_UP_CALLBACKS */
     }
     MUTEX_EXIT(&callp->lock);
     return 0;
@@ -1530,8 +1561,11 @@ void cm_EndCallbackGrantingCall(cm_scache_t *scp, cm_callbackRequest_t *cbrp,
     cm_racingRevokes_t *revp;          /* where we are */
     cm_racingRevokes_t *nrevp;         /* where we'll be next */
     int freeFlag;
-    cm_server_t * serverp = 0;
+    cm_server_t * serverp = NULL;
     int discardScp = 0;
+#ifdef GIVE_UP_CALLBACKS
+    int addFidToGUCB = 0;
+#endif /* GIVE_UP_CALLBACKS */
 
     lock_ObtainWrite(&cm_callbackLock);
     if (flags & CM_CALLBACK_MAINTAINCOUNT) {
@@ -1550,6 +1584,9 @@ void cm_EndCallbackGrantingCall(cm_scache_t *scp, cm_callbackRequest_t *cbrp,
        if (scp) {
             if (scp->cbServerp != cbrp->serverp) {
                 serverp = scp->cbServerp;
+#ifdef GIVE_UP_CALLBACKS
+                addFidToGUCB = 1;
+#endif /* GIVE_UP_CALLBACKS */
                 if (!freeFlag)
                     cm_GetServer(cbrp->serverp);
                 scp->cbServerp = cbrp->serverp;
@@ -1611,9 +1648,23 @@ void cm_EndCallbackGrantingCall(cm_scache_t *scp, cm_callbackRequest_t *cbrp,
         lock_ReleaseMutex(&scp->mx);
         cm_CallbackNotifyChange(scp);
         lock_ObtainMutex(&scp->mx);
+    } 
+#ifdef GIVE_UP_CALLBACKS    
+    else if (scp) {
+        lock_ObtainMutex(&scp->cbServerp->mx);
+        cm_RemoveFidFromGiveUpCallBackList(scp->cbServerp, &scp->fid);
+        lock_ReleaseMutex(&scp->cbServerp->mx);
     }
+#endif /* GIVE_UP_CALLBACKS */
 
     if ( serverp ) {
+#ifdef GIVE_UP_CALLBACKS
+        if (addFidToGUCB) {
+            lock_ObtainMutex(&serverp->mx);
+            cm_AddFidToGiveUpCallBackList(serverp, &scp->fid);
+            lock_ReleaseMutex(&serverp->mx);
+        }
+#endif /* GIVE_UP_CALLBACKS */
         lock_ObtainWrite(&cm_serverLock);
         cm_FreeServer(serverp);
         lock_ReleaseWrite(&cm_serverLock);
@@ -1784,3 +1835,134 @@ void cm_CheckCBExpiration(void)
     osi_Log0(afsd_logp, "CheckCBExpiration Complete");
 }
 
+
+#ifdef GIVE_UP_CALLBACKS
+/* server mutex must be held */
+/* do not hold cm_scacheLock */
+void cm_GiveUpCallBacksToServer(cm_server_t * serverp)
+{
+    struct AFSFid *tfids = NULL;
+    struct AFSCallBack callBacks[1];
+    struct AFSCBFids fidArray;
+    struct AFSCBs cbArray;
+    afs_int32 code = 0;
+    cm_server_gucb_t *gucbp, *nextp;
+    cm_conn_t *connp;
+    struct rx_connection * callp;
+    cm_req_t req;
+    int i, j;
+
+    for ( gucbp = serverp->gucbs, serverp->gucbs = NULL, lock_ReleaseMutex(&serverp->mx); 
+          gucbp; 
+          gucbp = nextp ) 
+    {
+        nextp = gucbp->nextp;
+
+        if (!tfids) {   /* only need to do these once */
+            tfids = (struct AFSFid *)malloc(AFS_MAXCBRSCALL * sizeof(*tfids));
+            osi_Assert(tfids);
+
+            fidArray.AFSCBFids_val = (struct AFSFid *)tfids;
+
+            cbArray.AFSCBs_len = 1;
+            cbArray.AFSCBs_val = callBacks;
+            memset(&callBacks[0], 0, sizeof(callBacks[0]));
+            callBacks[0].CallBackType = CB_EXCLUSIVE;
+        }
+        memset(tfids, 0, AFS_MAXCBRSCALL * sizeof(*tfids));
+
+        for ( i=0, j=0; i<gucbp->count; i++ ) {
+            if (gucbp->fids[i].cell != 0) {
+                cm_AFSFidFromFid(&tfids[j++], &gucbp->fids[i]);
+            }
+        }
+        fidArray.AFSCBFids_len = j;
+
+        cm_InitReq(&req);
+        req.flags |= CM_REQ_NORETRY;
+
+        osi_Log1(afsd_logp, "CALL GiveUpCallbacks serverp %xp", serverp);
+        do {
+            code = cm_ConnByServer(serverp, cm_rootUserp, &connp);
+            if (code) 
+                continue;
+
+            callp = cm_GetRxConn(connp);
+            code = RXAFS_GiveUpCallBacks(callp, &fidArray, &cbArray);
+            rx_PutConnection(callp);
+        } while (cm_Analyze(connp, cm_rootUserp, &req, NULL, NULL, NULL, NULL, code));
+        code = cm_MapRPCError(code, &req);
+
+        if (code)
+            osi_Log1(afsd_logp, "CALL GiveUpCallback FAILURE, code 0x%x", code);
+        else
+            osi_Log0(afsd_logp, "CALL GiveUpCallback SUCCESS");
+
+        free(gucbp);
+    }
+    lock_ObtainMutex(&serverp->mx);
+}
+
+
+void
+cm_GiveUpCallback(cm_scache_t * scp)
+{
+    time_t now;
+
+    cm_HoldSCacheNoLock(scp);
+    now = osi_Time();
+
+    if (scp->cbExpires > 0 && (scp->cbServerp == NULL || now < scp->cbExpires)) {
+        lock_ObtainMutex(&scp->cbServerp->mx);
+        cm_AddFidToGiveUpCallBackList(scp->cbServerp, &scp->fid);
+        lock_ReleaseMutex(&scp->cbServerp->mx);
+
+        /* assume the callbacks were given up even if we fail */
+        cm_PutServer(scp->cbServerp);
+        scp->cbServerp = NULL;
+        scp->cbExpires = 0;
+    }
+    cm_ReleaseSCacheNoLock(scp);
+}
+#endif /* GIVE_UP_CALLBACKS */
+
+void 
+cm_GiveUpAllCallbacks(cm_server_t *tsp)
+{
+    long code;
+    cm_conn_t *connp;
+    struct rx_connection * rxconnp;
+
+    if (tsp->type == CM_SERVER_FILE) {
+        code = cm_ConnByServer(tsp, cm_rootUserp, &connp);
+        if (code == 0) {
+            rxconnp = cm_GetRxConn(connp);
+           code = RXAFS_GiveUpAllCallBacks(rxconnp);
+           rx_PutConnection(rxconnp);
+
+            lock_ObtainMutex(&tsp->mx);
+#ifdef GIVE_UP_CALLBACKS
+            cm_FreeGiveUpCallBackList(tsp);
+#endif /* GIVE_UP_CALLBACKS */
+            lock_ReleaseMutex(&tsp->mx);
+        }
+    }
+}
+
+void
+cm_GiveUpAllCallbacksAllServers(void)
+{
+    cm_server_t *tsp;
+
+    lock_ObtainWrite(&cm_serverLock);
+    for (tsp = cm_allServersp; tsp; tsp = tsp->allNextp) {
+        cm_GetServerNoLock(tsp);
+        lock_ReleaseWrite(&cm_serverLock);
+        cm_GiveUpAllCallbacks(tsp);
+        lock_ObtainWrite(&cm_serverLock);
+        cm_PutServerNoLock(tsp);
+    }
+    lock_ReleaseWrite(&cm_serverLock);
+}
+
+
index 013777e1c4f783ce6dea7191f68d850ecda00b4c..bb9c7350f47b0249321ad99821bd3ec67b65a71b 100644 (file)
@@ -68,4 +68,16 @@ extern osi_rwlock_t cm_callbackLock;
 
 extern void cm_CallbackNotifyChange(cm_scache_t *scp);
 
+#ifdef GIVE_UP_CALLBACKS
+extern void cm_GiveUpCallback(struct cm_scache *);
+
+extern void cm_GiveUpCallBacksToServer(cm_server_t * serverp);
+
+#define AFS_MAXCBRSCALL   16      /* max to return in a given call */
+#endif /* GIVE_UP_CALLBACKS */
+
+extern void cm_GiveUpAllCallbacks(cm_server_t *tsp);
+
+extern void cm_GiveUpAllCallbacksAllServers(void);
+
 #endif /*  _CM_CALLBACK_H_ENV__ */
index 644b472ea207afb8648a0754c8a370a8fdee330c..8381bbe9cea084e4eef64569fb6cf7be2abf95ea 100644 (file)
@@ -162,17 +162,23 @@ long cm_RecycleSCache(cm_scache_t *scp, afs_int32 flags)
     scp->bulkStatProgress = hzero;
     scp->waitCount = 0;
 
-    scp->fid.vnode = 0;
-    scp->fid.volume = 0;
-    scp->fid.unique = 0;
-    scp->fid.cell = 0;
-
+#ifdef GIVE_UP_CALLBACKS
     /* discard callback */
     if (scp->cbServerp) {
-       cm_PutServer(scp->cbServerp);
-       scp->cbServerp = NULL;
+        cm_GiveUpCallback(scp);
+    }
+#else /* GIVE_UP_CALLBACKS */
+    if (scp->cbServerp) {
+        cm_PutServer(scp->cbServerp);
+        scp->cbServerp = NULL;
     }
     scp->cbExpires = 0;
+#endif /* GIVE_UP_CALLBACKS */
+
+    scp->fid.vnode = 0;
+    scp->fid.volume = 0;
+    scp->fid.unique = 0;
+    scp->fid.cell = 0;
 
     /* remove from dnlc */
     cm_dnlcPurgedp(scp);
@@ -449,11 +455,33 @@ cm_ValidateSCache(void)
     return cm_dnlcValidate();
 }
 
+void
+cm_SuspendSCache(void)
+{
+    cm_scache_t * scp;
+
+    cm_GiveUpAllCallbacksAllServers();
+
+    lock_ObtainWrite(&cm_scacheLock);
+    for ( scp = cm_data.allSCachesp; scp;
+          scp = scp->allNextp ) {
+        if (scp->cbServerp) {
+            cm_PutServer(scp->cbServerp);
+            scp->cbServerp = NULL;
+        }
+        scp->cbExpires = 0;
+        scp->flags &= ~CM_SCACHEFLAG_CALLBACK;
+    }
+    lock_ReleaseWrite(&cm_scacheLock);
+}
+
 long
 cm_ShutdownSCache(void)
 {
     cm_scache_t * scp;
 
+    lock_ObtainWrite(&cm_scacheLock);
+
     for ( scp = cm_data.allSCachesp; scp;
           scp = scp->allNextp ) {
         if (scp->randomACLp) {
@@ -461,9 +489,20 @@ cm_ShutdownSCache(void)
             cm_FreeAllACLEnts(scp);
             lock_ReleaseMutex(&scp->mx);
         }
+
+        if (scp->cbServerp) {
+            cm_PutServer(scp->cbServerp);
+            scp->cbServerp = NULL;
+        }
+        scp->cbExpires = 0;
+        scp->flags &= ~CM_SCACHEFLAG_CALLBACK;
+
         lock_FinalizeMutex(&scp->mx);
         lock_FinalizeRWLock(&scp->bufCreateLock);
     }
+    lock_ReleaseWrite(&cm_scacheLock);
+
+    cm_GiveUpAllCallbacksAllServers();
 
     return cm_dnlcShutdown();
 }
index c7f6529dbfdf18a9fdec7d87f0f269f31312abd2..0137a1c941f0a94ea805bf25a42168351a334f34 100644 (file)
@@ -379,6 +379,8 @@ extern long cm_ValidateSCache(void);
 
 extern long cm_ShutdownSCache(void);
 
+extern void cm_SuspendSCache(void);
+
 extern long cm_RecycleSCache(cm_scache_t *scp, afs_int32 flags);
 
 extern void cm_RemoveSCacheFromHashTable(cm_scache_t *scp);
index 6354bc4bf48d1f77473fb56f07d42b4983ec356a..92f9012498f021e0710e3673ef5717321827640a 100644 (file)
@@ -236,6 +236,17 @@ void cm_CheckServers(long flags, cm_cell_t *cellp)
         if (doPing) 
            cm_PingServer(tsp);
 
+#ifdef GIVE_UP_CALLBACKS
+        /* if this is a file server and it is not currently down
+         * give up any callbacks we have queued 
+         */
+        if (isFS && !(tsp->flags & CM_SERVERFLAG_DOWN)) {
+            lock_ObtainMutex(&tsp->mx);
+            cm_GiveUpCallBacksToServer(tsp);
+            lock_ReleaseMutex(&tsp->mx);
+        }
+#endif /* GIVE_UP_CALLBACKS */
+
         /* also, run the GC function for connections on all of the
          * server's connections.
          */
@@ -387,6 +398,22 @@ cm_server_t *cm_NewServer(struct sockaddr_in *socketp, int type, cm_cell_t *cell
     return tsp;
 }
 
+cm_server_t *
+cm_FindServerByIP(afs_uint32 ipaddr, int type)
+{
+    cm_server_t *tsp;
+
+    lock_ObtainRead(&cm_serverLock);
+    for (tsp = cm_allServersp; tsp; tsp = tsp->allNextp) {
+        if (tsp->type == type &&
+            tsp->addr.sin_addr.S_un.S_addr == ipaddr)
+            break;
+    }
+    lock_ReleaseRead(&cm_serverLock);
+
+    return tsp;
+}
+
 /* find a server based on its properties */
 cm_server_t *cm_FindServer(struct sockaddr_in *addrp, int type)
 {
@@ -715,18 +742,77 @@ void cm_FreeServerList(cm_serverRef_t** list, afs_uint32 flags)
     lock_ReleaseWrite(&cm_serverLock);
 }
 
-cm_server_t *
-cm_FindServerByIP(afs_uint32 ipaddr)
+#ifdef GIVE_UP_CALLBACKS
+cm_server_gucb_t *cm_NewServerGUCBs(void) {
+    cm_server_gucb_t *gucbp;
+
+    gucbp = malloc(sizeof(*gucbp));
+    if (gucbp)
+        memset(gucbp, 0, sizeof(*gucbp));
+
+    return gucbp;
+}
+
+
+/* server mutex must be held */
+void cm_AddFidToGiveUpCallBackList(cm_server_t * serverp, cm_fid_t *fidp) {
+    cm_server_gucb_t ** gucbpp;
+
+    for ( gucbpp = &serverp->gucbs; *gucbpp; gucbpp = &(*gucbpp)->nextp ) {
+        if ((*gucbpp)->count < AFS_MAXCBRSCALL) {
+            (*gucbpp)->fids[(*gucbpp)->count] = *fidp;
+            (*gucbpp)->count++;
+            return;
+        }
+    }
+
+    /* if we get here all of the allocated pages are full */
+    (*gucbpp) = cm_NewServerGUCBs();
+    if (*gucbpp) {
+        (*gucbpp)->fids[0] = *fidp;
+        (*gucbpp)->count = 1;
+    }
+}
+
+/* server mutex must be held */
+void cm_RemoveFidFromGiveUpCallBackList(cm_server_t *serverp, cm_fid_t *fidp) {
+    cm_server_gucb_t *gucbp;
+    int i;
+
+    for ( gucbp = serverp->gucbs; gucbp; gucbp = gucbp->nextp ) {
+        for ( i=0; i < gucbp->count; i++ ) {
+            if (cm_FidCmp(&gucbp->fids[i], fidp) == 0) {
+                /* invalidate this entry.  we will skip over it later */
+                gucbp->fids[i].cell = 0;
+                break;
+            }
+        }
+    }
+}
+
+/* server mutex must be held */
+void cm_FreeGiveUpCallBackList(cm_server_t * serverp)
+{
+    cm_server_gucb_t *gucbp, *nextp;
+
+    for ( gucbp = serverp->gucbs, serverp->gucbs = NULL; gucbp; gucbp = nextp ) {
+        nextp = gucbp->nextp;
+        free(gucbp);
+    }
+}
+
+void cm_FreeAllGiveUpCallBackLists(void)
 {
     cm_server_t *tsp;
 
     lock_ObtainRead(&cm_serverLock);
     for (tsp = cm_allServersp; tsp; tsp = tsp->allNextp) {
-        if (tsp->addr.sin_addr.S_un.S_addr == ipaddr)
-            break;
+        if (tsp->type == CM_SERVER_FILE && tsp->gucbs != NULL) {
+            lock_ObtainMutex(&tsp->mx);
+            cm_FreeGiveUpCallBackList(tsp);
+            lock_ReleaseMutex(&tsp->mx);
+        }
     }
     lock_ReleaseRead(&cm_serverLock);
-
-    return tsp;
 }
-
+#endif /* GIVE_UP_CALLBACKS */
index 9190ac8b665ca091ea7639cbd867e4ea6a63cabf..202335557779cd0338e19d49c545eb13a6ad64a3 100644 (file)
@@ -24,6 +24,15 @@ typedef struct cm_server_vols {
     struct cm_server_vols *nextp;
 } cm_server_vols_t;
 
+#ifdef GIVE_UP_CALLBACKS
+#define AFS_MAXCBRSCALL 16
+typedef struct cm_server_gucb {
+    afs_uint32          count;
+    cm_fid_t            fids[AFS_MAXCBRSCALL];
+    struct cm_server_gucb * nextp;
+} cm_server_gucb_t;
+#endif /* GIVE_UP_CALLBACKS */
+
 /* pointed to by volumes and cells without holds; cm_serverLock is obtained
  * at the appropriate times to change the pointers to these servers.
  */
@@ -40,6 +49,9 @@ typedef struct cm_server {
     osi_mutex_t mx;
     unsigned short ipRank;             /* server priority */
     cm_server_vols_t *  vols;           /* by mx */
+#ifdef GIVE_UP_CALLBACKS
+    cm_server_gucb_t *  gucbs;          /* by mx */
+#endif /* GIVE_UP_CALLBACKS */
 } cm_server_t;
 
 enum repstate {srv_not_busy, srv_busy, srv_offline, srv_deleted};
@@ -125,6 +137,17 @@ extern void cm_SetServerNo64Bit(cm_server_t * serverp, int no64bit);
 
 extern void cm_SetServerNoInlineBulk(cm_server_t * serverp, int no);
 
-extern cm_server_t * cm_FindServerByIP(afs_uint32 addr);
+extern cm_server_t * cm_FindServerByIP(afs_uint32 addr, int type);
+
+#ifdef GIVE_UP_CALLBACKS
+extern cm_server_gucb_t *cm_NewServerGUCBs(void);
+
+extern void cm_AddFidToGiveUpCallBackList(cm_server_t * serverp, cm_fid_t *fidp);
+
+extern void cm_RemoveFidFromGiveUpCallBackList(cm_server_t *serverp, cm_fid_t *fidp);
+
+extern void cm_FreeGiveUpCallBackList(cm_server_t * serverp);
 
+extern void cm_FreeAllGiveUpCallBackLists(void);
+#endif /* GIVE_UP_CALLBACKS */
 #endif /*  __CM_SERVER_H_ENV__ */