viced: Release all hosts in h_Enumerate*
[openafs.git] / src / viced / host.c
index 7d12aa3..7cf9b76 100644 (file)
@@ -952,23 +952,18 @@ h_TossStuff_r(struct host *host)
 
 
 
-/* h_Enumerate: Calls (*proc)(host, held, param) for at least each host in the
+/* h_Enumerate: Calls (*proc)(host, param) for at least each host in the
  * system at the start of the enumeration (perhaps more).  Hosts may be deleted
  * (have delete flag set); ditto for clients.  refCount is always incremented
- * before (*proc) is called.  The param flags is passed to (*proc) as the
- * param flags, permitting (*proc) to stop the enumeration (BAIL).
+ * before (*proc) is called.
  *
- * Needed?  Why not always h_Hold_r and h_Release_r in (*proc), or even -never-
- * h_Hold_r or h_Release_r in (*proc)?
- *
- * **The proc should return 0 if the host should be released, 1 if it should
- * be held after enumeration.
+ * The return value of the proc is a set of flags. The proc should set
+ * H_ENUMERATE_BAIL(foo) if the enumeration of hosts should be stopped early.
  */
 void
-h_Enumerate(int (*proc) (struct host*, int, void *), void *param)
+h_Enumerate(int (*proc) (struct host*, void *), void *param)
 {
     struct host *host, **list;
-    int *flags;
     int i, count;
     int totalCount;
 
@@ -979,13 +974,7 @@ h_Enumerate(int (*proc) (struct host*, int, void *), void *param)
     }
     list = (struct host **)malloc(hostCount * sizeof(struct host *));
     if (!list) {
-       ViceLog(0, ("Failed malloc in h_Enumerate (list)\n"));
-       osi_Panic("Failed malloc in h_Enumerate (list)\n");
-    }
-    flags = (int *)malloc(hostCount * sizeof(int));
-    if (!flags) {
-       ViceLog(0, ("Failed malloc in h_Enumerate (flags)\n"));
-       osi_Panic("Failed malloc in h_Enumerate (flags)\n");
+       ViceLogThenPanic(0, ("Failed malloc in h_Enumerate (list)\n"));
     }
     for (totalCount = count = 0, host = hostList;
          host && totalCount < hostCount;
@@ -1005,43 +994,51 @@ h_Enumerate(int (*proc) (struct host*, int, void *), void *param)
     }
     H_UNLOCK;
     for (i = 0; i < count; i++) {
-       flags[i] = (*proc) (list[i], flags[i], param);
+       int flags;
+       flags = (*proc) (list[i], param);
        H_LOCK;
        h_Release_r(list[i]);
        H_UNLOCK;
        /* bail out of the enumeration early */
-       if (H_ENUMERATE_ISSET_BAIL(flags[i]))
+       if (H_ENUMERATE_ISSET_BAIL(flags)) {
            break;
+       } else if (flags) {
+           ViceLog(0, ("h_Enumerate got back invalid return value %d\n", flags));
+           ShutDownAndCore(PANIC);
+       }
+    }
+    if (i < count-1) {
+       /* we bailed out of enumerating hosts early; we still have holds on
+        * some of the hosts in 'list', so release them */
+       i++;
+       H_LOCK;
+       for ( ; i < count; i++) {
+           h_Release_r(list[i]);
+       }
+       H_UNLOCK;
     }
     free((void *)list);
-    free((void *)flags);
 }      /* h_Enumerate */
 
 
 /* h_Enumerate_r (revised):
- * Calls (*proc)(host, flags, param) for each host in hostList, starting
+ * Calls (*proc)(host, param) for each host in hostList, starting
  * at enumstart. Called only under H_LOCK.  Hosts may be deleted (have
  * delete flag set); ditto for clients.  refCount is always incremented
- * before (*proc) is called.  The param flags is passed to (*proc) as the
- * param flags, permitting (*proc) to stop the enumeration (BAIL).
- *
- * Needed?  Why not always h_Hold_r and h_Release_r in (*proc), or even -never-
- * h_Hold_r or h_Release_r in (*proc)?
+ * before (*proc) is called.
  *
  * @note Assumes that hostList is only prepended to, that a host is never
  *       inserted into the middle. Otherwise this would not be guaranteed to
  *       terminate.
  *
- * **The proc should return 0 if the host should be released, 1 if it should
- * be held after enumeration.
+ * The return value of the proc is a set of flags. The proc should set
+ * H_ENUMERATE_BAIL(foo) if the enumeration of hosts should be stopped early.
  */
 void
