windows-readonly-volume-callbacks-20071109
authorJeffrey Altman <jaltman@secure-endpoints.com>
Sat, 10 Nov 2007 00:14:26 +0000 (00:14 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Sat, 10 Nov 2007 00:14:26 +0000 (00:14 +0000)
A .readonly volume callback applies to the entire volume.  Track it
in the cm_volume_t cbExpiresRO field and apply it to all cm_scache_t
objects with valid callbacks that are associated with that volume upon
each daemon callback check.  This will prevent premature callback
expiration.

Also, attempt to automatically refresh the callbacks every 30 minutes
by obtaining a callback on the volume root.  This value is configurable
with the "daemonCheckVolCBInterval" registry value.

Change from osi_Time() to time() for expiration values in order to
permit conversion to human readable values in cmdebug.

src/WINNT/afsd/cm_callback.c
src/WINNT/afsd/cm_daemon.c
src/WINNT/afsd/cm_scache.c
src/WINNT/afsd/cm_volume.c
src/WINNT/afsd/cm_volume.h

index d6d9e83..866f8d2 100644 (file)
@@ -263,6 +263,11 @@ void cm_RevokeVolumeCallback(struct rx_call *callp, cm_cell_t *cellp, AFSFid *fi
                 cm_CallbackNotifyChange(scp);
                 lock_ObtainWrite(&cm_scacheLock);
                 cm_ReleaseSCacheNoLock(scp);
+
+                if (scp->flags & CM_SCACHEFLAG_PURERO && scp->volp) {
+                    scp->volp->cbExpiresRO = 0;
+                }
+                
             }
         }      /* search one hash bucket */
     }  /* search all hash buckets */
@@ -480,6 +485,10 @@ SRXAFSCB_InitCallBackState(struct rx_call *callp)
                     cm_CallbackNotifyChange(scp);
                 lock_ObtainWrite(&cm_scacheLock);
                 cm_ReleaseSCacheNoLock(scp);
+
+                if (discarded && (scp->flags & CM_SCACHEFLAG_PURERO) && scp->volp && scp->volp->cbExpiresRO != 0)
+                    scp->volp->cbExpiresRO = 0;
+
             }  /* search one hash bucket */
        }       /* search all hash buckets */
        
@@ -737,7 +746,10 @@ SRXAFSCB_GetCE(struct rx_call *callp, long index, AFSDBCacheEntry *cep)
     cep->Length = scp->length.LowPart;
     cep->DataVersion = scp->dataVersion;
     cep->callback = afs_data_pointer_to_int32(scp->cbServerp);
-    cep->cbExpires = scp->cbExpires;
+    if (scp->flags & CM_SCACHEFLAG_PURERO && scp->volp)
+        cep->cbExpires = scp->volp->cbExpiresRO;
+    else
+        cep->cbExpires = scp->cbExpires;
     cep->refCount = scp->refCount;
     cep->opens = scp->openReads;
     cep->writers = scp->openWrites;
@@ -848,7 +860,10 @@ SRXAFSCB_GetCE64(struct rx_call *callp, long index, AFSDBCacheEntry64 *cep)
 #endif
     cep->DataVersion = scp->dataVersion;
     cep->callback = afs_data_pointer_to_int32(scp->cbServerp);
-    cep->cbExpires = scp->cbExpires;
+    if (scp->flags & CM_SCACHEFLAG_PURERO && scp->volp)
+        cep->cbExpires = scp->volp->cbExpiresRO;
+    else
+        cep->cbExpires = scp->cbExpires;
     cep->refCount = scp->refCount;
     cep->opens = scp->openReads;
     cep->writers = scp->openWrites;
@@ -1525,7 +1540,7 @@ void cm_StartCallbackGrantingCall(cm_scache_t *scp, cm_callbackRequest_t *cbrp)
     lock_ObtainWrite(&cm_callbackLock);
     cbrp->callbackCount = cm_callbackCount;
     cm_activeCallbackGrantingCalls++;
-    cbrp->startTime = osi_Time();
+    cbrp->startTime = time(NULL);
     cbrp->serverp = NULL;
     lock_ReleaseWrite(&cm_callbackLock);
 }
