Windows: restructure cm_ResetACLCache locking
[openafs.git] / src / WINNT / afsd / cm_aclent.c
index 7a14e26..65e3563 100644 (file)
@@ -1,24 +1,26 @@
 /*
  * 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
  */
 
+#include <afsconfig.h>
 #include <afs/param.h>
+#include <roken.h>
+
 #include <afs/stds.h>
 
 #include <windows.h>
 #include <stdlib.h>
 #include <string.h>
-#include <malloc.h>
 
 #include "afsd.h"
 #include <osisleep.h>
 
-/* 
+/*
  * This next lock controls access to all cm_aclent structures in the system,
  * in either the free list or in the LRU queue.  A read lock prevents someone
  * from modifying the list(s), and a write lock is required for modifying
@@ -33,19 +35,19 @@ static void CleanupACLEnt(cm_aclent_t * aclp)
 {
     cm_aclent_t *taclp;
     cm_aclent_t **laclpp;
-        
+
     if (aclp->backp) {
         if (aclp->backp->randomACLp) {
-            /* 
-             * Remove the entry from the vnode's list 
+            /*
+             * Remove the entry from the vnode's list
              */
-            lock_AssertMutex(&aclp->backp->mx);
+            lock_AssertWrite(&aclp->backp->rw);
             laclpp = &aclp->backp->randomACLp;
             for (taclp = *laclpp; taclp; laclpp = &taclp->nextp, taclp = *laclpp) {
-                if (taclp == aclp) 
+                if (taclp == aclp)
                     break;
             }
-            if (!taclp) 
+            if (!taclp)
                 osi_panic("CleanupACLEnt race", __FILE__, __LINE__);
             *laclpp = aclp->nextp;                     /* remove from vnode list */
         }
@@ -62,7 +64,7 @@ static void CleanupACLEnt(cm_aclent_t * aclp)
     aclp->tgtLifetime = 0;
 }
 
-/* 
+/*
  * Get an acl cache entry for a particular user and file, or return that it doesn't exist.
  * Called with the scp locked.
  */
@@ -73,12 +75,12 @@ long cm_FindACLCache(cm_scache_t *scp, cm_user_t *userp, afs_uint32 *rightsp)
 
     lock_ObtainWrite(&cm_aclLock);
     *rightsp = 0;   /* get a new acl from server if we don't find a
-                     * current entry 
+                     * current entry
                      */
 
     for (aclp = scp->randomACLp; aclp; aclp = aclp->nextp) {
         if (aclp->userp == userp) {
-            if (aclp->tgtLifetime && aclp->tgtLifetime <= osi_Time()) {
+            if (aclp->tgtLifetime && aclp->tgtLifetime <= time(NULL)) {
                 /* ticket expired */
                 osi_QRemoveHT((osi_queue_t **) &cm_data.aclLRUp, (osi_queue_t **) &cm_data.aclLRUEndp, &aclp->q);
                 CleanupACLEnt(aclp);
@@ -97,16 +99,16 @@ long cm_FindACLCache(cm_scache_t *scp, cm_user_t *userp, afs_uint32 *rightsp)
                               &aclp->q);
                }
                 retval = 0;     /* success */
-            }               
+            }
             break;
         }
     }
 
     lock_ReleaseWrite(&cm_aclLock);
     return retval;
-}       
+}
 
-/* 
+/*
  * This function returns a free (not in the LRU queue) acl cache entry.
  * It must be called with the cm_aclLock lock held
  */
@@ -114,7 +116,7 @@ static cm_aclent_t *GetFreeACLEnt(cm_scache_t * scp)
 {
     cm_aclent_t *aclp;
     cm_scache_t *ascp = 0;
-       
+
     if (cm_data.aclLRUp == NULL)
         osi_panic("empty aclent LRU", __FILE__, __LINE__);
 
@@ -127,41 +129,41 @@ static cm_aclent_t *GetFreeACLEnt(cm_scache_t * scp)
     if (aclp->backp && scp != aclp->backp) {
         ascp = aclp->backp;
         lock_ReleaseWrite(&cm_aclLock);
-        lock_ObtainMutex(&ascp->mx);
+        lock_ObtainWrite(&ascp->rw);
         lock_ObtainWrite(&cm_aclLock);
     }
     CleanupACLEnt(aclp);
 
     if (ascp)
-        lock_ReleaseMutex(&ascp->mx);
+        lock_ReleaseWrite(&ascp->rw);
     return aclp;
 }
 
 
