viced-avoid-tying-up-all-threads-20070730
[openafs.git] / src / viced / host.c
index ece9271..13aeb0f 100644 (file)
@@ -55,6 +55,7 @@ RCSID
 #include <afs/prs_fs.h>
 #include <afs/auth.h>
 #include <afs/afsutil.h>
+#include <afs/com_err.h>
 #include <rx/rx.h>
 #include <afs/cellconfig.h>
 #include <stdlib.h>
@@ -81,6 +82,7 @@ extern struct afsconf_dir *confDir;   /* config dir object */
 extern int lwps;               /* the max number of server threads */
 extern afsUUID FS_HostUUID;
 
+afsUUID nulluuid;
 int CEs = 0;                   /* active clients */
 int CEBlocks = 0;              /* number of blocks of CEs */
 struct client *CEFree = 0;     /* first free client */
@@ -286,31 +288,27 @@ hpr_Initialize(struct ubik_client **uclient)
 
     tdir = afsconf_Open(AFSDIR_SERVER_ETC_DIRPATH);
     if (!tdir) {
-       fprintf(stderr,
-               "libprot: Could not open configuration directory: %s.\n",
-               AFSDIR_SERVER_ETC_DIRPATH);
-      return -1;
+       ViceLog(0, ("hpr_Initialize: Could not open configuration directory: %s", AFSDIR_SERVER_ETC_DIRPATH));
+       return -1;
     }
     
     code = afsconf_GetLocalCell(tdir, cellstr, sizeof(cellstr));
     if (code) {
-       fprintf(stderr,
-               "libprot: Could not get local cell. [%d]\n", code);
+       ViceLog(0, ("hpr_Initialize: Could not get local cell. [%d]", code));
        afsconf_Close(tdir);
        return code;
     }
     
     code = afsconf_GetCellInfo(tdir, cellstr, "afsprot", &info);
     if (code) {
-       fprintf(stderr, "libprot: Could not locate cell %s in %s/%s\n",
-               cellstr, confDir, AFSDIR_CELLSERVDB_FILE);
+       ViceLog(0, ("hpr_Initialize: Could not locate cell %s in %s/%s", cellstr, confDir, AFSDIR_CELLSERVDB_FILE));
        afsconf_Close(tdir);
        return code;
     }
     
     code = rx_Init(0);
     if (code) {
-        fprintf(stderr, "libprot:  Could not initialize rx.\n");
+       ViceLog(0, ("hpr_Initialize: Could not initialize rx."));
        afsconf_Close(tdir);
         return code;
     }
@@ -325,9 +323,7 @@ hpr_Initialize(struct ubik_client **uclient)
     if ((afsconf_GetLatestKey(tdir, 0, 0) == 0)) {
         code = afsconf_ClientAuthSecure(tdir, &sc[2], &scIndex);
         if (code)
-            fprintf(stderr,
-                    "libprot: clientauthsecure returns %d %s"
-                    " (so trying noauth)\n", code, error_message(code));
+           ViceLog(0, ("hpr_Initialize: clientauthsecure returns %d %s (so trying noauth)", code, afs_error_message(code)));
         if (code)
             scIndex = 0;        /* use noauth */
         if (scIndex != 2)
@@ -346,9 +342,7 @@ hpr_Initialize(struct ubik_client **uclient)
                 /* this is a kerberos ticket, set scIndex accordingly */
                 scIndex = 2;
             else {
-                fprintf(stderr,
-                        "libprot: funny kvno (%d) in ticket, proceeding\n",
-                        ttoken.kvno);
+                ViceLog(0, ("hpr_Initialize: funny kvno (%d) in ticket, proceeding", ttoken.kvno));
                 scIndex = 2;
             }
             sc[2] =
@@ -360,8 +354,7 @@ hpr_Initialize(struct ubik_client **uclient)
     if ((scIndex == 0) && (sc[0] == 0))
         sc[0] = rxnull_NewClientSecurityObject();
     if ((scIndex == 0))
-        com_err("fileserver", code,
-                "Could not get afs tokens, running unauthenticated.");
+       ViceLog(0, ("hpr_Initialize: Could not get afs tokens, running unauthenticated. [%d]", code));
     
     memset(serverconns, 0, sizeof(serverconns));        /* terminate list!!! */
     for (i = 0; i < info.numServers; i++) {
@@ -373,7 +366,7 @@ hpr_Initialize(struct ubik_client **uclient)
 
     code = ubik_ClientInit(serverconns, uclient);
     if (code) {
-        com_err("fileserver", code, "ubik client init failed.");
+       ViceLog(0, ("hpr_Initialize: ubik client init failed. [%d]", code));
     }
     afsconf_Close(tdir);
     code = rxs_Release(sc[scIndex]);
@@ -1132,8 +1125,11 @@ h_Enumerate_r(int (*proc) (), struct host *enumstart, char *param)
        held = (*proc) (host, held, param);
        if (!H_ENUMERATE_ISSET_HELD(held))
            h_Release_r(host); /* this might free up the host */
-       if (H_ENUMERATE_ISSET_BAIL(held))
+       if (H_ENUMERATE_ISSET_BAIL(held)) {
+           if (!H_ENUMERATE_ISSET_HELD(nheld))
+               h_Release_r(next); /* this might free up the host */
            break;
+       }
     }
 }                              /*h_Enumerate_r */
 
