2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include <afs/param.h>
27 #include <rx/rx_prototypes.h>
28 #include <WINNT/afsreg.h>
33 long cm_daemonCheckDownInterval = 180;
34 long cm_daemonCheckUpInterval = 240;
35 long cm_daemonCheckVolInterval = 3600;
36 long cm_daemonCheckCBInterval = 60;
37 long cm_daemonCheckVolCBInterval = 0;
38 long cm_daemonCheckLockInterval = 60;
39 long cm_daemonTokenCheckInterval = 180;
40 long cm_daemonCheckOfflineVolInterval = 600;
41 long cm_daemonPerformanceTuningInterval = 0;
42 long cm_daemonRankServerInterval = 600;
43 long cm_daemonRDRShakeExtentsInterval = 0;
44 long cm_daemonAfsdHookReloadInterval = 0;
45 long cm_daemonEAccesCheckInterval = 1800;
47 typedef struct daemon_state {
49 afs_uint32 queueCount;
50 cm_bkgRequest_t *head;
51 cm_bkgRequest_t *tail;
52 afs_uint64 completeCount;
53 afs_uint64 retryCount;
54 afs_uint64 errorCount;
57 daemon_state_t *cm_daemons = NULL;
60 extern int powerStateSuspended;
61 int daemon_ShutdownFlag = 0;
62 static time_t lastIPAddrChange = 0;
64 static EVENT_HANDLE cm_Daemon_ShutdownEvent = NULL;
65 static EVENT_HANDLE cm_LockDaemon_ShutdownEvent = NULL;
66 static EVENT_HANDLE cm_IPAddrDaemon_ShutdownEvent = NULL;
67 static EVENT_HANDLE cm_BkgDaemon_ShutdownEvent[CM_MAX_DAEMONS] =
68 {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
70 void * cm_IpAddrDaemon(void * vparm)
72 extern void smb_CheckVCs(void);
73 char * name = "cm_IPAddrDaemon_ShutdownEvent";
75 cm_IPAddrDaemon_ShutdownEvent = thrd_CreateEvent(NULL, FALSE, FALSE, name);
76 if ( GetLastError() == ERROR_ALREADY_EXISTS )
77 afsi_log("Event Object Already Exists: %s", name);
79 rx_StartClientThread();
81 while (daemon_ShutdownFlag == 0) {
84 thrd_SetEvent(cm_IPAddrDaemon_ShutdownEvent);
85 Result = NotifyAddrChange(NULL,NULL);
86 if (Result == NO_ERROR && daemon_ShutdownFlag == 0) {
87 lastIPAddrChange = osi_Time();
89 smb_SetLanAdapterChangeDetected();
90 cm_SetLanAdapterChangeDetected();
91 thrd_ResetEvent(cm_IPAddrDaemon_ShutdownEvent);
93 cm_ServerClearRPCStats();
97 thrd_SetEvent(cm_IPAddrDaemon_ShutdownEvent);
102 afs_int32 cm_RequestWillBlock(cm_bkgRequest_t *rp)
104 afs_int32 willBlock = 0;
106 if (rp->procp == cm_BkgStore) {
108 * If the datastoring flag is set, it means that another
109 * thread is already performing an exclusive store operation
110 * on this file. The exclusive state will be cleared once
111 * the file server locks the vnode. Therefore, at most two
112 * threads can be actively involved in storing data at a time
115 lock_ObtainRead(&rp->scp->rw);
116 willBlock = (rp->scp->flags & CM_SCACHEFLAG_DATASTORING);
117 lock_ReleaseRead(&rp->scp->rw);
119 else if (rp->procp == RDR_BkgFetch || rp->procp == cm_BkgPrefetch) {
121 * Attempt to determine if there is a conflict on the requested
122 * range of the file. If the first in the range does not exist
123 * in the cache assume there is no conflict. If the buffer does
124 * exist, check to see if an I/O operation is in progress
125 * by using the writing and reading flags as an indicator.
127 cm_buf_t *bufp = NULL;
128 rock_BkgFetch_t *rockp = (rock_BkgFetch_t *)rp->rockp;
130 bufp = buf_Find(&rp->scp->fid, &rockp->base);
132 willBlock = (bufp->flags & (CM_BUF_WRITING|CM_BUF_READING));
140 void * cm_BkgDaemon(void * vparm)
145 long daemonID = (long)(LONG_PTR)vparm;
147 snprintf(name, sizeof(name), "cm_BkgDaemon_ShutdownEvent%u", daemonID);
149 cm_BkgDaemon_ShutdownEvent[daemonID] = thrd_CreateEvent(NULL, FALSE, FALSE, name);
150 if ( GetLastError() == ERROR_ALREADY_EXISTS )
151 afsi_log("Event Object Already Exists: %s", name);
153 rx_StartClientThread();
155 lock_ObtainWrite(&cm_daemons[daemonID].lock);
156 while (daemon_ShutdownFlag == 0) {
159 if (powerStateSuspended) {
163 if (!cm_daemons[daemonID].tail) {
164 osi_SleepW((LONG_PTR)&cm_daemons[daemonID].head, &cm_daemons[daemonID].lock);
165 lock_ObtainWrite(&cm_daemons[daemonID].lock);
169 /* we found a request */
170 for (rp = cm_daemons[daemonID].tail; rp; rp = (cm_bkgRequest_t *) osi_QPrev(&rp->q))
172 if (rp->scp->flags & CM_SCACHEFLAG_DELETED)
176 * If the request has active I/O such that this worker would
177 * be forced to block, leave the request in the queue and move
178 * on to one that might be available for servicing.
180 if (cm_RequestWillBlock(rp)) {
185 if (cm_ServerAvailable(&rp->scp->fid, rp->userp))
191 * Couldn't find a request that we could process at the
192 * current time. If there were requests that would cause
193 * the worker to block, sleep for 25ms so it can promptly
194 * respond when it is available. Otherwise, sleep for 1s.
196 * This polling cycle needs to be replaced with a proper
197 * producer/consumer dynamic worker pool.
199 osi_Log2(afsd_logp,"cm_BkgDaemon[%u] sleeping %dms all tasks would block",
200 daemonID, willBlock ? 100 : 1000);
202 lock_ReleaseWrite(&cm_daemons[daemonID].lock);
203 Sleep(willBlock ? 100 : 1000);
204 lock_ObtainWrite(&cm_daemons[daemonID].lock);
208 osi_QRemoveHT((osi_queue_t **) &cm_daemons[daemonID].head, (osi_queue_t **) &cm_daemons[daemonID].tail, &rp->q);
209 osi_assertx(cm_daemons[daemonID].queueCount-- > 0, "cm_bkgQueueCount 0");
210 lock_ReleaseWrite(&cm_daemons[daemonID].lock);
212 osi_Log2(afsd_logp,"cm_BkgDaemon[%u] processing request 0x%p", daemonID, rp);
214 if (rp->scp->flags & CM_SCACHEFLAG_DELETED) {
215 osi_Log2(afsd_logp,"cm_BkgDaemon[%u] DELETED scp 0x%x", daemonID, rp->scp);
216 code = CM_ERROR_BADFD;
218 #ifdef DEBUG_REFCOUNT
219 osi_Log3(afsd_logp,"cm_BkgDaemon[%u] (before) scp 0x%x ref %d", daemonID, rp->scp, rp->scp->refCount);
221 code = (*rp->procp)(rp->scp, rp->rockp, rp->userp, &rp->req);
222 #ifdef DEBUG_REFCOUNT
223 osi_Log3(afsd_logp,"cm_BkgDaemon[%u] (after) scp 0x%x ref %d", daemonID, rp->scp, rp->scp->refCount);
228 * Keep the following list synchronized with the
229 * error code list in cm_BkgStore.
230 * cm_SyncOpDone(CM_SCACHESYNC_ASYNCSTORE) will be called there unless
231 * one of these errors has occurred.
234 case CM_ERROR_TIMEDOUT: /* or server restarting */
236 case CM_ERROR_WOULDBLOCK:
237 case CM_ERROR_ALLBUSY:
238 case CM_ERROR_ALLDOWN:
239 case CM_ERROR_ALLOFFLINE:
240 case CM_ERROR_PARTIALWRITE:
241 if (rp->procp == cm_BkgStore ||
242 rp->procp == RDR_BkgFetch) {
244 "cm_BkgDaemon[%u] re-queueing failed request 0x%p code 0x%x",
246 lock_ObtainWrite(&cm_daemons[daemonID].lock);
247 cm_daemons[daemonID].queueCount++;
248 cm_daemons[daemonID].retryCount++;
249 osi_QAddT((osi_queue_t **) &cm_daemons[daemonID].head, (osi_queue_t **)&cm_daemons[daemonID].tail, &rp->q);
251 } /* otherwise fall through */
252 case 0: /* success */
253 default: /* other error */
255 osi_Log2(afsd_logp,"cm_BkgDaemon[%u] SUCCESS: request 0x%p", daemonID, rp);
256 cm_daemons[daemonID].completeCount++;
258 osi_Log3(afsd_logp,"cm_BkgDaemon[%u] FAILED: request dropped 0x%p code 0x%x",
260 cm_daemons[daemonID].errorCount++;
262 cm_ReleaseUser(rp->userp);
263 cm_ReleaseSCache(rp->scp);
266 lock_ObtainWrite(&cm_daemons[daemonID].lock);
269 lock_ReleaseWrite(&cm_daemons[daemonID].lock);
270 thrd_SetEvent(cm_BkgDaemon_ShutdownEvent[daemonID]);
275 int cm_QueueBKGRequest(cm_scache_t *scp, cm_bkgProc_t *procp, void *rockp,
276 cm_user_t *userp, cm_req_t *reqp)
278 cm_bkgRequest_t *rp, *rpq;
282 rp = malloc(sizeof(*rp));
283 memset(rp, 0, sizeof(*rp));
293 /* Use separate queues for fetch and store operations */
294 daemonID = scp->fid.hash % (cm_nDaemons/2) * 2;
295 if (procp == cm_BkgStore)
298 /* Check to see if this is a duplicate request */
299 lock_ObtainWrite(&cm_daemons[daemonID].lock);
300 if ( procp == cm_BkgStore || procp == RDR_BkgFetch || procp == cm_BkgPrefetch ) {
301 for (rpq = cm_daemons[daemonID].head; rpq; rpq = (cm_bkgRequest_t *) osi_QNext(&rpq->q))
303 if ( rpq->procp == procp &&
307 if (rp->procp == cm_BkgStore) {
308 rock_BkgStore_t *rock1p = (rock_BkgStore_t *)rp->rockp;
309 rock_BkgStore_t *rock2p = (rock_BkgStore_t *)rpq->rockp;
311 duplicate = (memcmp(rock1p, rock2p, sizeof(*rock1p)) == 0);
313 else if (rp->procp == RDR_BkgFetch || rp->procp == cm_BkgPrefetch) {
314 rock_BkgFetch_t *rock1p = (rock_BkgFetch_t *)rp->rockp;
315 rock_BkgFetch_t *rock2p = (rock_BkgFetch_t *)rpq->rockp;
317 duplicate = (memcmp(rock1p, rock2p, sizeof(*rock1p)) == 0);
321 /* found a duplicate; update request with latest info */
329 cm_daemons[daemonID].queueCount++;
330 osi_QAddH((osi_queue_t **) &cm_daemons[daemonID].head, (osi_queue_t **)&cm_daemons[daemonID].tail, &rp->q);
332 lock_ReleaseWrite(&cm_daemons[daemonID].lock);
335 cm_ReleaseSCache(scp);
336 cm_ReleaseUser(userp);
341 osi_Wakeup((LONG_PTR) &cm_daemons[daemonID].head);
347 IsWindowsFirewallPresent(void)
352 BOOLEAN result = FALSE;
353 LPQUERY_SERVICE_CONFIG pConfig = NULL;
357 /* Open services manager */
358 scm = OpenSCManager(NULL, NULL, GENERIC_READ);
359 if (!scm) return FALSE;
361 /* Open Windows Firewall service */
362 svc = OpenService(scm, "MpsSvc", SERVICE_QUERY_CONFIG);
364 afsi_log("MpsSvc Service could not be opened for query: 0x%x", GetLastError());
365 svc = OpenService(scm, "SharedAccess", SERVICE_QUERY_CONFIG);
367 afsi_log("SharedAccess Service could not be opened for query: 0x%x", GetLastError());
372 /* Query Windows Firewall service config, first just to get buffer size */
373 /* Expected to fail, so don't test return value */
374 (void) QueryServiceConfig(svc, NULL, 0, &BufSize);
375 status = GetLastError();
376 if (status != ERROR_INSUFFICIENT_BUFFER)
379 /* Allocate buffer */
380 pConfig = (LPQUERY_SERVICE_CONFIG)GlobalAlloc(GMEM_FIXED,BufSize);
384 /* Query Windows Firewall service config, this time for real */
385 flag = QueryServiceConfig(svc, pConfig, BufSize, &BufSize);
387 afsi_log("QueryServiceConfig failed: 0x%x", GetLastError());
391 /* Is it autostart? */
392 afsi_log("AutoStart 0x%x", pConfig->dwStartType);
393 if (pConfig->dwStartType < SERVICE_DEMAND_START)
399 CloseServiceHandle(svc);
401 CloseServiceHandle(scm);
407 cm_DaemonCheckInit(void)
414 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
415 0, KEY_QUERY_VALUE, &parmKey);
419 dummyLen = sizeof(DWORD);
420 code = RegQueryValueEx(parmKey, "daemonCheckDownInterval", NULL, NULL,
421 (BYTE *) &dummy, &dummyLen);
422 if (code == ERROR_SUCCESS && dummy)
423 cm_daemonCheckDownInterval = dummy;
424 afsi_log("daemonCheckDownInterval is %d", cm_daemonCheckDownInterval);
426 dummyLen = sizeof(DWORD);
427 code = RegQueryValueEx(parmKey, "daemonCheckUpInterval", NULL, NULL,
428 (BYTE *) &dummy, &dummyLen);
429 if (code == ERROR_SUCCESS && dummy)
430 cm_daemonCheckUpInterval = dummy;
431 afsi_log("daemonCheckUpInterval is %d", cm_daemonCheckUpInterval);
433 dummyLen = sizeof(DWORD);
434 code = RegQueryValueEx(parmKey, "daemonCheckVolInterval", NULL, NULL,
435 (BYTE *) &dummy, &dummyLen);
436 if (code == ERROR_SUCCESS && dummy)
437 cm_daemonCheckVolInterval = dummy;
438 afsi_log("daemonCheckVolInterval is %d", cm_daemonCheckVolInterval);
440 dummyLen = sizeof(DWORD);
441 code = RegQueryValueEx(parmKey, "daemonCheckCBInterval", NULL, NULL,
442 (BYTE *) &dummy, &dummyLen);
443 if (code == ERROR_SUCCESS && dummy)
444 cm_daemonCheckCBInterval = dummy;
445 afsi_log("daemonCheckCBInterval is %d", cm_daemonCheckCBInterval);
447 dummyLen = sizeof(DWORD);
448 code = RegQueryValueEx(parmKey, "daemonCheckVolCBInterval", NULL, NULL,
449 (BYTE *) &dummy, &dummyLen);
450 if (code == ERROR_SUCCESS && dummy)
451 cm_daemonCheckVolCBInterval = dummy;
452 afsi_log("daemonCheckVolCBInterval is %d", cm_daemonCheckVolCBInterval);
454 dummyLen = sizeof(DWORD);
455 code = RegQueryValueEx(parmKey, "daemonCheckLockInterval", NULL, NULL,
456 (BYTE *) &dummy, &dummyLen);
457 if (code == ERROR_SUCCESS && dummy)
458 cm_daemonCheckLockInterval = dummy;
459 afsi_log("daemonCheckLockInterval is %d", cm_daemonCheckLockInterval);
461 dummyLen = sizeof(DWORD);
462 code = RegQueryValueEx(parmKey, "daemonCheckTokenInterval", NULL, NULL,
463 (BYTE *) &dummy, &dummyLen);
464 if (code == ERROR_SUCCESS && dummy)
465 cm_daemonTokenCheckInterval = dummy;
466 afsi_log("daemonCheckTokenInterval is %d", cm_daemonTokenCheckInterval);
468 dummyLen = sizeof(DWORD);
469 code = RegQueryValueEx(parmKey, "daemonCheckOfflineVolInterval", NULL, NULL,
470 (BYTE *) &dummy, &dummyLen);
471 if (code == ERROR_SUCCESS && dummy)
472 cm_daemonCheckOfflineVolInterval = dummy;
473 afsi_log("daemonCheckOfflineVolInterval is %d", cm_daemonCheckOfflineVolInterval);
475 dummyLen = sizeof(DWORD);
476 code = RegQueryValueEx(parmKey, "daemonRDRShakeExtentsInterval", NULL, NULL,
477 (BYTE *) &dummy, &dummyLen);
478 if (code == ERROR_SUCCESS && dummy)
479 cm_daemonRDRShakeExtentsInterval = dummy;
480 afsi_log("daemonRDRShakeExtentsInterval is %d", cm_daemonRDRShakeExtentsInterval);
482 dummyLen = sizeof(DWORD);
483 code = RegQueryValueEx(parmKey, "daemonPerformanceTuningInterval", NULL, NULL,
484 (BYTE *) &dummy, &dummyLen);
485 if (code == ERROR_SUCCESS)
486 cm_daemonPerformanceTuningInterval = dummy;
487 afsi_log("daemonPerformanceTuningInterval is %d", cm_daemonPerformanceTuningInterval);
489 dummyLen = sizeof(DWORD);
490 code = RegQueryValueEx(parmKey, "daemonRankServerInterval", NULL, NULL,
491 (BYTE *) &dummy, &dummyLen);
492 if (code == ERROR_SUCCESS && dummy)
493 cm_daemonRankServerInterval = dummy;
494 afsi_log("daemonRankServerInterval is %d", cm_daemonRankServerInterval);
496 dummyLen = sizeof(DWORD);
497 code = RegQueryValueEx(parmKey, "daemonAfsdHookReloadInterval", NULL, NULL,
498 (BYTE *) &dummy, &dummyLen);
499 if (code == ERROR_SUCCESS && dummy)
500 cm_daemonAfsdHookReloadInterval = dummy;
501 afsi_log("daemonAfsdHookReloadInterval is %d", cm_daemonAfsdHookReloadInterval);
503 RegCloseKey(parmKey);
505 if (cm_daemonPerformanceTuningInterval)
506 cm_PerformanceTuningInit();
509 /* periodic lock check daemon */
510 void * cm_LockDaemon(void * vparm)
513 time_t lastLockCheck;
514 char * name = "cm_LockDaemon_ShutdownEvent";
516 cm_LockDaemon_ShutdownEvent = thrd_CreateEvent(NULL, FALSE, FALSE, name);
517 if ( GetLastError() == ERROR_ALREADY_EXISTS )
518 afsi_log("Event Object Already Exists: %s", name);
521 lastLockCheck = now - cm_daemonCheckLockInterval/2 + (rand() % cm_daemonCheckLockInterval);
523 while (daemon_ShutdownFlag == 0) {
524 if (powerStateSuspended) {
531 if (now > lastLockCheck + cm_daemonCheckLockInterval &&
532 daemon_ShutdownFlag == 0 &&
533 powerStateSuspended == 0) {
536 if (daemon_ShutdownFlag == 1)
540 thrd_Sleep(1000); /* sleep 1 second */
542 thrd_SetEvent(cm_LockDaemon_ShutdownEvent);
547 /* periodic check daemon */
548 void * cm_Daemon(void *vparm)
552 time_t lastCBExpirationCheck;
553 time_t lastVolCBRenewalCheck;
554 time_t lastDownServerCheck;
555 time_t lastUpServerCheck;
556 time_t lastTokenCacheCheck;
557 time_t lastBusyVolCheck;
558 time_t lastPerformanceCheck;
559 time_t lastServerRankCheck;
560 time_t lastRDRShakeExtents;
561 time_t lastAfsdHookReload;
562 time_t lastEAccesCheck;
566 HMODULE hHookDll = NULL;
567 AfsdDaemonHook daemonHook = NULL;
568 char * name = "cm_Daemon_ShutdownEvent";
569 int configureFirewall = IsWindowsFirewallPresent();
570 int bAddrChangeCheck = 0;
572 cm_Daemon_ShutdownEvent = thrd_CreateEvent(NULL, FALSE, FALSE, name);
573 if ( GetLastError() == ERROR_ALREADY_EXISTS )
574 afsi_log("Event Object Already Exists: %s", name);
576 if (!configureFirewall) {
577 afsi_log("No Windows Firewall detected");
580 if (cm_freelanceEnabled && cm_freelanceImportCellServDB)
581 cm_FreelanceImportCellServDB();
583 /* ping all file servers, up or down, with unauthenticated connection,
584 * to find out whether we have all our callbacks from the server still.
585 * Also, ping down VLDBs.
588 * Seed the random number generator with our own address, so that
589 * clients starting at the same time don't all do vol checks at the
592 gethostname(thostName, sizeof(thostName));
593 thp = gethostbyname(thostName);
594 if (thp == NULL) /* In djgpp, gethostname returns the netbios
595 name of the machine. gethostbyname will fail
596 looking this up if it differs from DNS name. */
599 memcpy(&code, thp->h_addr_list[0], 4);
603 cm_DaemonCheckInit();
606 lastVolCheck = now - cm_daemonCheckVolInterval/2 + (rand() % cm_daemonCheckVolInterval);
607 lastCBExpirationCheck = now - cm_daemonCheckCBInterval/2 + (rand() % cm_daemonCheckCBInterval);
608 if (cm_daemonCheckVolCBInterval)
609 lastVolCBRenewalCheck = now - cm_daemonCheckVolCBInterval/2 + (rand() % cm_daemonCheckVolCBInterval);
610 lastDownServerCheck = now - cm_daemonCheckDownInterval/2 + (rand() % cm_daemonCheckDownInterval);
611 lastUpServerCheck = now - cm_daemonCheckUpInterval/2 + (rand() % cm_daemonCheckUpInterval);
612 lastTokenCacheCheck = now - cm_daemonTokenCheckInterval/2 + (rand() % cm_daemonTokenCheckInterval);
613 if (cm_daemonCheckOfflineVolInterval)
614 lastBusyVolCheck = now - cm_daemonCheckOfflineVolInterval/2 * (rand() % cm_daemonCheckOfflineVolInterval);
615 if (cm_daemonPerformanceTuningInterval)
616 lastPerformanceCheck = now - cm_daemonPerformanceTuningInterval/2 * (rand() % cm_daemonPerformanceTuningInterval);
617 lastServerRankCheck = now - cm_daemonRankServerInterval/2 * (rand() % cm_daemonRankServerInterval);
618 if (cm_daemonRDRShakeExtentsInterval)
619 lastRDRShakeExtents = now - cm_daemonRDRShakeExtentsInterval/2 * (rand() % cm_daemonRDRShakeExtentsInterval);
620 if (cm_daemonAfsdHookReloadInterval)
621 lastAfsdHookReload = now;
622 lastEAccesCheck = now;
624 hHookDll = cm_LoadAfsdHookLib();
626 daemonHook = ( AfsdDaemonHook ) GetProcAddress(hHookDll, AFSD_DAEMON_HOOK);
628 while (daemon_ShutdownFlag == 0) {
629 if (powerStateSuspended) {
633 /* check to see if the listener threads halted due to network
634 * disconnect or other issues. If so, attempt to restart them.
636 smb_RestartListeners(0);
638 if (daemon_ShutdownFlag == 1)
641 if (configureFirewall) {
642 /* Open Microsoft Firewall to allow in port 7001 */
643 switch (icf_CheckAndAddAFSPorts(AFS_PORTSET_CLIENT)) {
645 afsi_log("Windows Firewall Configuration succeeded");
646 configureFirewall = 0;
649 afsi_log("Invalid Windows Firewall Port Set");
652 afsi_log("Unable to open Windows Firewall Profile");
655 afsi_log("Unable to create/modify Windows Firewall Port entries");
658 afsi_log("Unknown Windows Firewall Configuration error");
662 /* find out what time it is */
665 /* Determine whether an address change took place that we need to respond to */
666 if (bAddrChangeCheck)
667 bAddrChangeCheck = 0;
669 if (lastIPAddrChange != 0 && lastIPAddrChange + 2500 < now) {
670 bAddrChangeCheck = 1;
671 lastIPAddrChange = 0;
674 /* check down servers */
675 if ((bAddrChangeCheck || now > lastDownServerCheck + cm_daemonCheckDownInterval) &&
676 daemon_ShutdownFlag == 0 &&
677 powerStateSuspended == 0) {
678 lastDownServerCheck = now;
679 osi_Log0(afsd_logp, "cm_Daemon CheckDownServers");
680 cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS, NULL);
681 if (daemon_ShutdownFlag == 1)
686 if (bAddrChangeCheck &&
687 daemon_ShutdownFlag == 0 &&
688 powerStateSuspended == 0) {
689 cm_ForceNewConnectionsAllServers();
692 /* check up servers */
693 if ((bAddrChangeCheck || now > lastUpServerCheck + cm_daemonCheckUpInterval) &&
694 daemon_ShutdownFlag == 0 &&
695 powerStateSuspended == 0) {
696 lastUpServerCheck = now;
697 osi_Log0(afsd_logp, "cm_Daemon CheckUpServers");
698 cm_CheckServers(CM_FLAG_CHECKUPSERVERS, NULL);
699 if (daemon_ShutdownFlag == 1)
704 if (bAddrChangeCheck &&
705 daemon_ShutdownFlag == 0 &&
706 powerStateSuspended == 0) {
708 cm_VolStatus_Network_Addr_Change();
712 * Once every five minutes inspect the volume list and enforce
713 * the volume location expiration time.
715 if (now > lastVolCheck + 300 &&
716 daemon_ShutdownFlag == 0 &&
717 powerStateSuspended == 0) {
719 cm_RefreshVolumes(cm_daemonCheckVolInterval);
720 if (daemon_ShutdownFlag == 1)
725 /* Rank all up servers */
726 if ((now > lastServerRankCheck + cm_daemonRankServerInterval) &&
727 daemon_ShutdownFlag == 0 &&
728 powerStateSuspended == 0) {
729 lastServerRankCheck = now;
730 osi_Log0(afsd_logp, "cm_Daemon RankServer");
732 if(daemon_ShutdownFlag == 1)
737 if (cm_daemonCheckVolCBInterval &&
738 now > lastVolCBRenewalCheck + cm_daemonCheckVolCBInterval &&
739 daemon_ShutdownFlag == 0 &&
740 powerStateSuspended == 0) {
741 lastVolCBRenewalCheck = now;
742 cm_VolumeRenewROCallbacks();
743 if (daemon_ShutdownFlag == 1)
748 if ((bAddrChangeCheck || (cm_daemonCheckOfflineVolInterval &&
749 now > lastBusyVolCheck + cm_daemonCheckOfflineVolInterval)) &&
750 daemon_ShutdownFlag == 0 &&
751 powerStateSuspended == 0) {
752 lastBusyVolCheck = now;
753 cm_CheckOfflineVolumes();
754 if (daemon_ShutdownFlag == 1)
759 if (now > lastCBExpirationCheck + cm_daemonCheckCBInterval &&
760 daemon_ShutdownFlag == 0 &&
761 powerStateSuspended == 0) {
762 lastCBExpirationCheck = now;
763 cm_CheckCBExpiration();
764 if (daemon_ShutdownFlag == 1)
769 if (now > lastTokenCacheCheck + cm_daemonTokenCheckInterval &&
770 daemon_ShutdownFlag == 0 &&
771 powerStateSuspended == 0) {
772 lastTokenCacheCheck = now;
773 cm_CheckTokenCache(now);
774 if (daemon_ShutdownFlag == 1)
779 if (now > lastEAccesCheck + cm_daemonEAccesCheckInterval &&
780 daemon_ShutdownFlag == 0 &&
781 powerStateSuspended == 0) {
782 lastEAccesCheck = now;
783 cm_EAccesClearOutdatedEntries();
784 if (daemon_ShutdownFlag == 1)
789 if (cm_daemonRDRShakeExtentsInterval &&
790 now > lastRDRShakeExtents + cm_daemonRDRShakeExtentsInterval &&
791 daemon_ShutdownFlag == 0 &&
792 powerStateSuspended == 0) {
795 lastRDRShakeExtents = now;
796 if (cm_data.buf_redirCount > cm_data.buf_freeCount)
797 buf_RDRShakeSomeExtentsFree(&req, FALSE, 10 /* seconds */);
798 if (daemon_ShutdownFlag == 1)
803 /* allow an exit to be called prior to stopping the service */
804 if (cm_daemonAfsdHookReloadInterval &&
805 lastAfsdHookReload != 0 && lastAfsdHookReload < now) {
807 FreeLibrary(hHookDll);
812 hHookDll = cm_LoadAfsdHookLib();
814 daemonHook = ( AfsdDaemonHook ) GetProcAddress(hHookDll, AFSD_DAEMON_HOOK);
819 BOOL hookRc = daemonHook();
823 SetEvent(WaitToTerminate);
826 if (daemon_ShutdownFlag == 1) {
832 if (cm_daemonPerformanceTuningInterval &&
833 now > lastPerformanceCheck + cm_daemonPerformanceTuningInterval &&
834 daemon_ShutdownFlag == 0 &&
835 powerStateSuspended == 0) {
836 lastPerformanceCheck = now;
837 cm_PerformanceTuningCheck();
838 if (daemon_ShutdownFlag == 1)
844 * sleep .5 seconds. if the thread blocks for a long time
845 * we risk not being able to close the cache before Windows
846 * kills our process during system shutdown.
852 FreeLibrary(hHookDll);
855 thrd_SetEvent(cm_Daemon_ShutdownEvent);
860 void cm_DaemonShutdown(void)
865 daemon_ShutdownFlag = 1;
867 /* wait for shutdown */
868 for ( i=0; i<cm_nDaemons; i++) {
869 osi_Wakeup((LONG_PTR) &cm_daemons[i].head);
870 if (cm_BkgDaemon_ShutdownEvent[i])
871 code = thrd_WaitForSingleObject_Event(cm_BkgDaemon_ShutdownEvent[i], INFINITE);
874 if (cm_Daemon_ShutdownEvent)
875 code = thrd_WaitForSingleObject_Event(cm_Daemon_ShutdownEvent, INFINITE);
877 if (cm_LockDaemon_ShutdownEvent)
878 code = thrd_WaitForSingleObject_Event(cm_LockDaemon_ShutdownEvent, INFINITE);
882 * Do not waste precious time waiting for the ipaddr daemon to shutdown.
883 * When it does it means we have lost our network connection and we need
884 * it during cache shutdown in order to notify the file servers that this
885 * client is giving up all callbacks.
887 if (cm_IPAddrDaemon_ShutdownEvent)
888 code = thrd_WaitForSingleObject_Event(cm_IPAddrDaemon_ShutdownEvent, INFINITE);
892 void cm_InitDaemon(int nDaemons)
894 static osi_once_t once;
896 pthread_attr_t tattr;
900 pthread_attr_init(&tattr);
901 pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
903 if (nDaemons > CM_MAX_DAEMONS)
904 cm_nDaemons = CM_MAX_DAEMONS;
905 else if (nDaemons < CM_MIN_DAEMONS)
906 cm_nDaemons = CM_MIN_DAEMONS;
908 cm_nDaemons = (nDaemons / 2) * 2; /* must be divisible by two */
910 if (osi_Once(&once)) {
911 /* creating IP Address Change monitor daemon */
912 pstatus = pthread_create(&phandle, &tattr, cm_IpAddrDaemon, 0);
913 osi_assertx(pstatus == 0, "cm_IpAddrDaemon thread creation failure");
915 /* creating pinging daemon */
916 pstatus = pthread_create(&phandle, &tattr, cm_Daemon, 0);
917 osi_assertx(pstatus == 0, "cm_Daemon thread creation failure");
919 pstatus = pthread_create(&phandle, &tattr, cm_LockDaemon, 0);
920 osi_assertx(pstatus == 0, "cm_LockDaemon thread creation failure");
922 cm_daemons = malloc(nDaemons * sizeof(daemon_state_t));
924 for(i=0; i < cm_nDaemons; i++) {
925 lock_InitializeRWLock(&cm_daemons[i].lock, "cm_daemonLock",
926 LOCK_HIERARCHY_DAEMON_GLOBAL);
927 cm_daemons[i].head = cm_daemons[i].tail = NULL;
928 cm_daemons[i].queueCount=0;
929 cm_daemons[i].completeCount=0;
930 cm_daemons[i].retryCount=0;
931 cm_daemons[i].errorCount=0;
932 pstatus = pthread_create(&phandle, &tattr, cm_BkgDaemon, (LPVOID)(LONG_PTR)i);
933 osi_assertx(pstatus == 0, "cm_BkgDaemon thread creation failure");
938 pthread_attr_destroy(&tattr);