/*
* 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
{
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 */
}
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.
*/
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);
&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
*/
{
cm_aclent_t *aclp;
cm_scache_t *ascp = 0;
-
+
if (cm_data.aclLRUp == NULL)
osi_panic("empty aclent LRU", __FILE__, __LINE__);
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 */
return 0;
}
-/*
+/*
* Initialize the cache to have an entries. Called during system startup.
*/
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);
}
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;
}
-/*
+/*
* 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).
}
-/*
+/*
* 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) {
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);
+}
+
+