-h_Enumerate_r(int (*proc) (struct host *, int, void *),
+h_Enumerate_r(int (*proc) (struct host *, void *),
              struct host *enumstart, void *param)
 {
     struct host *host, *next;
-    int flags = 0;
-    int nflags = 0;
     int count;
     int origHostCount;
 
@@ -1080,7 +1077,7 @@ h_Enumerate_r(int (*proc) (struct host *, int, void *),
      * h_Release_r */
     origHostCount = hostCount;
 
-    for (count = 0, host = enumstart; host && count < origHostCount; host = next, flags = nflags, count++) {
+    for (count = 0, host = enumstart; host && count < origHostCount; host = next, count++) {
        next = host->next;
 
        /* find the next non-deleted host */
@@ -1092,14 +1089,21 @@ h_Enumerate_r(int (*proc) (struct host *, int, void *),
                ShutDownAndCore(PANIC);
            }
        }
-       if (next && !H_ENUMERATE_ISSET_BAIL(flags))
+       if (next)
            h_Hold_r(next);
 
        if (!(host->hostFlags & HOSTDELETED)) {
-           flags = (*proc) (host, flags, param);
+           int flags;
+           flags = (*proc) (host, param);
            if (H_ENUMERATE_ISSET_BAIL(flags)) {
                h_Release_r(host); /* this might free up the host */
+               if (next) {
+                   h_Release_r(next);
+               }
                break;
+           } else if (flags) {
+               ViceLog(0, ("h_Enumerate_r got back invalid return value %d\n", flags));
+               ShutDownAndCore(PANIC);
            }
        }
        h_Release_r(host); /* this might free up the host */
@@ -1146,8 +1150,7 @@ h_AddHostToUuidHashTable_r(struct afsUUID *uuid, struct host *host)
     /* insert into beginning of list for this bucket */
     chain = (struct h_UuidHashChain *)malloc(sizeof(struct h_UuidHashChain));
     if (!chain) {
-       ViceLog(0, ("Failed malloc in h_AddHostToUuidHashTable_r\n"));
-       osi_Panic("Failed malloc in h_AddHostToUuidHashTable_r\n");
+       ViceLogThenPanic(0, ("Failed malloc in h_AddHostToUuidHashTable_r\n"));
     }
     chain->hostPtr = host;
     chain->next = hostUuidHashTable[index];
@@ -1333,8 +1336,7 @@ createHostAddrHashChain_r(int index, afs_uint32 addr, afs_uint16 port, struct ho
     /* insert into beginning of list for this bucket */
     chain = (struct h_AddrHashChain *)malloc(sizeof(struct h_AddrHashChain));
     if (!chain) {
-       ViceLog(0, ("Failed malloc in h_AddHostToAddrHashTable_r\n"));
-       osi_Panic("Failed malloc in h_AddHostToAddrHashTable_r\n");
+       ViceLogThenPanic(0, ("Failed malloc in h_AddHostToAddrHashTable_r\n"));
     }
     chain->hostPtr = host;
     chain->next = hostAddrHashTable[index];
@@ -1554,8 +1556,7 @@ addInterfaceAddr_r(struct host *host, afs_uint32 addr, afs_uint16 port)
     interface = (struct Interface *)
        malloc(sizeof(struct Interface) + (sizeof(struct AddrPort) * number));
     if (!interface) {
-       ViceLog(0, ("Failed malloc in addInterfaceAddr_r\n"));
-       osi_Panic("Failed malloc in addInterfaceAddr_r\n");
+       ViceLogThenPanic(0, ("Failed malloc in addInterfaceAddr_r\n"));
     }
     interface->numberOfInterfaces = number + 1;
     interface->uuid = host->interface->uuid;
@@ -1747,8 +1748,7 @@ h_GetHost_r(struct rx_connection *tcon)
            ((code == 0) && (afs_uuid_equal(&interf.uuid, &nulluuid)))) {
            identP = (struct Identity *)malloc(sizeof(struct Identity));
            if (!identP) {
-               ViceLog(0, ("Failed malloc in h_GetHost_r\n"));
-               osi_Panic("Failed malloc in h_GetHost_r\n");
+               ViceLogThenPanic(0, ("Failed malloc in h_GetHost_r\n"));
            }
            identP->valid = 0;
            rx_SetSpecific(tcon, rxcon_ident_key, identP);
@@ -1789,8 +1789,7 @@ h_GetHost_r(struct rx_connection *tcon)
            interfValid = 1;
            identP = (struct Identity *)malloc(sizeof(struct Identity));
            if (!identP) {
-               ViceLog(0, ("Failed malloc in h_GetHost_r\n"));
-               osi_Panic("Failed malloc in h_GetHost_r\n");
+               ViceLogThenPanic(0, ("Failed malloc in h_GetHost_r\n"));
            }
            identP->valid = 1;
            identP->uuid = interf.uuid;
@@ -1978,8 +1977,7 @@ h_GetHost_r(struct rx_connection *tcon)
                    pident = 1;
 
                if (!identP) {
-                   ViceLog(0, ("Failed malloc in h_GetHost_r\n"));
-                   osi_Panic("Failed malloc in h_GetHost_r\n");
+                   ViceLogThenPanic(0, ("Failed malloc in h_GetHost_r\n"));
                }
                identP->valid = 0;
                if (!pident)
@@ -1997,8 +1995,7 @@ h_GetHost_r(struct rx_connection *tcon)
                    pident = 1;
 
                if (!identP) {
-                   ViceLog(0, ("Failed malloc in h_GetHost_r\n"));
-                   osi_Panic("Failed malloc in h_GetHost_r\n");
+                   ViceLogThenPanic(0, ("Failed malloc in h_GetHost_r\n"));
                }
                identP->valid = 1;
                interfValid = 1;
@@ -2262,8 +2259,7 @@ MapName_r(char *aname, char *acell, afs_int32 * aval)
            foreign = 1;        /* attempt cross-cell authentication */
            tname = (char *)malloc(PR_MAXNAMELEN);
            if (!tname) {
-               ViceLog(0, ("Failed malloc in MapName_r\n"));
-               osi_Panic("Failed malloc in MapName_r\n");
+               ViceLogThenPanic(0, ("Failed malloc in MapName_r\n"));
            }
            strcpy(tname, aname);
            tname[anamelen] = '@';
@@ -2663,6 +2659,14 @@ GetClient(struct rx_connection *tcon, struct client **cp)
        H_UNLOCK;
        return VICETOKENDEAD;
     }
+    if (client->deleted) {
+       ViceLog(0, ("GetClient: got deleted client, this should not happen! "
+                   "Connection will appear to have no rights; "
+                   "tcon %p sid %d epoch %d client %p host %s:%d viceid %d\n",
+                   tcon, (int)rxr_CidOf(tcon), (int)rxr_GetEpoch(tcon), client,
+                   afs_inet_ntoa_r(client->host->host, hoststr),
+                   (int)ntohs(client->host->port), (int)client->ViceId));
+    }
 
     client->refCount++;
     *cp = client;
@@ -2695,8 +2699,7 @@ h_UserName(struct client *client)
     lids.idlist_len = 1;
     lids.idlist_val = (afs_int32 *) malloc(1 * sizeof(afs_int32));
     if (!lids.idlist_val) {
-       ViceLog(0, ("Failed malloc in h_UserName\n"));
-       osi_Panic("Failed malloc in h_UserName\n");
+       ViceLogThenPanic(0, ("Failed malloc in h_UserName\n"));
     }
     lnames.namelist_len = 0;
     lnames.namelist_val = (prname *) 0;
@@ -2724,7 +2727,7 @@ h_PrintStats(void)
 
 
 static int
-h_PrintClient(struct host *host, int flags, void *rock)
+h_PrintClient(struct host *host, void *rock)
 {
     StreamHandle_t *file = (StreamHandle_t *)rock;
     struct client *client;
@@ -2739,11 +2742,11 @@ h_PrintClient(struct host *host, int flags, void *rock)
     LastCall = host->LastCall;
     if (host->hostFlags & HOSTDELETED) {
        H_UNLOCK;
-       return flags;
+       return 0;
     }
     strftime(tbuffer, sizeof(tbuffer), "%a %b %d %T %Y",
             localtime_r(&LastCall, &tm));
-    snprintf(tmpStr, sizeof tmpStr, "Host %s:%d down = %d, LastCall %s",
+    snprintf(tmpStr, sizeof tmpStr, "Host %s:%d down = %d, LastCall %s\n",
             afs_inet_ntoa_r(host->host, hoststr),
             ntohs(host->port), (host->hostFlags & VENUSDOWN),
             tbuffer);
@@ -2754,11 +2757,11 @@ h_PrintClient(struct host *host, int flags, void *rock)
            strftime(tbuffer, sizeof(tbuffer), "%a %b %d %T %Y",
                     localtime_r(&expTime, &tm));
            snprintf(tmpStr, sizeof tmpStr,
-                    "    user id=%d,  name=%s, sl=%s till %s",
+                    "    user id=%d,  name=%s, sl=%s till %s\n",
                     client->ViceId, h_UserName(client),
                     client->authClass ? "Authenticated"
                                       : "Not authenticated",
-                    client->authClass ? tbuffer : "No Limit\n");
+                    client->authClass ? tbuffer : "No Limit");
            (void)STREAM_WRITE(tmpStr, strlen(tmpStr), 1, file);
            snprintf(tmpStr, sizeof tmpStr, "      CPS-%d is [",
                         client->CPS.prlist_len);
@@ -2775,7 +2778,7 @@ h_PrintClient(struct host *host, int flags, void *rock)
        }
     }
     H_UNLOCK;
-    return flags;
+    return 0;
 
 }                              /*h_PrintClient */
 
@@ -2804,7 +2807,7 @@ h_PrintClients(void)
     now = FT_ApproxTime();
     strftime(tbuffer, sizeof(tbuffer), "%a %b %d %T %Y",
             localtime_r(&now, &tm));
-    snprintf(tmpStr, sizeof tmpStr, "List of active users at %s\n",
+    snprintf(tmpStr, sizeof tmpStr, "List of active users at %s\n\n",
             tbuffer);
     (void)STREAM_WRITE(tmpStr, strlen(tmpStr), 1, file);
     h_Enumerate(h_PrintClient, (char *)file);
@@ -2816,7 +2819,7 @@ h_PrintClients(void)
 
 
 static int
-h_DumpHost(struct host *host, int flags, void *rock)
+h_DumpHost(struct host *host, void *rock)
 {
     StreamHandle_t *file = (StreamHandle_t *)rock;
 
@@ -2855,7 +2858,7 @@ h_DumpHost(struct host *host, int flags, void *rock)
     (void)STREAM_WRITE(tmpStr, strlen(tmpStr), 1, file);
 
     H_UNLOCK;
-    return flags;
+    return 0;
 
 }                              /*h_DumpHost */
 
@@ -2878,7 +2881,7 @@ h_DumpHosts(void)
     now = FT_ApproxTime();
     strftime(tbuffer, sizeof(tbuffer), "%a %b %d %T %Y",
             localtime_r(&now, &tm));
-    snprintf(tmpStr, sizeof tmpStr, "List of active hosts at %s\n", tbuffer);
+    snprintf(tmpStr, sizeof tmpStr, "List of active hosts at %s\n\n", tbuffer);
     (void)STREAM_WRITE(tmpStr, strlen(tmpStr), 1, file);
     h_Enumerate(h_DumpHost, (char *)file);
     STREAM_REALLYCLOSE(file);
@@ -2894,10 +2897,10 @@ h_DumpHosts(void)
 static int h_stateFillHeader(struct host_state_header * hdr);
 static int h_stateCheckHeader(struct host_state_header * hdr);
 static int h_stateAllocMap(struct fs_dump_state * state);
-static int h_stateSaveHost(struct host * host, int flags, void *rock);
+static int h_stateSaveHost(struct host * host, void *rock);
 static int h_stateRestoreHost(struct fs_dump_state * state);
-static int h_stateRestoreIndex(struct host * h, int flags, void *rock);
-static int h_stateVerifyHost(struct host * h, int flags, void *rock);
+static int h_stateRestoreIndex(struct host * h, void *rock);
+static int h_stateVerifyHost(struct host * h, void *rock);
 static int h_stateVerifyAddrHash(struct fs_dump_state * state, struct host * h,
                                  afs_uint32 addr, afs_uint16 port, int valid);
 static int h_stateVerifyUuidHash(struct fs_dump_state * state, struct host * h);
@@ -2990,13 +2993,13 @@ h_stateRestoreIndices(struct fs_dump_state * state)
 }
 
 static int
-h_stateRestoreIndex(struct host * h, int flags, void *rock)
+h_stateRestoreIndex(struct host * h, void *rock)
 {
     struct fs_dump_state *state = (struct fs_dump_state *)rock;
     if (cb_OldToNew(state, h->cblist, &h->cblist)) {
-       return H_ENUMERATE_BAIL(flags);
+       return H_ENUMERATE_BAIL(0);
     }
-    return flags;
+    return 0;
 }
 
 int
@@ -3007,14 +3010,14 @@ h_stateVerify(struct fs_dump_state * state)
 }
 
 static int
-h_stateVerifyHost(struct host * h, int flags, void* rock)
+h_stateVerifyHost(struct host * h, void* rock)
 {
     struct fs_dump_state *state = (struct fs_dump_state *)rock;
     int i;
 
     if (h == NULL) {
        ViceLog(0, ("h_stateVerifyHost: error: NULL host pointer in linked list\n"));
-       return H_ENUMERATE_BAIL(flags);
+       return H_ENUMERATE_BAIL(0);
     }
 
     if (h->interface) {
@@ -3036,7 +3039,7 @@ h_stateVerifyHost(struct host * h, int flags, void* rock)
        state->bail = 1;
     }
 
-    return flags;
+    return 0;
 }
 
 /**
@@ -3214,7 +3217,7 @@ h_stateAllocMap(struct fs_dump_state * state)
 
 /* function called by h_Enumerate to save a host to disk */
 static int
-h_stateSaveHost(struct host * host, int flags, void* rock)
+h_stateSaveHost(struct host * host, void* rock)
 {
     struct fs_dump_state *state = (struct fs_dump_state *) rock;
     int if_len=0, hcps_len=0;
@@ -3280,9 +3283,9 @@ h_stateSaveHost(struct host * host, int flags, void* rock)
     if (hcps)
        free(hcps);
     if (state->bail) {
-       return H_ENUMERATE_BAIL(flags);
+       return H_ENUMERATE_BAIL(0);
     }
-    return flags;
+    return 0;
 }
 
 /* restores a host from disk */
@@ -3807,7 +3810,7 @@ CheckHost(struct host *host, int flags, void *rock)
 #endif
 
 int
-CheckHost_r(struct host *host, int flags, void *dummy)
+CheckHost_r(struct host *host, void *dummy)
 {
     struct client *client;
     struct rx_connection *cb_conn = NULL;
@@ -3818,7 +3821,7 @@ CheckHost_r(struct host *host, int flags, void *dummy)
     FS_STATE_RDLOCK;
     if (fs_state.mode == FS_MODE_SHUTDOWN) {
        FS_STATE_UNLOCK;
-       return H_ENUMERATE_BAIL(flags);
+       return H_ENUMERATE_BAIL(0);
     }
     FS_STATE_UNLOCK;
 #endif
@@ -3905,7 +3908,7 @@ CheckHost_r(struct host *host, int flags, void *dummy)
        }
        h_Unlock_r(host);
     }
-    return flags;
+    return 0;
 
 }                              /*CheckHost_r */
 
@@ -4033,16 +4036,14 @@ initInterfaceAddr_r(struct host *host, struct interfaceAddr *interf)
            malloc(sizeof(struct Interface) +
                   (sizeof(struct AddrPort) * (count - 1)));
        if (!interface) {
-           ViceLog(0, ("Failed malloc in initInterfaceAddr_r 1\n"));
-           osi_Panic("Failed malloc in initInterfaceAddr_r 1\n");
+           ViceLogThenPanic(0, ("Failed malloc in initInterfaceAddr_r 1\n"));
        }
        interface->numberOfInterfaces = count;
     } else {
        interface = (struct Interface *)
            malloc(sizeof(struct Interface) + (sizeof(struct AddrPort) * count));
        if (!interface) {
-           ViceLog(0, ("Failed malloc in initInterfaceAddr_r 2\n"));
-           osi_Panic("Failed malloc in initInterfaceAddr_r 2\n");
+           ViceLogThenPanic(0, ("Failed malloc in initInterfaceAddr_r 2\n"));
        }
        interface->numberOfInterfaces = count + 1;
        interface->interface[count].addr = myAddr;