Windows: Move file server lock releases to daemon
authorJeffrey Altman <jaltman@your-file-system.com>
Sun, 10 Jul 2011 23:19:17 +0000 (00:19 +0100)
committerJeffrey Altman <jaltman@openafs.org>
Mon, 11 Jul 2011 07:57:08 +0000 (00:57 -0700)
Create a new lock daemon thread which performs regular
cm_LockCheck() calls.  If a lock is deleted check the cm_scache_t
to see if the matching file server lock should be dropped.   If yes,
drop it.

This effectively caches file server locks for two seconds after
they are released to provide a chance for subsequent local lock
requests on the same file to avoid a file server RPC.  It also
ensures that windows processes do not thrash the file server and
force callback breaks.

Change-Id: I1c452e231ff282d9b45026aed1b02ab0c5932a77
Reviewed-on: http://gerrit.openafs.org/4964
Reviewed-by: Jeffrey Altman <jaltman@openafs.org>
Tested-by: Jeffrey Altman <jaltman@openafs.org>

src/WINNT/afsd/cm_daemon.c
src/WINNT/afsd/cm_vnodeops.c

index aadfc90..97cddd6 100644 (file)
@@ -35,7 +35,7 @@ long cm_daemonCheckUpInterval    = 240;
 long cm_daemonCheckVolInterval   = 3600;
 long cm_daemonCheckCBInterval    = 60;
 long cm_daemonCheckVolCBInterval = 0;
-long cm_daemonCheckLockInterval  = 60;
+long cm_daemonCheckLockInterval  = 2;
 long cm_daemonTokenCheckInterval = 180;
 long cm_daemonCheckOfflineVolInterval = 600;
 long cm_daemonPerformanceTuningInterval = 0;
@@ -56,6 +56,7 @@ static int cm_nDaemons = 0;
 static time_t lastIPAddrChange = 0;
 
 static EVENT_HANDLE cm_Daemon_ShutdownEvent = NULL;
+static EVENT_HANDLE cm_LockDaemon_ShutdownEvent = NULL;
 static EVENT_HANDLE cm_IPAddrDaemon_ShutdownEvent = NULL;
 static EVENT_HANDLE cm_BkgDaemon_ShutdownEvent[CM_MAX_DAEMONS] =
        {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
@@ -360,11 +361,46 @@ cm_DaemonCheckInit(void)
         cm_PerformanceTuningInit();
 }
 
+/* periodic lock check daemon */
+void cm_LockDaemon(long parm)
+{
+    time_t now;
+    time_t lastLockCheck;
+    char * name = "cm_LockDaemon_ShutdownEvent";
+
+    cm_LockDaemon_ShutdownEvent = thrd_CreateEvent(NULL, FALSE, FALSE, name);
+    if ( GetLastError() == ERROR_ALREADY_EXISTS )
+        afsi_log("Event Object Already Exists: %s", name);
+
+    now = osi_Time();
+    lastLockCheck = now - cm_daemonCheckLockInterval/2 + (rand() % cm_daemonCheckLockInterval);
+
+    while (daemon_ShutdownFlag == 0) {
+        if (powerStateSuspended) {
+            Sleep(1000);
+            continue;
+        }
+
+        now = osi_Time();
+
+        if (now > lastLockCheck + cm_daemonCheckLockInterval &&
+            daemon_ShutdownFlag == 0 &&
+            powerStateSuspended == 0) {
+            lastLockCheck = now;
+            cm_CheckLocks();
+            if (daemon_ShutdownFlag == 1)
+                break;
+        }
+
+        thrd_Sleep(1000);              /* sleep 1 second */
+    }
+    thrd_SetEvent(cm_LockDaemon_ShutdownEvent);
+}
+
 /* periodic check daemon */
 void cm_Daemon(long parm)
 {
     time_t now;
-    time_t lastLockCheck;
     time_t lastVolCheck;
     time_t lastCBExpirationCheck;
     time_t lastVolCBRenewalCheck;
@@ -420,7 +456,6 @@ void cm_Daemon(long parm)
     lastCBExpirationCheck = now - cm_daemonCheckCBInterval/2 + (rand() % cm_daemonCheckCBInterval);
     if (cm_daemonCheckVolCBInterval)
         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);
     lastTokenCacheCheck = now - cm_daemonTokenCheckInterval/2 + (rand() % cm_daemonTokenCheckInterval);
@@ -568,16 +603,6 @@ void cm_Daemon(long parm)
            now = osi_Time();
         }
 
