Windows: Record callback issued time
[openafs.git] / src / WINNT / afsd / cm_callback.c
index aef6777..1936698 100644 (file)
@@ -169,6 +169,7 @@ void cm_RevokeCallback(struct rx_call *callp, cm_cell_t * cellp, AFSFid *fidp)
     tfid.volume = fidp->Volume;
     tfid.vnode = fidp->Vnode;
     tfid.unique = fidp->Unique;
+    CM_FID_GEN_HASH(&tfid);
     hash = CM_SCACHE_HASH(&tfid);
 
     osi_Log3(afsd_logp, "RevokeCallback vol %u vn %u uniq %u",
@@ -197,14 +198,14 @@ void cm_RevokeCallback(struct rx_call *callp, cm_cell_t * cellp, AFSFid *fidp)
             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);
 
-            if (RDR_Initialized)
-                RDR_InvalidateObject(scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique,
-                                     scp->fid.hash, scp->fileType, AFS_INVALIDATE_CALLBACK);
-
             lock_ObtainWrite(&scp->rw);
             cm_DiscardSCache(scp);
             lock_ReleaseWrite(&scp->rw);
 
+            if (RDR_Initialized)
+                RDR_InvalidateObject(scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique,
+                                     scp->fid.hash, scp->fileType, AFS_INVALIDATE_CALLBACK);
+
             cm_CallbackNotifyChange(scp);
 
             lock_ObtainWrite(&cm_scacheLock);
