From d9410aba89c5a257635fa33dbd78db2c0cb32ac8 Mon Sep 17 00:00:00 2001 From: Simon Wilkinson Date: Sat, 6 Mar 2010 00:13:06 +0000 Subject: [PATCH] Linux: Make keyring destructor remove all tokens 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 Reviewed-by: Derrick Brashear --- src/afs/LINUX/osi_groups.c | 10 +++------- src/afs/afs_prototypes.h | 2 +- src/afs/afs_user.c | 24 ++++++++++++++++++++++++ 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/afs/LINUX/osi_groups.c b/src/afs/LINUX/osi_groups.c index b1fc848fb..dfe2dcafe 100644 --- a/src/afs/LINUX/osi_groups.c +++ b/src/afs/LINUX/osi_groups.c @@ -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(); } diff --git a/src/afs/afs_prototypes.h b/src/afs/afs_prototypes.h index 4f3ac7db4..8db9f00f7 100644 --- a/src/afs/afs_prototypes.h +++ b/src/afs/afs_prototypes.h @@ -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); diff --git a/src/afs/afs_user.c b/src/afs/afs_user.c index 7e04e7c22..db9be5b15 100644 --- a/src/afs/afs_user.c +++ b/src/afs/afs_user.c @@ -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 /* -- 2.39.5