viced: Clear all client CPS on FlushCPS
authorAndrew Deason <adeason@sinenomine.net>
Tue, 19 Jun 2012 19:42:23 +0000 (14:42 -0500)
committerDerrick Brashear <shadow@dementix.org>
Wed, 27 Jun 2012 12:38:35 +0000 (05:38 -0700)
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.

Change-Id: I46532984cc470f41c83fb8c686766e4a4d49edd0
Reviewed-on: http://gerrit.openafs.org/7574
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Derrick Brashear <shadow@dementix.org>

src/viced/afsfileprocs.c
src/viced/host.c
src/viced/host.h

index f343dd6..e0a27e4 100644 (file)
@@ -5616,6 +5616,25 @@ SRXAFS_GetCapabilities(struct rx_call * acall, Capabilities * capabilities)
     return 0;
 }
 
+/* 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,
@@ -5625,7 +5644,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;
@@ -5648,23 +5666,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;
index 2d80f43..6eadd5b 100644 (file)
@@ -73,6 +73,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);
 
@@ -2226,36 +2233,46 @@ MapName_r(char *uname, 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;
 }
 
 static int
index e056074..d67f11b 100644 (file)
@@ -210,7 +210,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);