@@ -1543,7 +1558,7 @@ void cm_EndCallbackGrantingCall(cm_scache_t *scp, cm_callbackRequest_t *cbrp,
     cm_racingRevokes_t *nrevp;         /* where we'll be next */
     int freeFlag;
     cm_server_t * serverp = NULL;
-    int discardScp = 0;
+    int discardScp = 0, discardVolCB = 0;
 
     lock_ObtainWrite(&cm_callbackLock);
     if (flags & CM_CALLBACK_MAINTAINCOUNT) {
@@ -1572,6 +1587,8 @@ void cm_EndCallbackGrantingCall(cm_scache_t *scp, cm_callbackRequest_t *cbrp,
                     serverp = cbrp->serverp;
             }
             scp->cbExpires = cbrp->startTime + cbp->ExpirationTime;
+            if (scp->flags & CM_SCACHEFLAG_PURERO && scp->volp)
+                scp->volp->cbExpiresRO = scp->cbExpires;
         } else {
             if (freeFlag)
                 serverp = cbrp->serverp;
@@ -1609,6 +1626,10 @@ void cm_EndCallbackGrantingCall(cm_scache_t *scp, cm_callbackRequest_t *cbrp,
                       cbrp->callbackCount, revp->callbackCount,
                       cm_callbackCount);
             discardScp = 1;
+
+            if ((scp->flags & CM_SCACHEFLAG_PURERO) && scp->volp && 
+                (revp->flags & (CM_RACINGFLAG_CANCELVOL | CM_RACINGFLAG_CANCELALL)))
+                scp->volp->cbExpiresRO = 0;
         }
         if (freeFlag) 
             free(revp);
@@ -1820,6 +1841,11 @@ void cm_CheckCBExpiration(void)
     for (i=0; i<cm_data.scacheHashTableSize; i++) {
         for (scp = cm_data.scacheHashTablep[i]; scp; scp=scp->nextp) {
             downTime = 0;
+            if (scp->flags & CM_SCACHEFLAG_PURERO && scp->volp) {
+                if (scp->volp->cbExpiresRO > scp->cbExpires && scp->cbExpires > 0)
+                    scp->cbExpires = scp->volp->cbExpiresRO;
+            }
+
             if (scp->cbServerp && scp->cbExpires > 0 && now > scp->cbExpires && 
                  (cm_CBServersUp(scp, &downTime) || downTime == 0 || downTime >= scp->cbExpires)) 
             {
index 15aaad1..5e47a7f 100644 (file)
@@ -30,6 +30,7 @@ long cm_daemonCheckDownInterval  = 180;
 long cm_daemonCheckUpInterval    = 240;
 long cm_daemonCheckVolInterval   = 3600;
 long cm_daemonCheckCBInterval    = 60;
+long cm_daemonCheckVolCBInterval = 1800;
 long cm_daemonCheckLockInterval  = 60;
 long cm_daemonTokenCheckInterval = 180;
 long cm_daemonCheckOfflineVolInterval = 600;
@@ -269,6 +270,13 @@ cm_DaemonCheckInit(void)
     afsi_log("daemonCheckCBInterval is %d", cm_daemonCheckCBInterval);
 
     dummyLen = sizeof(DWORD);
+    code = RegQueryValueEx(parmKey, "daemonCheckVolCBInterval", NULL, NULL,
+                           (BYTE *) &dummy, &dummyLen);
+    if (code == ERROR_SUCCESS)
+       cm_daemonCheckVolCBInterval = dummy;
+    afsi_log("daemonCheckVolCBInterval is %d", cm_daemonCheckVolCBInterval);
+
+    dummyLen = sizeof(DWORD);
     code = RegQueryValueEx(parmKey, "daemonCheckLockInterval", NULL, NULL,
                            (BYTE *) &dummy, &dummyLen);
     if (code == ERROR_SUCCESS)
@@ -299,6 +307,7 @@ void cm_Daemon(long parm)
     time_t lastLockCheck;
     time_t lastVolCheck;
     time_t lastCBExpirationCheck;
+    time_t lastVolCBRenewalCheck;
     time_t lastDownServerCheck;
     time_t lastUpServerCheck;
     time_t lastTokenCacheCheck;
@@ -338,6 +347,7 @@ void cm_Daemon(long parm)
     now = osi_Time();
     lastVolCheck = now - cm_daemonCheckVolInterval/2 + (rand() % cm_daemonCheckVolInterval);
     lastCBExpirationCheck = now - cm_daemonCheckCBInterval/2 + (rand() % cm_daemonCheckCBInterval);
+    lastVolCBRenewalCheck = now - cm_daemonCheckVolCBInterval/2 + (rand() % cm_daemonCheckVolCBInterval);
     lastLockCheck = now - cm_daemonCheckLockInterval/2 + (rand() % cm_daemonCheckLockInterval);
     lastDownServerCheck = now - cm_daemonCheckDownInterval/2 + (rand() % cm_daemonCheckDownInterval);
     lastUpServerCheck = now - cm_daemonCheckUpInterval/2 + (rand() % cm_daemonCheckUpInterval);
@@ -396,6 +406,12 @@ void cm_Daemon(long parm)
            now = osi_Time();
         }
 
+        if (now > lastVolCBRenewalCheck + cm_daemonCheckVolCBInterval) {
+            lastVolCBRenewalCheck = now;
+            cm_VolumeRenewROCallbacks();
+            now = osi_Time();
+        }
+
         if (now > lastBusyVolCheck + cm_daemonCheckOfflineVolInterval) {
             lastVolCheck = now;
             cm_CheckOfflineVolumes();
index 0a19d82..9b6ed5e 100644 (file)
@@ -496,8 +496,14 @@ cm_SuspendSCache(void)
 
     lock_ObtainWrite(&cm_scacheLock);
     for ( scp = cm_data.allSCachesp; scp; scp = scp->allNextp ) {
-        if (scp->cbServerp)
+        if (scp->cbServerp) {
+            if (scp->flags & CM_SCACHEFLAG_PURERO && scp->volp) {
+                if (scp->volp->cbExpiresRO == scp->cbExpires) {
+                    scp->volp->cbExpiresRO = now+1;
+                }
+            }
             scp->cbExpires = now+1;
+        }
     }
     lock_ReleaseWrite(&cm_scacheLock);
 }
index b3d46f8..3ee4812 100644 (file)
@@ -73,7 +73,7 @@ cm_ShutdownVolume(void)
             cm_VolumeStatusNotification(volp, volp->ro.ID, volp->ro.state, vl_alldown);
         if (volp->bk.ID)
             cm_VolumeStatusNotification(volp, volp->bk.ID, volp->bk.state, vl_alldown);
-
+        volp->cbExpiresRO = 0;
         lock_FinalizeMutex(&volp->mx);
     }
 
@@ -114,6 +114,7 @@ void cm_InitVolume(int newFile, long maxVols)
                     cm_VolumeStatusNotification(volp, volp->ro.ID, vl_alldown, volp->ro.state);
                 if (volp->bk.ID)
                     cm_VolumeStatusNotification(volp, volp->bk.ID, vl_alldown, volp->bk.state);
+                volp->cbExpiresRO = 0;
             }
         }
         osi_EndOnce(&once);