-        if (now > lastLockCheck + cm_daemonCheckLockInterval &&
-            daemon_ShutdownFlag == 0 &&
-            powerStateSuspended == 0) {
-            lastLockCheck = now;
-            cm_CheckLocks();
-            if (daemon_ShutdownFlag == 1)
-                break;
-           now = osi_Time();
-        }
-
         if (now > lastTokenCacheCheck + cm_daemonTokenCheckInterval &&
             daemon_ShutdownFlag == 0 &&
             powerStateSuspended == 0) {
@@ -640,6 +665,9 @@ void cm_DaemonShutdown(void)
     if (cm_Daemon_ShutdownEvent)
         code = thrd_WaitForSingleObject_Event(cm_Daemon_ShutdownEvent, INFINITE);
 
+    if (cm_LockDaemon_ShutdownEvent)
+        code = thrd_WaitForSingleObject_Event(cm_LockDaemon_ShutdownEvent, INFINITE);
+
     for ( i=0; i<cm_nDaemons; i++) {
         if (cm_BkgDaemon_ShutdownEvent[i])
             code = thrd_WaitForSingleObject_Event(cm_BkgDaemon_ShutdownEvent[i], INFINITE);
@@ -675,6 +703,11 @@ void cm_InitDaemon(int nDaemons)
         osi_assertx(phandle != NULL, "cm_Daemon thread creation failure");
         thrd_CloseHandle(phandle);
 
+        phandle = thrd_Create((SecurityAttrib) 0, 0,
+                               (ThreadFunc) cm_LockDaemon, 0, 0, &pid, "cm_LockDaemon");
+        osi_assertx(phandle != NULL, "cm_LockDaemon thread creation failure");
+        thrd_CloseHandle(phandle);
+
        for(i=0; i < cm_nDaemons; i++) {
             phandle = thrd_Create((SecurityAttrib) 0, 0,
                                    (ThreadFunc) cm_BkgDaemon, (LPVOID)(LONG_PTR)i, 0, &pid,
index 7f234de..6fcc938 100644 (file)
@@ -5082,12 +5082,6 @@ long cm_UnlockByKey(cm_scache_t * scp,
 
             fileLock->flags |= CM_FILELOCK_FLAG_DELETED;
 
-            cm_ReleaseUser(fileLock->userp);
-            cm_ReleaseSCacheNoLock(scp);
-
-            fileLock->userp = NULL;
-            fileLock->scp = NULL;
-
             n_unlocks++;
         }
     }
@@ -5104,8 +5098,6 @@ long cm_UnlockByKey(cm_scache_t * scp,
 
     osi_Log1(afsd_logp, "cm_UnlockByKey done with %d locks", n_unlocks);
 
-    code = cm_IntUnlock(scp, userp, reqp);
-
     osi_Log1(afsd_logp, "cm_UnlockByKey code 0x%x", code);
     osi_Log4(afsd_logp, "   Leaving scp with excl[%d], shared[%d], client[%d], serverLock[%d]",
              scp->exclusiveLocks, scp->sharedLocks, scp->clientLocks,
@@ -5218,19 +5210,8 @@ long cm_Unlock(cm_scache_t *scp,
     }
 
     fileLock->flags |= CM_FILELOCK_FLAG_DELETED;
-    if (userp != NULL) {
-        cm_ReleaseUser(fileLock->userp);
-    } else {
-        userp = fileLock->userp;
-        release_userp = TRUE;
-    }
-    fileLock->userp = NULL;
-    cm_ReleaseSCacheNoLock(scp);
-    fileLock->scp = NULL;
     lock_ReleaseWrite(&cm_scacheLock);
 
-    code = cm_IntUnlock(scp, userp, reqp);
-
     if (release_userp) {
         cm_ReleaseUser(userp);
         release_userp = FALSE;
@@ -5311,6 +5292,19 @@ void cm_CheckLocks()
        code = -1;
 
         if (IS_LOCK_DELETED(fileLock)) {
+            cm_user_t *userp = fileLock->userp;
+            cm_scache_t *scp = fileLock->scp;
+            fileLock->userp = NULL;
+            fileLock->scp = NULL;
+
+            lock_ReleaseWrite(&cm_scacheLock);
+            lock_ObtainWrite(&scp->rw);
+            code = cm_IntUnlock(scp, userp, &req);
+            lock_ReleaseWrite(&scp->rw);
+
+            cm_ReleaseUser(fileLock->userp);
+            lock_ObtainWrite(&cm_scacheLock);
+            cm_ReleaseSCacheNoLock(scp);
 
             osi_QRemove(&cm_allFileLocks, q);
             cm_PutFileLock(fileLock);