#include <stdio.h>
#include <errno.h>
+#include <string.h>
#ifdef AFS_NT40_ENV
#include <fcntl.h>
#include <winsock2.h>
#include <netinet/in.h>
#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#else
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#endif
-
#include <afs/stds.h>
#include <rx/xdr.h>
#include <afs/assert.h>
if (!uclient) {
code = hpr_Initialize(&uclient);
- assert(pthread_setspecific(viced_uclient_key, (void *)uclient) == 0);
+ if (!code)
+ assert(pthread_setspecific(viced_uclient_key, (void *)uclient) == 0);
+ else
+ return code;
}
over = 0;
if (!uclient) {
code = hpr_Initialize(&uclient);
- assert(pthread_setspecific(viced_uclient_key, (void *)uclient) == 0);
+ if (!code)
+ assert(pthread_setspecific(viced_uclient_key, (void *)uclient) == 0);
+ else
+ return code;
}
for (i = 0; i < names->namelist_len; i++)
if (!uclient) {
code = hpr_Initialize(&uclient);
- assert(pthread_setspecific(viced_uclient_key, (void *)uclient) == 0);
+ if (!code)
+ assert(pthread_setspecific(viced_uclient_key, (void *)uclient) == 0);
+ else
+ return code;
}
code = ubik_PR_IDToName(uclient, 0, ids, names);
if (!uclient) {
code = hpr_Initialize(&uclient);
- assert(pthread_setspecific(viced_uclient_key, (void *)uclient) == 0);
+ if (!code)
+ assert(pthread_setspecific(viced_uclient_key, (void *)uclient) == 0);
+ else
+ return code;
}
over = 0;
void
h_flushhostcps(register afs_uint32 hostaddr, register afs_uint16 hport)
{
- register struct host *host;
+ struct host *host;
int held = 0;
H_LOCK;
- host = h_Lookup_r(hostaddr, hport, &held);
+ h_Lookup_r(hostaddr, hport, &held, &host);
if (host) {
host->hcpsfailed = 1;
if (!held)
/* hostaddr and hport are in network order */
/* Note: host should be released by caller if 0 == *heldp and non-null */
/* hostaddr and hport are in network order */
-struct host *
-h_Lookup_r(afs_uint32 haddr, afs_uint16 hport, int *heldp)
+int
+h_Lookup_r(afs_uint32 haddr, afs_uint16 hport, int *heldp, struct host **hostp)
{
afs_int32 now;
struct host *host = NULL;
assert(host);
if (!(host->hostFlags & HOSTDELETED) && chain->addr == haddr
&& chain->port == hport) {
+ if ((host->hostFlags & HWHO_INPROGRESS) &&
+ h_threadquota(host->lock.num_waiting)) {
+ *hostp = 0;
+ return VBUSY;
+ }
*heldp = h_Held_r(host);
if (!*heldp)
h_Hold_r(host);
}
host = NULL;
}
- return host;
-
+ *hostp = host;
+ return 0;
} /*h_Lookup */
/* Lookup a host given its UUID. */
if (!(held[count] = h_Held_r(host)))
h_Hold_r(host);
}
- assert(count == hostCount);
+ if (count != hostCount) {
+ ViceLog(0, ("h_Enumerate found %d of %d hosts\n", count, hostCount));
+ }
+ assert(count <= hostCount);
H_UNLOCK;
for (i = 0; i < count; i++) {
held[i] = (*proc) (list[i], held[i], param);
caps.Capabilities_len = 0;
code = 0;
- host = h_Lookup_r(haddr, hport, &held);
+ if (h_Lookup_r(haddr, hport, &held, &host))
+ return 0;
identP = (struct Identity *)rx_GetSpecific(tcon, rxcon_ident_key);
if (host && !identP && !(host->Console & 1)) {
/* This is a new connection, and we already have a host
* of the caller matches the identity in the host structure.
*/
if ((host->hostFlags & HWHO_INPROGRESS) &&
- h_threadquota(host->lock.num_waiting))
+ h_threadquota(host->lock.num_waiting)) {
+ if (!held)
+ h_Release_r(host);
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)
ntohs(host->port)));
goto retry;
}
+ host->hostFlags |= HWHO_INPROGRESS;
host->hostFlags &= ~ALTADDR;
cb_conn = host->callback_rxcon;
rx_GetConnection(cb_conn);
cb_conn=NULL;
H_LOCK;
if ((code == RXGEN_OPCODE) ||
- (afs_uuid_equal(&interf.uuid, &nulluuid))) {
+ ((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"));
host, 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);
host->interface ? uuid2 : "no_uuid"));
/* The host in the cache is not the host for this connection */
+ h_Lock_r(host);
host->hostFlags |= HOSTDELETED;
- host->hostFlags &= ~HWHO_INPROGRESS;
h_Unlock_r(host);
if (!held)
h_Release_r(host);
int pident = 0;
cb_conn = host->callback_rxcon;
rx_GetConnection(cb_conn);
+ host->hostFlags |= HWHO_INPROGRESS;
H_UNLOCK;
code =
RXAFSCB_TellMeAboutYourself(cb_conn, &interf, &caps);
cb_conn=NULL;
H_LOCK;
if ((code == RXGEN_OPCODE) ||
- afs_uuid_equal(&interf.uuid, &nulluuid)) {
+ ((code == 0) && (afs_uuid_equal(&interf.uuid, &nulluuid)))) {
if (!identP)
identP =
(struct Identity *)malloc(sizeof(struct Identity));
&FS_HostUUID);
rx_PutConnection(cb_conn);
cb_conn=NULL;
+ H_LOCK;
if (code == 0) {
ViceLog(25,
("InitCallBackState3 success on host %x (%s:%d)\n",
{
int ret = 0, found = 0;
struct host *host = NULL;
- struct h_hashChain *chain;
+ struct h_AddrHashChain *chain;
int index = h_HashIndex(addr);
char tmp[16];
int chain_len = 0;
{
int ret = 0, found = 0;
struct host *host = NULL;
- struct h_hashChain *chain;
+ struct h_UuidHashChain *chain;
afsUUID * uuidp = &h->interface->uuid;
int index = h_UuidHashIndex(uuidp);
char tmp[40];
} /*CheckHost */
+int
+CheckHost_r(register struct host *host, int held, char *dummy)
+{
+ register struct client *client;
+ struct rx_connection *cb_conn = NULL;
+ int code;
+
+#ifdef AFS_DEMAND_ATTACH_FS
+ /* kill the checkhost lwp ASAP during shutdown */
+ FS_STATE_RDLOCK;
+ if (fs_state.mode == FS_MODE_SHUTDOWN) {
+ FS_STATE_UNLOCK;
+ return H_ENUMERATE_BAIL(held);
+ }
+ FS_STATE_UNLOCK;
+#endif
+
+ /* Host is held by h_Enumerate_r */
+ for (client = host->FirstClient; client; client = client->next) {
+ if (client->refCount == 0 && client->LastCall < clientdeletetime) {
+ client->deleted = 1;
+ host->hostFlags |= CLIENTDELETED;
+ }
+ }
+ if (host->LastCall < checktime) {
+ h_Lock_r(host);
+ if (!(host->hostFlags & HOSTDELETED)) {
+ cb_conn = host->callback_rxcon;
+ rx_GetConnection(cb_conn);
+ if (host->LastCall < clientdeletetime) {
+ host->hostFlags |= HOSTDELETED;
+ if (!(host->hostFlags & VENUSDOWN)) {
+ host->hostFlags &= ~ALTADDR; /* alternate address invalid */
+ if (host->interface) {
+ H_UNLOCK;
+ code =
+ RXAFSCB_InitCallBackState3(cb_conn,
+ &FS_HostUUID);
+ H_LOCK;
+ } else {
+ H_UNLOCK;
+ code =
+ RXAFSCB_InitCallBackState(cb_conn);
+ H_LOCK;
+ }
+ host->hostFlags |= ALTADDR; /* alternate addresses valid */
+ if (code) {
+ char hoststr[16];
+ (void)afs_inet_ntoa_r(host->host, hoststr);
+ ViceLog(0,
+ ("CB: RCallBackConnectBack (host.c) failed for host %s:%d\n",
+ hoststr, ntohs(host->port)));
+ host->hostFlags |= VENUSDOWN;
+ }
+ /* Note: it's safe to delete hosts even if they have call
+ * back state, because break delayed callbacks (called when a
+ * message is received from the workstation) will always send a
+ * break all call backs to the workstation if there is no
+ *callback.
+ */
+ }
+ } else {
+ if (!(host->hostFlags & VENUSDOWN) && host->cblist) {
+ char hoststr[16];
+ (void)afs_inet_ntoa_r(host->host, hoststr);
+ if (host->interface) {
+ afsUUID uuid = host->interface->uuid;
+ H_UNLOCK;
+ code = RXAFSCB_ProbeUuid(cb_conn, &uuid);
+ H_LOCK;
+ if (code) {
+ if (MultiProbeAlternateAddress_r(host)) {
+ ViceLog(0,("CheckHost_r: Probing all interfaces of host %s:%d failed, code %d\n",
+ hoststr, ntohs(host->port), code));
+ host->hostFlags |= VENUSDOWN;
+ }
+ }
+ } else {
+ H_UNLOCK;
+ code = RXAFSCB_Probe(cb_conn);
+ H_LOCK;
+ if (code) {
+ ViceLog(0,
+ ("CheckHost_r: Probe failed for host %s:%d, code %d\n",
+ hoststr, ntohs(host->port), code));
+ host->hostFlags |= VENUSDOWN;
+ }
+ }
+ }
+ }
+ H_UNLOCK;
+ rx_PutConnection(cb_conn);
+ cb_conn=NULL;
+ H_LOCK;
+ }
+ h_Unlock_r(host);
+ }
+ return held;
+
+} /*CheckHost_r */
+
/*
* Set VenusDown for any hosts that have not had a call in 15 minutes and
*/
checktime = now - 15 * 60;
clientdeletetime = now - 120 * 60; /* 2 hours ago */
- h_Enumerate(CheckHost, NULL);
-
+
+ H_LOCK;
+ h_Enumerate_r(CheckHost_r, hostList, NULL);
+ H_UNLOCK;
} /*h_CheckHosts */
/*