@@ -764,6 +765,7 @@ long cm_GetVolumeByName(struct cm_cell *cellp, char *volumeNamep,
         volp->rw.state = volp->ro.state = volp->bk.state = vl_unknown;
         volp->rw.nextp = volp->ro.nextp = volp->bk.nextp = NULL;
         volp->rw.flags = volp->ro.flags = volp->bk.flags = 0;
+        volp->cbExpiresRO = 0;
         cm_AddVolumeToNameHashTable(volp);
         lock_ReleaseWrite(&cm_volumeLock);
     }
@@ -1494,3 +1496,38 @@ enum volstatus cm_GetVolumeStatus(cm_volume_t *volp, afs_uint32 volID)
     }
 }
 
+
+void 
+cm_VolumeRenewROCallbacks(void)
+{
+    cm_volume_t * volp;
+
+
+    lock_ObtainRead(&cm_volumeLock);
+    for (volp = cm_data.allVolumesp; volp; volp=volp->allNextp) {
+        if ( volp->cbExpiresRO > 0) {
+            cm_req_t      req;
+            cm_fid_t      fid;
+            cm_scache_t * scp;
+
+            fid.cell = volp->cellp->cellID;
+            fid.volume = volp->ro.ID;
+            fid.vnode = 1;
+            fid.unique = 1;
+
+            cm_InitReq(&req);
+
+            if (cm_GetSCache(&fid, &scp, cm_rootUserp, &req) == 0) {
+                lock_ReleaseRead(&cm_volumeLock);
+                lock_ObtainMutex(&scp->mx);
+                cm_GetCallback(scp, cm_rootUserp, &req, 1);
+                lock_ReleaseMutex(&scp->mx);
+                cm_ReleaseSCache(scp);
+                lock_ObtainRead(&cm_volumeLock);
+            }
+        }
+    }
+    lock_ReleaseRead(&cm_volumeLock);
+}
+
+
index d6f1497..2626970 100644 (file)
@@ -39,6 +39,7 @@ typedef struct cm_volume {
     osi_mutex_t mx;
     afs_uint32 flags;                  /* by mx */
     afs_uint32 refCount;               /* by cm_volumeLock */
+    time_t cbExpiresRO;                 /* latest RO expiration time; by cm_scacheLock */
 } cm_volume_t;
 
 #define CM_VOLUMEFLAG_RESET       1    /* reload this info on next use */
@@ -119,4 +120,6 @@ extern void cm_UpdateVolumeStatus(cm_volume_t *volp, afs_uint32 volID);
 extern void cm_VolumeStatusNotification(cm_volume_t * volp, afs_uint32 volID, enum volstatus old, enum volstatus new);
 
 extern enum volstatus cm_GetVolumeStatus(cm_volume_t *volp, afs_uint32 volID);
+
+extern void cm_VolumeRenewROCallbacks(void);
 #endif /*  __CM_VOLUME_H_ENV__ */