@@ -225,6 +226,7 @@ cm_callbackDiscardROVolumeByFID(cm_fid_t *fidp)
         cm_PutVolume(volp);
         if (volp->cbExpiresRO) {
             volp->cbExpiresRO = 0;
+            volp->cbIssuedRO = 0;
             if (volp->cbServerpRO) {
                 cm_PutServer(volp->cbServerpRO);
                 volp->cbServerpRO = NULL;
@@ -522,7 +524,6 @@ extern osi_rwlock_t cm_aclLock;
 extern osi_rwlock_t buf_globalLock;
 extern osi_rwlock_t cm_cellLock;
 extern osi_rwlock_t cm_connLock;
-extern osi_rwlock_t cm_daemonLock;
 extern osi_rwlock_t cm_dnlcLock;
 extern osi_rwlock_t cm_scacheLock;
 extern osi_rwlock_t cm_serverLock;
@@ -557,7 +558,6 @@ static struct _ltable {
     {"cm_connLock",      (char*)&cm_connLock,           LOCKTYPE_RW},
     {"cm_userLock",      (char*)&cm_userLock,           LOCKTYPE_RW},
     {"cm_volumeLock",    (char*)&cm_volumeLock,         LOCKTYPE_RW},
-    {"cm_daemonLock",    (char*)&cm_daemonLock,         LOCKTYPE_RW},
     {"cm_dnlcLock",      (char*)&cm_dnlcLock,           LOCKTYPE_RW},
     {"cm_utilsLock",     (char*)&cm_utilsLock,          LOCKTYPE_RW},
     {"smb_globalLock",   (char*)&smb_globalLock,        LOCKTYPE_RW},
@@ -982,6 +982,8 @@ SRXAFSCB_InitCallBackState3(struct rx_call *callp, afsUUID* serverUuid)
     cm_cell_t* cellp = NULL;
     afs_uint32 hash;
     int discarded;
+    cm_fid_t discardFid;
+    afs_uint32 discardType;
     struct rx_connection *connp;
     struct rx_peer *peerp;
     unsigned long host = 0;
@@ -1072,6 +1074,8 @@ SRXAFSCB_InitCallBackState3(struct rx_call *callp, afsUUID* serverUuid)
                     if (cm_ServerEqual(scp->cbServerp, tsp)) {
                         osi_Log4(afsd_logp, "InitCallbackState3 Discarding SCache scp 0x%p vol %u vn %u uniq %u",
                                   scp, scp->fid.volume, scp->fid.vnode, scp->fid.unique);
+                        discardFid = scp->fid;
+                        discardType = scp->fileType;
                         cm_DiscardSCache(scp);
                         discarded = 1;
                     }
@@ -1080,8 +1084,8 @@ SRXAFSCB_InitCallBackState3(struct rx_call *callp, afsUUID* serverUuid)
                 if (discarded) {
                     cm_CallbackNotifyChange(scp);
                     if (RDR_Initialized)
-                        RDR_InvalidateObject(scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique,
-                                              scp->fid.hash, scp->fileType, AFS_INVALIDATE_EXPIRED);
+                        RDR_InvalidateObject(discardFid.cell, discardFid.volume, discardFid.vnode, discardFid.unique,
+                                             discardFid.hash, discardType, AFS_INVALIDATE_EXPIRED);
                 }
                 lock_ObtainWrite(&cm_scacheLock);
                 cm_ReleaseSCacheNoLock(scp);
@@ -1152,15 +1156,21 @@ GetCellCommon(afs_int32 a_cellnum, char **a_name, serverList *a_hosts)
     afs_int32 sn;
     cm_cell_t * cellp;
     cm_serverRef_t * serverRefp;
+    size_t len;
 
     cellp = cm_FindCellByID(a_cellnum, CM_FLAG_NOPROBE);
     if (!cellp) {
-        *a_name = strdup("");
+        *a_name = (char *)xdr_alloc(sizeof(char));
+        if (*a_name)
+            *a_name = '\0';
         return 0;
     }
 
     lock_ObtainRead(&cm_serverLock);
-    *a_name = strdup(cellp->name);
+    len = strlen(cellp->name)+1;
+    *a_name = (char *)xdr_alloc(len);
+    if (*a_name)
+        memcpy(*a_name, cellp->name, len);
 
     for ( sn = 0, serverRefp = cellp->vlServersp;
           sn < AFSMAXCELLHOSTS && serverRefp;
@@ -1403,6 +1413,7 @@ int SRXAFSCB_GetLocalCell(struct rx_call *callp, char **a_name)
     struct rx_peer *peerp;
     unsigned long host = 0;
     unsigned short port = 0;
+    size_t len;
 
     if (cm_shutdown)
         return 1;
@@ -1416,7 +1427,10 @@ int SRXAFSCB_GetLocalCell(struct rx_call *callp, char **a_name)
              ntohl(host), ntohs(port));
 
     if (cm_data.rootCellp) {
-        t_name = strdup(cm_data.rootCellp->name);
+        len = strlen(cm_data.rootCellp->name) + 1;
+        t_name = (char *)xdr_alloc(len);
+        if (t_name)
+            memcpy(t_name, cm_data.rootCellp->name, len);
     } else {
        t_name = (char *)xdr_alloc(1);
        t_name[0] = '\0';
@@ -1625,52 +1639,40 @@ void cm_StartCallbackGrantingCall(cm_scache_t *scp, cm_callbackRequest_t *cbrp)
  *
  * Called with scp write locked, so we can discard the callbacks easily with
  * this locking hierarchy.
+ *
+ * Performs cleanup of the stack allocated cm_callbackRequest_t object.
+ *
+ * Returns 0 on success and non-zero if the callback lost a race.
  */
-void cm_EndCallbackGrantingCall(cm_scache_t *scp, cm_callbackRequest_t *cbrp,
-                                AFSCallBack *cbp, AFSVolSync *volSyncp, long flags)
+int
+cm_EndCallbackGrantingCall(cm_scache_t *scp, cm_callbackRequest_t *cbrp,
+                           AFSCallBack *cbp, AFSVolSync *volSyncp, long flags)
 {
     cm_racingRevokes_t *revp;          /* where we are */
     cm_racingRevokes_t *nrevp;         /* where we'll be next */
-    int freeFlag;
+    int freeRacingRevokes;
+    int freeServer;
     cm_server_t * serverp = NULL;
-    int discardScp = 0, discardVolCB = 0;
+    int lostRace = 0;
 
     lock_ObtainWrite(&cm_callbackLock);
     if (flags & CM_CALLBACK_MAINTAINCOUNT) {
         osi_assertx(cm_activeCallbackGrantingCalls > 0,
                     "CM_CALLBACK_MAINTAINCOUNT && cm_activeCallbackGrantingCalls == 0");
+        freeServer = 0;
     }
     else {
         osi_assertx(cm_activeCallbackGrantingCalls-- > 0,
                     "!CM_CALLBACK_MAINTAINCOUNT && cm_activeCallbackGrantingCalls == 0");
+        freeServer = 1;
     }
     if (cm_activeCallbackGrantingCalls == 0)
-        freeFlag = 1;
+        freeRacingRevokes = 1;
     else
-        freeFlag = 0;
+        freeRacingRevokes = 0;
 
-    /* record the callback; we'll clear it below if we really lose it */
-    if (cbrp) {
-       if (scp) {
-            if (!cm_ServerEqual(scp->cbServerp, cbrp->serverp)) {
-                serverp = scp->cbServerp;
-                if (!freeFlag)
-                    cm_GetServer(cbrp->serverp);
-                scp->cbServerp = cbrp->serverp;
-            } else {
-                if (freeFlag)
-                    serverp = cbrp->serverp;
-            }
-            scp->cbExpires = cbrp->startTime + cbp->ExpirationTime;
-        } else {
-            if (freeFlag)
-                serverp = cbrp->serverp;
-        }
-        if (freeFlag)
-            cbrp->serverp = NULL;
-    }
-
-    /* a callback was actually revoked during our granting call, so
+    /*
+     * a callback was revoked during our granting call, so
      * run down the list of revoked fids, looking for ours.
      * If activeCallbackGrantingCalls is zero, free the elements, too.
      *
@@ -1699,36 +1701,46 @@ void cm_EndCallbackGrantingCall(cm_scache_t *scp, cm_callbackRequest_t *cbrp,
                       scp,
                       cbrp->callbackCount, revp->callbackCount,
                       cm_callbackCount);
-            discardScp = 1;
+            lostRace = 1;
             if ((scp->flags & CM_SCACHEFLAG_PURERO) &&
                  (revp->flags & CM_RACINGFLAG_ALL))
                 cm_callbackDiscardROVolumeByFID(&scp->fid);
         }
-        if (freeFlag)
+        if (freeRacingRevokes)
             free(revp);
     }
 
     /* if we freed the list, zap the pointer to it */
-    if (freeFlag)
+    if (freeRacingRevokes)
         cm_racingRevokesp = NULL;
-
     lock_ReleaseWrite(&cm_callbackLock);
 
-    if ( discardScp ) {
-        cm_DiscardSCache(scp);
-        lock_ReleaseWrite(&scp->rw);
-        cm_CallbackNotifyChange(scp);
-        if (RDR_Initialized)
-            RDR_InvalidateObject(scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique,
-                                 scp->fid.hash, scp->fileType, AFS_INVALIDATE_CALLBACK);
-        lock_ObtainWrite(&scp->rw);
-    } else {
-        if (scp && scp->flags & CM_SCACHEFLAG_PURERO) {
+    /* record the callback if we didn't lose it */
+    if (!lostRace && scp) {
+        if (cbrp) {
+            if (!cm_ServerEqual(scp->cbServerp, cbrp->serverp)) {
+                serverp = scp->cbServerp;
+                scp->cbServerp = cbrp->serverp;
+                if (freeServer) {
+                    cbrp->serverp = NULL;
+                } else {
+                    cm_GetServer(scp->cbServerp);
+                }
+            } else if (freeServer) {
+                serverp = cbrp->serverp;
+                cbrp->serverp = NULL;
+            }
+            scp->cbExpires = cbrp->startTime + cbp->ExpirationTime;
+            scp->cbIssued = time(NULL);
+        }
+
+        if (scp->flags & CM_SCACHEFLAG_PURERO) {
             cm_volume_t * volp = cm_GetVolumeByFID(&scp->fid);
             if (volp) {
                 if (volSyncp) {
                     lock_ObtainWrite(&cm_scacheLock);
                     volp->cbExpiresRO = scp->cbExpires;
+                    volp->cbIssuedRO = scp->cbIssued;
                     volp->creationDateRO = volSyncp->spare1;
                     if (volp->cbServerpRO != scp->cbServerp) {
                         if (volp->cbServerpRO)
@@ -1742,12 +1754,27 @@ void cm_EndCallbackGrantingCall(cm_scache_t *scp, cm_callbackRequest_t *cbrp,
             }
         }
     }
+    else
+    {
+        /*
+         * No need to discard the cm_scache object or notify the
+         * afs redirector or smb client about a change if we did lose
+         * the race.  That was done when the callback was processed in
+         * cm_RevokeCallback().
+         */
+        if (cbrp && freeServer) {
+            serverp = cbrp->serverp;
+            cbrp->serverp = NULL;
+        }
+    }
 
     if ( serverp ) {
         lock_ObtainWrite(&cm_serverLock);
         cm_FreeServer(serverp);
         lock_ReleaseWrite(&cm_serverLock);
     }
+
+    return lostRace;
 }
 
 /* if flags is 1, we want to force the code to make one call, anyway.
@@ -1834,7 +1861,7 @@ long cm_GetCallback(cm_scache_t *scp, struct cm_user *userp,
                                      &afsStatus, &callback, &volSync);
             rx_PutConnection(rxconnp);
 
-        } while (cm_Analyze(connp, userp, reqp, &sfid, &volSync, NULL,
+        } while (cm_Analyze(connp, userp, reqp, &sfid, 0, &volSync, NULL,
                             &cbr, code));
         code = cm_MapRPCError(code, reqp);
         if (code)
@@ -1846,8 +1873,9 @@ long cm_GetCallback(cm_scache_t *scp, struct cm_user *userp,
 
         lock_ObtainWrite(&scp->rw);
         if (code == 0) {
-            cm_EndCallbackGrantingCall(scp, &cbr, &callback, &volSync, 0);
-            cm_MergeStatus(NULL, scp, &afsStatus, &volSync, userp, reqp, 0);
+            int lostRace = cm_EndCallbackGrantingCall(scp, &cbr, &callback, &volSync, 0);
+            if (!lostRace)
+                cm_MergeStatus(NULL, scp, &afsStatus, &volSync, userp, reqp, 0);
         } else {
             cm_EndCallbackGrantingCall(NULL, &cbr, NULL, NULL, 0);
             InterlockedDecrement(&scp->activeRPCs);
@@ -1985,6 +2013,7 @@ void cm_CheckCBExpiration(void)
                 {
                     lock_ObtainWrite(&scp->rw);
                     scp->cbExpires = volp->cbExpiresRO;
+                    scp->cbIssued = volp->cbIssuedRO;
                     if (volp->cbServerpRO != scp->cbServerp) {
                         if (scp->cbServerp)
                             cm_PutServer(scp->cbServerp);
@@ -2020,7 +2049,7 @@ void cm_CheckCBExpiration(void)
 
             if (RDR_Initialized)
                 RDR_InvalidateObject(scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique,
-                                      scp->fid.hash, scp->fileType, AFS_INVALIDATE_EXPIRED);
+                                     scp->fid.hash, scp->fileType, AFS_INVALIDATE_EXPIRED);
 
             cm_CallbackNotifyChange(scp);
 
@@ -2047,7 +2076,7 @@ cm_GiveUpAllCallbacks(cm_server_t *tsp, afs_int32 markDown)
 
     if ((tsp->type == CM_SERVER_FILE) && !(tsp->flags & CM_SERVERFLAG_DOWN))
     {
-        code = cm_ConnByServer(tsp, cm_rootUserp, &connp);
+        code = cm_ConnByServer(tsp, cm_rootUserp, FALSE, &connp);
         if (code == 0) {
             rxconnp = cm_GetRxConn(connp);
             rx_SetConnDeadTime(rxconnp, 10);
@@ -2142,7 +2171,7 @@ cm_GiveUpAllCallbacksAllServersMulti(afs_int32 markDown)
         lock_ReleaseRead(&cm_serverLock);
 
         serversp[nconns] = tsp;
-        code = cm_ConnByServer(tsp, cm_rootUserp, &conns[nconns]);
+        code = cm_ConnByServer(tsp, cm_rootUserp, FALSE, &conns[nconns]);
         if (code) {
             lock_ObtainRead(&cm_serverLock);
             cm_PutServerNoLock(tsp);