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 <buildbot@rampaginggeek.com>
Reviewed-by: Derrick Brashear <shadow@dementix.org>
(cherry picked from commit
387fe294f663abd9c92cd007869e2e9e8cc11d69)
Change-Id: I45b278b59649526b62eb83353cfe31465e79c712
Reviewed-on: http://gerrit.openafs.org/9487
Reviewed-by: Andrew Deason <adeason@sinenomine.net>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Stephan Wiesand <stephan.wiesand@desy.de>
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,
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;
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;
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);
/*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;
}
/*
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);