@@ -1303,6 +1299,24 @@ removeInterfaceAddr_r(struct host *host, afs_uint32 addr, afs_uint16 port)
     return 0;
 }
 
+int 
+h_threadquota(int waiting) 
+{
+    if (lwps > 64) {
+       if (waiting > 5)
+           return 1;
+    } else if (lwps > 32) {
+       if (waiting > 4)
+           return 1;
+    } else if (lwps > 16) {
+       if (waiting > 3)
+           return 1;
+    } else {
+       if (waiting > 2)
+           return 1;
+    }
+    return 0;
+}
 
 /* Host is returned held */
 struct host *
@@ -1339,8 +1353,12 @@ h_GetHost_r(struct rx_connection *tcon)
         * structure for this address. Verify that the identity
         * of the caller matches the identity in the host structure.
         */
+       if ((host->hostFlags & HWHO_INPROGRESS) && 
+           h_threadquota(host->lock.num_waiting))
+           return 0;
        h_Lock_r(host);
        if (!(host->hostFlags & ALTADDR)) {
+           host->hostFlags &= ~HWHO_INPROGRESS;
            /* Another thread is doing initialization */
            h_Unlock_r(host);
            if (!held)
@@ -1362,7 +1380,8 @@ h_GetHost_r(struct rx_connection *tcon)
        rx_PutConnection(cb_conn);
        cb_conn=NULL;
        H_LOCK;
-       if (code == RXGEN_OPCODE) {
+       if ((code == RXGEN_OPCODE) || 
+           (afs_uuid_equal(&interf.uuid, &nulluuid))) {
            identP = (struct Identity *)malloc(sizeof(struct Identity));
            if (!identP) {
                ViceLog(0, ("Failed malloc in h_GetHost_r\n"));
@@ -1380,6 +1399,7 @@ h_GetHost_r(struct rx_connection *tcon)
                         afs_inet_ntoa_r(host->host, hoststr),
                         ntohs(host->port)));
                host->hostFlags |= HOSTDELETED;
+               host->hostFlags &= ~HWHO_INPROGRESS;
                h_Unlock_r(host);
                if (!held)
                    h_Release_r(host);
@@ -1405,6 +1425,7 @@ h_GetHost_r(struct rx_connection *tcon)
                        ("Host %s:%d has changed its identity, deleting.\n",
                         afs_inet_ntoa_r(host->host, hoststr), host->port));
                host->hostFlags |= HOSTDELETED;
+               host->hostFlags &= ~HWHO_INPROGRESS;
                h_Unlock_r(host);
                if (!held)
                    h_Release_r(host);
@@ -1424,6 +1445,7 @@ h_GetHost_r(struct rx_connection *tcon)
        else
            host->hostFlags &= ~(HERRORTRANS);
        host->hostFlags |= ALTADDR;
+       host->hostFlags &= ~HWHO_INPROGRESS;
        h_Unlock_r(host);
     } else if (host) {
        if (!(host->hostFlags & ALTADDR)) {
@@ -1433,6 +1455,7 @@ h_GetHost_r(struct rx_connection *tcon)
                     afs_inet_ntoa_r(host->host, hoststr),
                     ntohs(host->port)));
            h_Lock_r(host);
+           host->hostFlags &= ~HWHO_INPROGRESS;
            h_Unlock_r(host);
            if (!held)
                h_Release_r(host);
@@ -1465,6 +1488,7 @@ h_GetHost_r(struct rx_connection *tcon)
 
            /* The host in the cache is not the host for this connection */
            host->hostFlags |= HOSTDELETED;
+           host->hostFlags &= ~HWHO_INPROGRESS;
            h_Unlock_r(host);
            if (!held)
                h_Release_r(host);
@@ -1485,7 +1509,8 @@ h_GetHost_r(struct rx_connection *tcon)
            rx_PutConnection(cb_conn);
            cb_conn=NULL;
            H_LOCK;