-/* 
- * Add rights to an acl cache entry.  Do the right thing if not present, 
+/*
+ * Add rights to an acl cache entry.  Do the right thing if not present,
  * including digging up an entry from the LRU queue.
  *
  * The scp must be locked when this function is called.
  */
 long cm_AddACLCache(cm_scache_t *scp, cm_user_t *userp, afs_uint32 rights)
 {
-    register struct cm_aclent *aclp;
+    struct cm_aclent *aclp;
 
     lock_ObtainWrite(&cm_aclLock);
     for (aclp = scp->randomACLp; aclp; aclp = aclp->nextp) {
         if (aclp->userp == userp) {
             aclp->randomAccess = rights;
-            if (aclp->tgtLifetime == 0) 
+            if (aclp->tgtLifetime == 0)
                 aclp->tgtLifetime = cm_TGTLifeTime(pag);
             lock_ReleaseWrite(&cm_aclLock);
             return 0;
         }
     }
 
-    /* 
-     * Didn't find the dude we're looking for, so take someone from the LRUQ 
-     * and  reuse. But first try the free list and see if there's already 
+    /*
+     * Didn't find the dude we're looking for, so take someone from the LRUQ
+     * and  reuse. But first try the free list and see if there's already
      * someone there.
      */
     aclp = GetFreeACLEnt(scp);          /* can't fail, panics instead */
@@ -248,7 +250,7 @@ long cm_ValidateACLCache(void)
     return 0;
 }
 
-/* 
+/*
  * Initialize the cache to have an entries.  Called during system startup.
  */
 long cm_InitACLCache(int newFile, long size)
@@ -258,7 +260,7 @@ long cm_InitACLCache(int newFile, long size)
     static osi_once_t once;
 
     if (osi_Once(&once)) {
-        lock_InitializeRWLock(&cm_aclLock, "cm_aclLock");
+        lock_InitializeRWLock(&cm_aclLock, "cm_aclLock", LOCK_HIERARCHY_ACL_GLOBAL);
         osi_EndOnce(&once);
     }
 
@@ -268,8 +270,8 @@ long cm_InitACLCache(int newFile, long size)
         aclp = (cm_aclent_t *) cm_data.aclBaseAddress;
         memset(aclp, 0, size * sizeof(cm_aclent_t));
 
-        /* 
-         * Put all of these guys on the LRU queue 
+        /*
+         * Put all of these guys on the LRU queue
          */
         for (i = 0; i < size; i++) {
             aclp->magic = CM_ACLENT_MAGIC;
@@ -289,7 +291,7 @@ long cm_InitACLCache(int newFile, long size)
 }
 
 
-/* 
+/*
  * Free all associated acl entries.  We actually just clear the back pointer
  * since the acl entries are already in the free list.  The scp must be locked
  * or completely unreferenced (such as when called while recycling the scp).
@@ -315,16 +317,18 @@ void cm_FreeAllACLEnts(cm_scache_t *scp)
 }
 
 
-/* 
+/*
  * Invalidate all ACL entries for particular user on this particular vnode.
  *
- * The scp must be locked.
+ * The scp must not be locked.
  */
 void cm_InvalidateACLUser(cm_scache_t *scp, cm_user_t *userp)
 {
     cm_aclent_t *aclp;
     cm_aclent_t **laclpp;
+    int found = 0;
 
+    lock_ObtainWrite(&scp->rw);
     lock_ObtainWrite(&cm_aclLock);
     laclpp = &scp->randomACLp;
     for (aclp = *laclpp; aclp; laclpp = &aclp->nextp, aclp = *laclpp) {
@@ -333,8 +337,38 @@ void cm_InvalidateACLUser(cm_scache_t *scp, cm_user_t *userp)
             cm_ReleaseUser(aclp->userp);
             aclp->userp = NULL;
             aclp->backp = (struct cm_scache *) 0;
+            found = 1;
             break;
         }
     }
     lock_ReleaseWrite(&cm_aclLock);
+    lock_ReleaseWrite(&scp->rw);
 }
+
+/*
+ * Invalidate ACL info for a user that has just        obtained or lost tokens.
+ */
+void
+cm_ResetACLCache(cm_cell_t *cellp, cm_user_t *userp)
+{
+    cm_scache_t *scp, *nextScp;
+    afs_uint32 hash;
+
+    lock_ObtainRead(&cm_scacheLock);
+    for (hash=0; hash < cm_data.scacheHashTableSize; hash++) {
+        for (scp=cm_data.scacheHashTablep[hash]; scp; scp=nextScp) {
+            nextScp = scp->nextp;
+            if (cellp == NULL ||
+                scp->fid.cell == cellp->cellID) {
+                cm_HoldSCacheNoLock(scp);
+                lock_ReleaseRead(&cm_scacheLock);
+                cm_InvalidateACLUser(scp, userp);
+                lock_ObtainRead(&cm_scacheLock);
+                cm_ReleaseSCacheNoLock(scp);
+            }
+        }
+    }
+    lock_ReleaseRead(&cm_scacheLock);
+}
+
+