From 1984f86fcfa094b7e7b2a2c37d8f3690b6e20aa3 Mon Sep 17 00:00:00 2001 From: Andrew Deason Date: Tue, 19 Jun 2012 14:42:23 -0500 Subject: [PATCH] viced: Clear all client CPS on FlushCPS Currently the fileserver only finds the first applicable 'client' structure (via h_ID2Client) for a FlushCPS operation, and invalidates the CPS for it. However, there may be many 'client' structures in memory for the given viceid, since we may have many connections for the same user (possibly from different hosts). So, modify FlushCPS to find all relevant client structures, and invalidate the CPS calculation on them. Reviewed-on: http://gerrit.openafs.org/7574 Tested-by: BuildBot Reviewed-by: Derrick Brashear (cherry picked from commit 387fe294f663abd9c92cd007869e2e9e8cc11d69) Change-Id: I45b278b59649526b62eb83353cfe31465e79c712 Reviewed-on: http://gerrit.openafs.org/9487 Reviewed-by: Andrew Deason Tested-by: BuildBot Reviewed-by: Stephan Wiesand --- src/viced/afsfileprocs.c | 38 +++++++++++++------------ src/viced/host.c | 61 +++++++++++++++++++++++++--------------- src/viced/host.h | 4 ++- 3 files changed, 62 insertions(+), 41 deletions(-) diff --git a/src/viced/afsfileprocs.c b/src/viced/afsfileprocs.c index 691a4ebda..8e2b07bbb 100644 --- a/src/viced/afsfileprocs.c +++ b/src/viced/afsfileprocs.c @@ -6552,6 +6552,25 @@ SRXAFS_GetCapabilities(struct rx_call * acall, Capabilities * capabilities) return code; } +/* client is held, but not locked */ +static int +FlushClientCPS(struct client *client, void *arock) +{ + ObtainWriteLock(&client->lock); + + client->prfail = 2; /* Means re-eval client's cps */ + + if ((client->ViceId != ANONYMOUSID) && client->CPS.prlist_val) { + free(client->CPS.prlist_val); + client->CPS.prlist_val = NULL; + client->CPS.prlist_len = 0; + } + + ReleaseWriteLock(&client->lock); + + return 0; +} + afs_int32 SRXAFS_FlushCPS(struct rx_call * acall, struct ViceIds * vids, struct IPAddrs * addrs, afs_int32 spare1, afs_int32 * spare2, @@ -6561,7 +6580,6 @@ SRXAFS_FlushCPS(struct rx_call * acall, struct ViceIds * vids, afs_int32 nids, naddrs; afs_int32 *vd, *addr; Error errorCode = 0; /* return code to caller */ - struct client *client = 0; ViceLog(1, ("SRXAFS_FlushCPS\n")); FS_LOCK; @@ -6584,23 +6602,7 @@ SRXAFS_FlushCPS(struct rx_call * acall, struct ViceIds * vids, for (i = 0; i < nids; i++, vd++) { if (!*vd) continue; - client = h_ID2Client(*vd); /* returns write locked and refCounted, or NULL */ - if (!client) - continue; - - client->prfail = 2; /* Means re-eval client's cps */ -#ifdef notdef - if (client->tcon) { - rx_SetRock(((struct rx_connection *)client->tcon), 0); - } -#endif - if ((client->ViceId != ANONYMOUSID) && client->CPS.prlist_val) { - free(client->CPS.prlist_val); - client->CPS.prlist_val = NULL; - client->CPS.prlist_len = 0; - } - ReleaseWriteLock(&client->lock); - PutClient(&client); + h_EnumerateClients(*vd, FlushClientCPS, NULL); } addr = addrs->IPAddrs_val; diff --git a/src/viced/host.c b/src/viced/host.c index b14a3c462..7ccaec81b 100644 --- a/src/viced/host.c +++ b/src/viced/host.c @@ -86,6 +86,13 @@ int rxcon_client_key; static struct rx_securityClass *sc = NULL; +/* arguments for PerHost_EnumerateClient enumeration */ +struct enumclient_args { + afs_int32 vid; + int (*proc)(struct client *client, void *rock); + void *rock; +}; + static void h_SetupCallbackConn_r(struct host * host); static int h_threadquota(int); @@ -2344,36 +2351,46 @@ MapName_r(char *aname, char *acell, afs_int32 * aval) /*MapName*/ -/* NOTE: this returns the client with a Write lock and a refCount */ -struct client * -h_ID2Client(afs_int32 vid) +static int +PerHost_EnumerateClient(struct host *host, void *arock) { + struct enumclient_args *args = arock; struct client *client; - struct host *host; - int count; + int code; - H_LOCK; - for (count = 0, host = hostList; host && count < hostCount; host = host->next, count++) { - if (host->hostFlags & HOSTDELETED) - continue; - for (client = host->FirstClient; client; client = client->next) { - if (!client->deleted && client->ViceId == vid) { - client->refCount++; - H_UNLOCK; - ObtainWriteLock(&client->lock); - return client; + for (client = host->FirstClient; client; client = client->next) { + if (!client->deleted && client->ViceId == args->vid) { + + client->refCount++; + H_UNLOCK; + + code = (*args->proc)(client, args->rock); + + H_LOCK; + h_ReleaseClient_r(client); + + if (code) { + return H_ENUMERATE_BAIL(0); } } } - if (count != hostCount) { - ViceLog(0, ("h_ID2Client found %d of %d hosts\n", count, hostCount)); - } else if (host != NULL) { - ViceLog(0, ("h_ID2Client found more than %d hosts\n", hostCount)); - ShutDownAndCore(PANIC); - } + return 0; +} + +void +h_EnumerateClients(afs_int32 vid, + int (*proc)(struct client *client, void *rock), + void *rock) +{ + struct enumclient_args args; + args.vid = vid; + args.proc = proc; + args.rock = rock; + + H_LOCK; + h_Enumerate_r(PerHost_EnumerateClient, hostList, &args); H_UNLOCK; - return NULL; } /* diff --git a/src/viced/host.h b/src/viced/host.h index 58b2b9342..fbe31284f 100644 --- a/src/viced/host.h +++ b/src/viced/host.h @@ -224,7 +224,9 @@ extern struct host *h_GetHost_r(struct rx_connection *tcon); extern struct client *h_FindClient_r(struct rx_connection *tcon); extern int h_ReleaseClient_r(struct client *client); extern void h_TossStuff_r(struct host *host); -extern struct client *h_ID2Client(afs_int32 vid); +extern void h_EnumerateClients(afs_int32 vid, + int (*proc)(struct client *client, void *rock), + void *arock); extern int GetClient(struct rx_connection *tcon, struct client **cp); extern int PutClient(struct client **cp); extern void h_PrintStats(void); -- 2.39.5