-           if (code == RXGEN_OPCODE) {
+           if ((code == RXGEN_OPCODE) || 
+               afs_uuid_equal(&interf.uuid, &nulluuid)) {
                if (!identP)
                    identP =
                        (struct Identity *)malloc(sizeof(struct Identity));
@@ -1541,6 +1566,7 @@ h_GetHost_r(struct rx_connection *tcon)
                    if (!(oheld = h_Held_r(oldHost)))
                        h_Hold_r(oldHost);
                    h_Lock_r(oldHost);
+                   oldHost->hostFlags |= HWHO_INPROGRESS;
 
                     if (oldHost->interface) {
                        int code2;
@@ -1631,6 +1657,7 @@ h_GetHost_r(struct rx_connection *tcon)
                        }
                    }
                    host->hostFlags |= HOSTDELETED;
+                   host->hostFlags &= ~HWHO_INPROGRESS;
                    h_Unlock_r(host);
                    /* release host because it was allocated by h_Alloc_r */
                    h_Release_r(host);
@@ -1677,6 +1704,7 @@ h_GetHost_r(struct rx_connection *tcon)
        else
            host->hostFlags &= ~(HERRORTRANS);
        host->hostFlags |= ALTADDR;     /* host structure initialization complete */
+       host->hostFlags &= ~HWHO_INPROGRESS;
        h_Unlock_r(host);
     }
     if (caps.Capabilities_val)
@@ -1696,6 +1724,7 @@ int  num_lrealms = -1;
 void
 h_InitHostPackage()
 {
+    memset(&nulluuid, 0, sizeof(afsUUID));
     afsconf_GetLocalCell(confDir, localcellname, PR_MAXNAMELEN);
     if (num_lrealms == -1) {
        int i;
@@ -1704,7 +1733,7 @@ h_InitHostPackage()
                break;
        }
 
-       if (i=0) {
+       if (i == 0) {
            ViceLog(0,
                    ("afs_krb_get_lrealm failed, using %s.\n",
                     localcellname));
@@ -1926,6 +1955,9 @@ h_FindClient_r(struct rx_connection *tcon)
     if (!client) { /* loop */
        host = h_GetHost_r(tcon);       /* Returns it h_Held */
 
+       if (!host) 
+           return 0;
+
     retryfirstclient:
        /* First try to find the client structure */
        for (client = host->FirstClient; client; client = client->next) {
@@ -2031,7 +2063,7 @@ h_FindClient_r(struct rx_connection *tcon)
            if (created) {
                ViceLog(0, ("FindClient: stillborn client %x(%x); conn %x (host %s:%d) had client %x(%x)\n", 
                            client, client->sid, tcon, 
-                           rxr_AddrStringOf(tcon),
+                           afs_inet_ntoa_r(rxr_HostOf(tcon), hoststr),
                            ntohs(rxr_PortOf(tcon)),
                            oldClient, oldClient->sid));
                if ((client->ViceId != ANONYMOUSID) && client->CPS.prlist_val)
@@ -2054,7 +2086,7 @@ h_FindClient_r(struct rx_connection *tcon)
        } else {
            ViceLog(0, ("FindClient: deleted client %x(%x) already had conn %x (host %s:%d), stolen by client %x(%x)\n", 
                        oldClient, oldClient->sid, tcon, 
-                       rxr_AddrStringOf(tcon),
+                       afs_inet_ntoa_r(rxr_HostOf(tcon), hoststr),
                        ntohs(rxr_PortOf(tcon)),
                        client, client->sid));
            /* rx_SetSpecific will be done immediately below */
@@ -2101,8 +2133,8 @@ GetClient(struct rx_connection *tcon, struct client **cp)
     client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
     if (client == NULL) {
        ViceLog(0,
-               ("GetClient: no client in conn %x (host %s:%d), VBUSYING\n",
-                tcon, rxr_AddrStringOf(tcon),ntohs(rxr_PortOf(tcon))));
+               ("GetClient: no client in conn %x (host %x:%d), VBUSYING\n",
+                tcon, rxr_HostOf(tcon),ntohs(rxr_PortOf(tcon))));
        H_UNLOCK;
        return VBUSY;
     }
@@ -3121,6 +3153,7 @@ CheckHost(register struct host *host, int held)
     }
     if (host->LastCall < checktime) {
        h_Lock_r(host);
+       host->hostFlags |= HWHO_INPROGRESS;
        if (!(host->hostFlags & HOSTDELETED)) {
            cb_conn = host->callback_rxcon;
            rx_GetConnection(cb_conn);
@@ -3190,6 +3223,7 @@ CheckHost(register struct host *host, int held)
            cb_conn=NULL;
            H_LOCK;
        }
+       host->hostFlags &= ~HWHO_INPROGRESS;
        h_Unlock_r(host);
     }
     H_UNLOCK;