Linux: Make keyring destructor remove all tokens
authorSimon Wilkinson <sxw@inf.ed.ac.uk>
Sat, 6 Mar 2010 00:13:06 +0000 (00:13 +0000)
committerDerrick Brashear <shadow@dementia.org>
Sat, 6 Mar 2010 14:43:10 +0000 (06:43 -0800)
The keyring destructor on Linux was only destroying the first
unixuser structure found for the PAG being destroyed. In environments
where each PAG contains tokens for multiple cells, this led to us
leaking unixuser structures, and eventually grinding to a hault due
to the length of the resulting hash chains (and some horrific
O(n-squared) performance in the PAG statistics code).

Add a utility function for the keyring destruction function to call
which will mark as deleted all unixuser structures for a particular
PAG, and use it.

Change-Id: I355465c43cc2cf9d70f613d6f97cd65552260157
Cc: Eric.Hagberg@morganstanley.com
Reviewed-on: http://gerrit.openafs.org/1524
Tested-by: Simon Wilkinson <sxw@inf.ed.ac.uk>
Reviewed-by: Derrick Brashear <shadow@dementia.org>

src/afs/LINUX/osi_groups.c
src/afs/afs_prototypes.h
src/afs/afs_user.c

index b1fc848..dfe2dca 100644 (file)
@@ -472,17 +472,13 @@ static int afs_pag_match(const struct key *key, const void *description)
 static void afs_pag_destroy(struct key *key)
 {
     afs_uint32 pag = key->payload.value;
-    struct unixuser *pu;
     int locked = ISAFS_GLOCK();
 
     if (!locked)
        AFS_GLOCK();
-    pu = afs_FindUser(pag, -1, READ_LOCK);
-    if (pu) {
-       pu->ct.EndTimestamp = 0;
-       pu->tokenTime = 0;
-       afs_PutUser(pu, READ_LOCK);
-    }
+
+    afs_MarkUserExpired(pag);
+
     if (!locked)
        AFS_GUNLOCK();
 }
index 4f3ac7d..8db9f00 100644 (file)
@@ -932,7 +932,7 @@ extern void afs_CheckTokenCache(void);
 extern void afs_ResetAccessCache(afs_int32 uid, int alock);
 extern void afs_ResetUserConns(register struct unixuser *auser);
 extern void afs_SetPrimary(register struct unixuser *au, register int aflag);
-
+extern void afs_MarkUserExpired(afs_int32 pag);
 
 /* afs_util.c */
 extern afs_int32 afs_strtoi_r(const char *str, char **endptr, afs_uint32 *ret);
index 7e04e7c..db9be5b 100644 (file)
@@ -562,6 +562,30 @@ afs_SetPrimary(register struct unixuser *au, register int aflag)
 }                              /*afs_SetPrimary */
 
 
+/**
+ * Mark all of the unixuser records held for a particular PAG as
+ * expired
+ *
+ * @param[in] pag
+ *     PAG to expire records for
+ */
+void
+afs_MarkUserExpired(afs_int32 pag) {
+    afs_int32 i;
+    struct unixuser *tu;
+
+    i = UHash(pag);
+    ObtainWriteLock(&afs_xuser, 9);
+    for (tu = afs_users[i]; tu; tu = tu->next) {
+       if (tu->uid == pag) {
+           tu->ct.EndTimestamp = 0;
+           tu->tokenTime = 0;
+       }
+    }
+    ReleaseWriteLock(&afs_xuser);
+}
+
+
 #if AFS_GCPAGS
 
 /*