static void cm_MarkServerDown(cm_server_t *tsp, afs_int32 code, int wasDown) { /* mark server as down */ if (!(tsp->flags & CM_SERVERFLAG_DOWN)) { _InterlockedOr(&tsp->flags, CM_SERVERFLAG_DOWN); tsp->downTime = time(NULL); } if (code != VRESTARTING) { lock_ReleaseMutex(&tsp->mx); cm_ForceNewConnections(tsp); lock_ObtainMutex(&tsp->mx); } /* Now update the volume status if necessary */ if (!wasDown) { if (tsp->type == CM_SERVER_FILE) { cm_server_vols_t * tsrvp; cm_volume_t * volp; int i; cm_req_t req; for (tsrvp = tsp->vols; tsrvp; tsrvp = tsrvp->nextp) { for (i=0; i<NUM_SERVER_VOLS; i++) { if (tsrvp->ids[i] != 0) { cm_InitReq(&req); lock_ReleaseMutex(&tsp->mx); code = cm_FindVolumeByID(tsp->cellp, tsrvp->ids[i], cm_rootUserp, &req, CM_GETVOL_FLAG_NO_LRU_UPDATE, &volp); lock_ObtainMutex(&tsp->mx); if (code == 0) { cm_UpdateVolumeStatus(volp, tsrvp->ids[i]); cm_PutVolume(volp); } } } } } cm_RankServer(tsp); } }
/* periodic check daemon */ void * cm_Daemon(void *vparm) { time_t now; time_t lastVolCheck; time_t lastCBExpirationCheck; time_t lastVolCBRenewalCheck; time_t lastDownServerCheck; time_t lastUpServerCheck; time_t lastTokenCacheCheck; time_t lastBusyVolCheck; time_t lastPerformanceCheck; time_t lastServerRankCheck; time_t lastRDRShakeExtents; time_t lastAfsdHookReload; time_t lastEAccesCheck; char thostName[200]; unsigned long code; struct hostent *thp; HMODULE hHookDll = NULL; AfsdDaemonHook daemonHook = NULL; char * name = "cm_Daemon_ShutdownEvent"; int configureFirewall = IsWindowsFirewallPresent(); int bAddrChangeCheck = 0; cm_Daemon_ShutdownEvent = thrd_CreateEvent(NULL, FALSE, FALSE, name); if ( GetLastError() == ERROR_ALREADY_EXISTS ) afsi_log("Event Object Already Exists: %s", name); if (!configureFirewall) { afsi_log("No Windows Firewall detected"); } if (cm_freelanceEnabled && cm_freelanceImportCellServDB) cm_FreelanceImportCellServDB(); /* ping all file servers, up or down, with unauthenticated connection, * to find out whether we have all our callbacks from the server still. * Also, ping down VLDBs. */ /* * Seed the random number generator with our own address, so that * clients starting at the same time don't all do vol checks at the * same time. */ gethostname(thostName, sizeof(thostName)); thp = gethostbyname(thostName); if (thp == NULL) /* In djgpp, gethostname returns the netbios name of the machine. gethostbyname will fail looking this up if it differs from DNS name. */ code = 0; else memcpy(&code, thp->h_addr_list[0], 4); srand(ntohl(code)); cm_DaemonCheckInit(); now = osi_Time(); lastVolCheck = now - cm_daemonCheckVolInterval/2 + (rand() % cm_daemonCheckVolInterval); lastCBExpirationCheck = now - cm_daemonCheckCBInterval/2 + (rand() % cm_daemonCheckCBInterval); if (cm_daemonCheckVolCBInterval) lastVolCBRenewalCheck = now - cm_daemonCheckVolCBInterval/2 + (rand() % cm_daemonCheckVolCBInterval); lastDownServerCheck = now - cm_daemonCheckDownInterval/2 + (rand() % cm_daemonCheckDownInterval); lastUpServerCheck = now - cm_daemonCheckUpInterval/2 + (rand() % cm_daemonCheckUpInterval); lastTokenCacheCheck = now - cm_daemonTokenCheckInterval/2 + (rand() % cm_daemonTokenCheckInterval); if (cm_daemonCheckOfflineVolInterval) lastBusyVolCheck = now - cm_daemonCheckOfflineVolInterval/2 * (rand() % cm_daemonCheckOfflineVolInterval); if (cm_daemonPerformanceTuningInterval) lastPerformanceCheck = now - cm_daemonPerformanceTuningInterval/2 * (rand() % cm_daemonPerformanceTuningInterval); lastServerRankCheck = now - cm_daemonRankServerInterval/2 * (rand() % cm_daemonRankServerInterval); if (cm_daemonRDRShakeExtentsInterval) lastRDRShakeExtents = now - cm_daemonRDRShakeExtentsInterval/2 * (rand() % cm_daemonRDRShakeExtentsInterval); if (cm_daemonAfsdHookReloadInterval) lastAfsdHookReload = now; lastEAccesCheck = now; hHookDll = cm_LoadAfsdHookLib(); if (hHookDll) daemonHook = ( AfsdDaemonHook ) GetProcAddress(hHookDll, AFSD_DAEMON_HOOK); while (daemon_ShutdownFlag == 0) { if (powerStateSuspended) { Sleep(1000); continue; } /* check to see if the listener threads halted due to network * disconnect or other issues. If so, attempt to restart them. */ smb_RestartListeners(0); if (daemon_ShutdownFlag == 1) break; if (configureFirewall) { /* Open Microsoft Firewall to allow in port 7001 */ switch (icf_CheckAndAddAFSPorts(AFS_PORTSET_CLIENT)) { case 0: afsi_log("Windows Firewall Configuration succeeded"); configureFirewall = 0; break; case 1: afsi_log("Invalid Windows Firewall Port Set"); break; case 2: afsi_log("Unable to open Windows Firewall Profile"); break; case 3: afsi_log("Unable to create/modify Windows Firewall Port entries"); break; default: afsi_log("Unknown Windows Firewall Configuration error"); } } /* find out what time it is */ now = osi_Time(); /* Determine whether an address change took place that we need to respond to */ if (bAddrChangeCheck) bAddrChangeCheck = 0; if (lastIPAddrChange != 0 && lastIPAddrChange + 2500 < now) { bAddrChangeCheck = 1; lastIPAddrChange = 0; } /* check down servers */ if ((bAddrChangeCheck || now > lastDownServerCheck + cm_daemonCheckDownInterval) && daemon_ShutdownFlag == 0 && powerStateSuspended == 0) { lastDownServerCheck = now; osi_Log0(afsd_logp, "cm_Daemon CheckDownServers"); cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS, NULL); if (daemon_ShutdownFlag == 1) break; now = osi_Time(); } if (bAddrChangeCheck && daemon_ShutdownFlag == 0 && powerStateSuspended == 0) { cm_ForceNewConnectionsAllServers(); } /* check up servers */ if ((bAddrChangeCheck || now > lastUpServerCheck + cm_daemonCheckUpInterval) && daemon_ShutdownFlag == 0 && powerStateSuspended == 0) { lastUpServerCheck = now; osi_Log0(afsd_logp, "cm_Daemon CheckUpServers"); cm_CheckServers(CM_FLAG_CHECKUPSERVERS, NULL); if (daemon_ShutdownFlag == 1) break; now = osi_Time(); } if (bAddrChangeCheck && daemon_ShutdownFlag == 0 && powerStateSuspended == 0) { smb_CheckVCs(); cm_VolStatus_Network_Addr_Change(); } /* * Once every five minutes inspect the volume list and enforce * the volume location expiration time. */ if (now > lastVolCheck + 300 && daemon_ShutdownFlag == 0 && powerStateSuspended == 0) { lastVolCheck = now; cm_RefreshVolumes(cm_daemonCheckVolInterval); if (daemon_ShutdownFlag == 1) break; now = osi_Time(); } /* Rank all up servers */ if ((now > lastServerRankCheck + cm_daemonRankServerInterval) && daemon_ShutdownFlag == 0 && powerStateSuspended == 0) { lastServerRankCheck = now; osi_Log0(afsd_logp, "cm_Daemon RankServer"); cm_RankUpServers(); if(daemon_ShutdownFlag == 1) break; now = osi_Time(); } if (cm_daemonCheckVolCBInterval && now > lastVolCBRenewalCheck + cm_daemonCheckVolCBInterval && daemon_ShutdownFlag == 0 && powerStateSuspended == 0) { lastVolCBRenewalCheck = now; cm_VolumeRenewROCallbacks(); if (daemon_ShutdownFlag == 1) break; now = osi_Time(); } if ((bAddrChangeCheck || (cm_daemonCheckOfflineVolInterval && now > lastBusyVolCheck + cm_daemonCheckOfflineVolInterval)) && daemon_ShutdownFlag == 0 && powerStateSuspended == 0) { lastBusyVolCheck = now; cm_CheckOfflineVolumes(); if (daemon_ShutdownFlag == 1) break; now = osi_Time(); } if (now > lastCBExpirationCheck + cm_daemonCheckCBInterval && daemon_ShutdownFlag == 0 && powerStateSuspended == 0) { lastCBExpirationCheck = now; cm_CheckCBExpiration(); if (daemon_ShutdownFlag == 1) break; now = osi_Time(); } if (now > lastTokenCacheCheck + cm_daemonTokenCheckInterval && daemon_ShutdownFlag == 0 && powerStateSuspended == 0) { lastTokenCacheCheck = now; cm_CheckTokenCache(now); if (daemon_ShutdownFlag == 1) break; now = osi_Time(); } if (now > lastEAccesCheck + cm_daemonEAccesCheckInterval && daemon_ShutdownFlag == 0 && powerStateSuspended == 0) { lastEAccesCheck = now; cm_EAccesClearOutdatedEntries(); if (daemon_ShutdownFlag == 1) break; now = osi_Time(); } if (cm_daemonRDRShakeExtentsInterval && now > lastRDRShakeExtents + cm_daemonRDRShakeExtentsInterval && daemon_ShutdownFlag == 0 && powerStateSuspended == 0) { cm_req_t req; cm_InitReq(&req); lastRDRShakeExtents = now; if (cm_data.buf_redirCount > cm_data.buf_freeCount) buf_RDRShakeSomeExtentsFree(&req, FALSE, 10 /* seconds */); if (daemon_ShutdownFlag == 1) break; now = osi_Time(); } /* allow an exit to be called prior to stopping the service */ if (cm_daemonAfsdHookReloadInterval && lastAfsdHookReload != 0 && lastAfsdHookReload < now) { if (hHookDll) { FreeLibrary(hHookDll); hHookDll = NULL; daemonHook = NULL; } hHookDll = cm_LoadAfsdHookLib(); if (hHookDll) daemonHook = ( AfsdDaemonHook ) GetProcAddress(hHookDll, AFSD_DAEMON_HOOK); } if (daemonHook) { BOOL hookRc = daemonHook(); if (hookRc == FALSE) { SetEvent(WaitToTerminate); } if (daemon_ShutdownFlag == 1) { break; } now = osi_Time(); } if (cm_daemonPerformanceTuningInterval && now > lastPerformanceCheck + cm_daemonPerformanceTuningInterval && daemon_ShutdownFlag == 0 && powerStateSuspended == 0) { lastPerformanceCheck = now; cm_PerformanceTuningCheck(); if (daemon_ShutdownFlag == 1) break; now = osi_Time(); } /* * sleep .5 seconds. if the thread blocks for a long time * we risk not being able to close the cache before Windows * kills our process during system shutdown. */ thrd_Sleep(500); } if (hHookDll) { FreeLibrary(hHookDll); } thrd_SetEvent(cm_Daemon_ShutdownEvent); pthread_exit(NULL); return NULL; }
long ReadData(cm_scache_t *scp, osi_hyper_t offset, long count, char *op, cm_user_t *userp, long *readp) { //osi_hyper_t offset; long code; cm_buf_t *bufferp; osi_hyper_t fileLength; osi_hyper_t thyper; osi_hyper_t lastByte; osi_hyper_t bufferOffset; long bufIndex, nbytes; int sequential = 0; cm_req_t req; cm_InitReq(&req); bufferp = NULL; lock_ObtainWrite(&scp->rw); /* start by looking up the file's end */ code = cm_SyncOp(scp, NULL, userp, &req, 0, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS); if (code) goto done; cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS); /* now we have the entry locked, look up the length */ fileLength = scp->length; /* adjust count down so that it won't go past EOF */ thyper.LowPart = count; thyper.HighPart = 0; thyper = LargeIntegerAdd(offset, thyper); /* where read should end */ lastByte = thyper; if (LargeIntegerGreaterThan(thyper, fileLength)) { /* we'd read past EOF, so just stop at fileLength bytes. * Start by computing how many bytes remain in the file. */ thyper = LargeIntegerSubtract(fileLength, offset); /* if we are past EOF, read 0 bytes */ if (LargeIntegerLessThanZero(thyper)) count = 0; else count = thyper.LowPart; } *readp = count; /* now, copy the data one buffer at a time, * until we've filled the request packet */ while (1) { /* if we've copied all the data requested, we're done */ if (count <= 0) break; /* otherwise, load up a buffer of data */ thyper.HighPart = offset.HighPart; thyper.LowPart = offset.LowPart & ~(buf_bufferSize-1); if (!bufferp || !LargeIntegerEqualTo(thyper, bufferOffset)) { /* wrong buffer */ if (bufferp) { buf_Release(bufferp); bufferp = NULL; } lock_ReleaseWrite(&scp->rw); code = buf_Get(scp, &thyper, &bufferp); lock_ObtainWrite(&scp->rw); if (code) goto done; bufferOffset = thyper; /* now get the data in the cache */ while (1) { code = cm_SyncOp(scp, bufferp, userp, &req, 0, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ); if (code) goto done; cm_SyncOpDone(scp, bufferp, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ); if (cm_HaveBuffer(scp, bufferp, 0)) break; /* otherwise, load the buffer and try again */ code = cm_GetBuffer(scp, bufferp, NULL, userp, &req); if (code) break; } if (code) { buf_Release(bufferp); bufferp = NULL; goto done; } } /* if (wrong buffer) ... */ /* now we have the right buffer loaded. Copy out the * data from here to the user's buffer. */ bufIndex = offset.LowPart & (buf_bufferSize - 1); /* and figure out how many bytes we want from this buffer */ nbytes = buf_bufferSize - bufIndex; /* what remains in buffer */ if (nbytes > count) nbytes = count; /* don't go past EOF */ /* now copy the data */ memcpy(op, bufferp->datap + bufIndex, nbytes); /* adjust counters, pointers, etc. */ op += nbytes; count -= nbytes; thyper.LowPart = nbytes; thyper.HighPart = 0; offset = LargeIntegerAdd(thyper, offset); } /* while 1 */ done: lock_ReleaseWrite(&scp->rw); //lock_ReleaseMutex(&fidp->mx); if (bufferp) buf_Release(bufferp); if (code == 0 && sequential) cm_ConsiderPrefetch(scp, &lastByte, *readp, userp, &req); return code; }
long WriteData(cm_scache_t *scp, osi_hyper_t offset, long count, char *op, cm_user_t *userp, long *writtenp) { long code = 0; long written = 0; osi_hyper_t fileLength; /* file's length at start of write */ osi_hyper_t minLength; /* don't read past this */ afs_uint32 nbytes; /* # of bytes to transfer this iteration */ cm_buf_t *bufferp; osi_hyper_t thyper; /* hyper tmp variable */ osi_hyper_t bufferOffset; afs_uint32 bufIndex; /* index in buffer where our data is */ int doWriteBack; osi_hyper_t writeBackOffset;/* offset of region to write back when * I/O is done */ DWORD filter = 0; cm_req_t req; cm_InitReq(&req); bufferp = NULL; doWriteBack = 0; lock_ObtainWrite(&scp->rw); /* start by looking up the file's end */ code = cm_SyncOp(scp, NULL, userp, &req, 0, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_SETSTATUS | CM_SCACHESYNC_GETSTATUS); if (code) goto done; cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_SETSTATUS | CM_SCACHESYNC_GETSTATUS); #if 0 /* make sure we have a writable FD */ if (!(fidp->flags & SMB_FID_OPENWRITE)) { code = CM_ERROR_BADFDOP; goto done; } #endif /* now we have the entry locked, look up the length */ fileLength = scp->length; minLength = fileLength; if (LargeIntegerGreaterThan(minLength, scp->serverLength)) minLength = scp->serverLength; /* adjust file length if we extend past EOF */ thyper.LowPart = count; thyper.HighPart = 0; thyper = LargeIntegerAdd(offset, thyper); /* where write should end */ if (LargeIntegerGreaterThan(thyper, fileLength)) { /* we'd write past EOF, so extend the file */ scp->mask |= CM_SCACHEMASK_LENGTH; scp->length = thyper; filter |= (FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_SIZE); } else filter |= FILE_NOTIFY_CHANGE_LAST_WRITE; /* now, if the new position (thyper) and the old (offset) are in * different storeback windows, remember to store back the previous * storeback window when we're done with the write. */ if ((thyper.LowPart & (-cm_chunkSize)) != (offset.LowPart & (-cm_chunkSize))) { /* they're different */ doWriteBack = 1; writeBackOffset.HighPart = offset.HighPart; writeBackOffset.LowPart = offset.LowPart & (-cm_chunkSize); } *writtenp = count; /* now, copy the data one buffer at a time, until we've filled the * request packet */ while (1) { /* if we've copied all the data requested, we're done */ if (count <= 0) break; /* handle over quota or out of space */ if (scp->flags & (CM_SCACHEFLAG_OVERQUOTA | CM_SCACHEFLAG_OUTOFSPACE)) { *writtenp = written; break; } /* otherwise, load up a buffer of data */ thyper.HighPart = offset.HighPart; thyper.LowPart = offset.LowPart & ~(buf_bufferSize-1); if (!bufferp || !LargeIntegerEqualTo(thyper, bufferOffset)) { /* wrong buffer */ if (bufferp) { lock_ReleaseMutex(&bufferp->mx); buf_Release(bufferp); bufferp = NULL; } lock_ReleaseWrite(&scp->rw); code = buf_Get(scp, &thyper, &bufferp); lock_ObtainMutex(&bufferp->mx); lock_ObtainWrite(&scp->rw); if (code) goto done; bufferOffset = thyper; /* now get the data in the cache */ while (1) { code = cm_SyncOp(scp, bufferp, userp, &req, 0, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_WRITE | CM_SCACHESYNC_BUFLOCKED); if (code) goto done; cm_SyncOpDone(scp, bufferp, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_WRITE | CM_SCACHESYNC_BUFLOCKED); /* If we're overwriting the entire buffer, or * if we're writing at or past EOF, mark the * buffer as current so we don't call * cm_GetBuffer. This skips the fetch from the * server in those cases where we're going to * obliterate all the data in the buffer anyway, * or in those cases where there is no useful * data at the server to start with. * * Use minLength instead of scp->length, since * the latter has already been updated by this * call. */ if (LargeIntegerGreaterThanOrEqualTo(bufferp->offset, minLength) || LargeIntegerEqualTo(offset, bufferp->offset) && (count >= buf_bufferSize || LargeIntegerGreaterThanOrEqualTo(LargeIntegerAdd(offset, ConvertLongToLargeInteger(count)), minLength))) { if (count < buf_bufferSize && bufferp->dataVersion == -1) memset(bufferp->datap, 0, buf_bufferSize); bufferp->dataVersion = scp->dataVersion; } if (cm_HaveBuffer(scp, bufferp, 1)) break; /* otherwise, load the buffer and try again */ lock_ReleaseMutex(&bufferp->mx); code = cm_GetBuffer(scp, bufferp, NULL, userp, &req); lock_ReleaseWrite(&scp->rw); lock_ObtainMutex(&bufferp->mx); lock_ObtainWrite(&scp->rw); if (code) break; } if (code) { lock_ReleaseMutex(&bufferp->mx); buf_Release(bufferp); bufferp = NULL; goto done; } } /* if (wrong buffer) ... */ /* now we have the right buffer loaded. Copy out the * data from here to the user's buffer. */ bufIndex = offset.LowPart & (buf_bufferSize - 1); /* and figure out how many bytes we want from this buffer */ nbytes = buf_bufferSize - bufIndex; /* what remains in buffer */ if (nbytes > count) nbytes = count; /* don't go past end of request */ /* now copy the data */ memcpy(bufferp->datap + bufIndex, op, nbytes); buf_SetDirty(bufferp, bufIndex, nbytes, userp); /* adjust counters, pointers, etc. */ op += nbytes; count -= nbytes; written += nbytes; thyper.LowPart = nbytes; thyper.HighPart = 0; offset = LargeIntegerAdd(thyper, offset); } /* while 1 */ done: lock_ReleaseWrite(&scp->rw); if (bufferp) { lock_ReleaseMutex(&bufferp->mx); buf_Release(bufferp); } if (code == 0 && doWriteBack) { lock_ObtainWrite(&scp->rw); code = cm_SyncOp(scp, NULL, userp, &req, 0, CM_SCACHESYNC_ASYNCSTORE); lock_ReleaseWrite(&scp->rw); if (code == 0) cm_QueueBKGRequest(scp, cm_BkgStore, writeBackOffset.LowPart, writeBackOffset.HighPart, cm_chunkSize, 0, userp); } /* cm_SyncOpDone is called when cm_BkgStore completes */ return code; }
static void cm_CheckServersMulti(afs_uint32 flags, cm_cell_t *cellp) { /* * The goal of this function is to probe simultaneously * probe all of the up/down servers (vldb/file) as * specified by flags in the minimum number of RPCs. * Effectively that means use one multi_RXAFS_GetCapabilities() * followed by possibly one multi_RXAFS_GetTime() and * one multi_VL_ProbeServer(). * * To make this work we must construct the list of vldb * and file servers that are to be probed as well as the * associated data structures. */ int srvAddrCount = 0; struct srvAddr **addrs = NULL; cm_conn_t **conns = NULL; struct rx_connection **rxconns = NULL; cm_req_t req; afs_int32 i, nconns = 0, maxconns; afs_int32 *conntimer, *results; Capabilities *caps = NULL; cm_server_t ** serversp, *tsp; afs_uint32 isDown, wasDown; afs_uint32 code; time_t start; char hoststr[16]; cm_InitReq(&req); maxconns = max(cm_numFileServers,cm_numVldbServers); if (maxconns == 0) return; conns = (cm_conn_t **)malloc(maxconns * sizeof(cm_conn_t *)); rxconns = (struct rx_connection **)malloc(maxconns * sizeof(struct rx_connection *)); conntimer = (afs_int32 *)malloc(maxconns * sizeof (afs_int32)); results = (afs_int32 *)malloc(maxconns * sizeof (afs_int32)); serversp = (cm_server_t **)malloc(maxconns * sizeof(cm_server_t *)); caps = (Capabilities *)malloc(maxconns * sizeof(Capabilities)); memset(caps, 0, maxconns * sizeof(Capabilities)); if ((flags & CM_FLAG_CHECKFILESERVERS) || !(flags & (CM_FLAG_CHECKFILESERVERS|CM_FLAG_CHECKVLDBSERVERS))) { lock_ObtainRead(&cm_serverLock); for (nconns=0, tsp = cm_serversAllFirstp; tsp != NULL && nconns < maxconns; tsp = (cm_server_t *)osi_QNext(&tsp->allq)) { if (tsp->type != CM_SERVER_FILE || tsp->cellp == NULL || /* SetPref only */ cellp && cellp != tsp->cellp) continue; cm_GetServerNoLock(tsp); lock_ReleaseRead(&cm_serverLock); lock_ObtainMutex(&tsp->mx); isDown = tsp->flags & CM_SERVERFLAG_DOWN; if (tsp->pingCount > 0 || !((isDown && (flags & CM_FLAG_CHECKDOWNSERVERS)) || (!isDown && (flags & CM_FLAG_CHECKUPSERVERS)))) { lock_ReleaseMutex(&tsp->mx); lock_ObtainRead(&cm_serverLock); cm_PutServerNoLock(tsp); continue; } InterlockedIncrement(&tsp->pingCount); lock_ReleaseMutex(&tsp->mx); if (cm_noIPAddr > 0) code = cm_ConnByServer(tsp, cm_rootUserp, FALSE, &conns[nconns]); else code = RX_CALL_DEAD; if (code) { lock_ObtainMutex(&tsp->mx); if (code == RX_CALL_DEAD) cm_MarkServerDown(tsp, code, isDown); InterlockedDecrement(&tsp->pingCount); lock_ReleaseMutex(&tsp->mx); lock_ObtainRead(&cm_serverLock); cm_PutServerNoLock(tsp); continue; } lock_ObtainRead(&cm_serverLock); rxconns[nconns] = cm_GetRxConn(conns[nconns]); if (conntimer[nconns] = (isDown ? 1 : 0)) rx_SetConnHardDeadTime(rxconns[nconns], 10); serversp[nconns] = tsp; nconns++; } lock_ReleaseRead(&cm_serverLock); if (nconns) { /* Perform the multi call */ start = time(NULL); multi_Rx(rxconns,nconns) { multi_RXAFS_GetCapabilities(&caps[multi_i]); results[multi_i]=multi_error; } multi_End; }
void cm_PingServer(cm_server_t *tsp) { long code; int wasDown = 0; cm_conn_t *connp; struct rx_connection * rxconnp; Capabilities caps = {0, 0}; char hoststr[16]; cm_req_t req; lock_ObtainMutex(&tsp->mx); if (InterlockedIncrement(&tsp->pingCount) > 1) { tsp->waitCount++; osi_SleepM((LONG_PTR)tsp, &tsp->mx); lock_ObtainMutex(&tsp->mx); InterlockedDecrement(&tsp->pingCount); if (--tsp->waitCount > 0) osi_Wakeup((LONG_PTR)tsp); lock_ReleaseMutex(&tsp->mx); return; } wasDown = tsp->flags & CM_SERVERFLAG_DOWN; afs_inet_ntoa_r(tsp->addr.sin_addr.S_un.S_addr, hoststr); lock_ReleaseMutex(&tsp->mx); if (cm_noIPAddr > 0) code = cm_ConnByServer(tsp, cm_rootUserp, FALSE, &connp); else code = RX_CALL_DEAD; /* No network */ if (code == 0) { /* now call the appropriate ping call. Drop the timeout if * the server is known to be down, so that we don't waste a * lot of time retiming out down servers. */ osi_Log4(afsd_logp, "cm_PingServer server %s (%s) was %s with caps 0x%x", osi_LogSaveString(afsd_logp, hoststr), tsp->type == CM_SERVER_VLDB ? "vldb" : "file", wasDown ? "down" : "up", tsp->capabilities); rxconnp = cm_GetRxConn(connp); if (wasDown) rx_SetConnHardDeadTime(rxconnp, 10); if (tsp->type == CM_SERVER_VLDB) { code = VL_ProbeServer(rxconnp); } else { /* file server */ code = RXAFS_GetCapabilities(rxconnp, &caps); } if (wasDown) rx_SetConnHardDeadTime(rxconnp, HardDeadtimeout); rx_PutConnection(rxconnp); cm_PutConn(connp); } /* got an unauthenticated connection to this server */ lock_ObtainMutex(&tsp->mx); if (code >= 0 || code == RXGEN_OPCODE) { /* mark server as up */ _InterlockedAnd(&tsp->flags, ~CM_SERVERFLAG_DOWN); tsp->downTime = 0; /* we currently handle 32-bits of capabilities */ if (code != RXGEN_OPCODE && caps.Capabilities_len > 0) { tsp->capabilities = caps.Capabilities_val[0]; xdr_free((xdrproc_t) xdr_Capabilities, &caps); caps.Capabilities_len = 0; caps.Capabilities_val = 0; } else { tsp->capabilities = 0; } osi_Log3(afsd_logp, "cm_PingServer server %s (%s) is up with caps 0x%x", osi_LogSaveString(afsd_logp, hoststr), tsp->type == CM_SERVER_VLDB ? "vldb" : "file", tsp->capabilities); /* Now update the volume status if necessary */ if (wasDown) { cm_server_vols_t * tsrvp; cm_volume_t * volp; int i; for (tsrvp = tsp->vols; tsrvp; tsrvp = tsrvp->nextp) { for (i=0; i<NUM_SERVER_VOLS; i++) { if (tsrvp->ids[i] != 0) { cm_InitReq(&req); lock_ReleaseMutex(&tsp->mx); code = cm_FindVolumeByID(tsp->cellp, tsrvp->ids[i], cm_rootUserp, &req, CM_GETVOL_FLAG_NO_LRU_UPDATE, &volp); lock_ObtainMutex(&tsp->mx); if (code == 0) { cm_UpdateVolumeStatus(volp, tsrvp->ids[i]); cm_PutVolume(volp); } } } } cm_RankServer(tsp); } } else { cm_MarkServerDown(tsp, code, wasDown); osi_Log3(afsd_logp, "cm_PingServer server %s (%s) is down with caps 0x%x", osi_LogSaveString(afsd_logp, hoststr), tsp->type == CM_SERVER_VLDB ? "vldb" : "file", tsp->capabilities); } InterlockedDecrement(&tsp->pingCount); if (tsp->waitCount > 0) osi_Wakeup((LONG_PTR)tsp); lock_ReleaseMutex(&tsp->mx); }