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;
46 osi_rwlock_t *cm_daemonLockp;
47 afs_uint64 *cm_bkgQueueCountp; /* # of queued requests */
48 cm_bkgRequest_t **cm_bkgListpp; /* first elt in the list of requests */
49 cm_bkgRequest_t **cm_bkgListEndpp; /* last elt in the list of requests */
51 extern int powerStateSuspended;
52 int daemon_ShutdownFlag = 0;
54 static time_t lastIPAddrChange = 0;
56 static EVENT_HANDLE cm_Daemon_ShutdownEvent = NULL;
57 static EVENT_HANDLE cm_LockDaemon_ShutdownEvent = NULL;
58 static EVENT_HANDLE cm_IPAddrDaemon_ShutdownEvent = NULL;
59 static EVENT_HANDLE cm_BkgDaemon_ShutdownEvent[CM_MAX_DAEMONS] =
60 {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
62 void * cm_IpAddrDaemon(void * vparm)
64 extern void smb_CheckVCs(void);
65 char * name = "cm_IPAddrDaemon_ShutdownEvent";
67 cm_IPAddrDaemon_ShutdownEvent = thrd_CreateEvent(NULL, FALSE, FALSE, name);
68 if ( GetLastError() == ERROR_ALREADY_EXISTS )
69 afsi_log("Event Object Already Exists: %s", name);
71 rx_StartClientThread();
73 while (daemon_ShutdownFlag == 0) {
76 thrd_SetEvent(cm_IPAddrDaemon_ShutdownEvent);
77 Result = NotifyAddrChange(NULL,NULL);
78 if (Result == NO_ERROR && daemon_ShutdownFlag == 0) {
79 lastIPAddrChange = osi_Time();
81 smb_SetLanAdapterChangeDetected();
82 cm_SetLanAdapterChangeDetected();
83 thrd_ResetEvent(cm_IPAddrDaemon_ShutdownEvent);
87 thrd_SetEvent(cm_IPAddrDaemon_ShutdownEvent);
92 afs_int32 cm_RequestWillBlock(cm_bkgRequest_t *rp)
94 afs_int32 willBlock = 0;
96 if (rp->procp == cm_BkgStore) {
98 * If the datastoring flag is set, it means that another
99 * thread is already performing an exclusive store operation
100 * on this file. The exclusive state will be cleared once
101 * the file server locks the vnode. Therefore, at most two
102 * threads can be actively involved in storing data at a time
105 lock_ObtainRead(&rp->scp->rw);
106 willBlock = (rp->scp->flags & CM_SCACHEFLAG_DATASTORING);
107 lock_ReleaseRead(&rp->scp->rw);
109 else if (rp->procp == RDR_BkgFetch || rp->procp == cm_BkgPrefetch) {
111 * Attempt to determine if there is a conflict on the requested
112 * range of the file. If the first in the range does not exist
113 * in the cache assume there is no conflict. If the buffer does
114 * exist, check to see if an I/O operation is in progress
115 * by using the writing and reading flags as an indicator.
118 cm_buf_t *bufp = NULL;
120 base.LowPart = rp->p1;
121 base.HighPart = rp->p2;
123 bufp = buf_Find(&rp->scp->fid, &base);
125 willBlock = (bufp->flags & (CM_BUF_WRITING|CM_BUF_READING));
133 void * cm_BkgDaemon(void * vparm)
138 long daemonID = (long)(LONG_PTR)vparm;
140 snprintf(name, sizeof(name), "cm_BkgDaemon_ShutdownEvent%u", daemonID);
142 cm_BkgDaemon_ShutdownEvent[daemonID] = thrd_CreateEvent(NULL, FALSE, FALSE, name);
143 if ( GetLastError() == ERROR_ALREADY_EXISTS )
144 afsi_log("Event Object Already Exists: %s", name);
146 rx_StartClientThread();
148 lock_ObtainWrite(&cm_daemonLockp[daemonID]);
149 while (daemon_ShutdownFlag == 0) {
152 if (powerStateSuspended) {
156 if (!cm_bkgListEndpp[daemonID]) {
157 osi_SleepW((LONG_PTR)&cm_bkgListpp[daemonID], &cm_daemonLockp[daemonID]);
158 lock_ObtainWrite(&cm_daemonLockp[daemonID]);
162 /* we found a request */
163 for (rp = cm_bkgListEndpp[daemonID]; rp; rp = (cm_bkgRequest_t *) osi_QPrev(&rp->q))
165 if (rp->scp->flags & CM_SCACHEFLAG_DELETED)
169 * If the request has active I/O such that this worker would
170 * be forced to block, leave the request in the queue and move
171 * on to one that might be available for servicing.
173 if (cm_RequestWillBlock(rp)) {
178 if (cm_ServerAvailable(&rp->scp->fid, rp->userp))
184 * Couldn't find a request that we could process at the
185 * current time. If there were requests that would cause
186 * the worker to block, sleep for 25ms so it can promptly
187 * respond when it is available. Otherwise, sleep for 1s.
189 * This polling cycle needs to be replaced with a proper
190 * producer/consumer dynamic worker pool.
192 osi_Log2(afsd_logp,"cm_BkgDaemon[%u] sleeping %dms all tasks would block",
193 daemonID, willBlock ? 100 : 1000);
195 lock_ReleaseWrite(&cm_daemonLockp[daemonID]);
196 Sleep(willBlock ? 100 : 1000);
197 lock_ObtainWrite(&cm_daemonLockp[daemonID]);
201 osi_QRemoveHT((osi_queue_t **) &cm_bkgListpp[daemonID], (osi_queue_t **) &cm_bkgListEndpp[daemonID], &rp->q);
202 osi_assertx(cm_bkgQueueCountp[daemonID]-- > 0, "cm_bkgQueueCount 0");
203 lock_ReleaseWrite(&cm_daemonLockp[daemonID]);
205 osi_Log2(afsd_logp,"cm_BkgDaemon[%u] processing request 0x%p", daemonID, rp);
207 if (rp->scp->flags & CM_SCACHEFLAG_DELETED) {
208 osi_Log2(afsd_logp,"cm_BkgDaemon[%u] DELETED scp 0x%x", daemonID, rp->scp);
209 code = CM_ERROR_BADFD;
211 #ifdef DEBUG_REFCOUNT
212 osi_Log3(afsd_logp,"cm_BkgDaemon[%u] (before) scp 0x%x ref %d", daemonID, rp->scp, rp->scp->refCount);
214 code = (*rp->procp)(rp->scp, rp->p1, rp->p2, rp->p3, rp->p4, rp->userp, &rp->req);
215 #ifdef DEBUG_REFCOUNT
216 osi_Log3(afsd_logp,"cm_BkgDaemon[%u] (after) scp 0x%x ref %d", daemonID, rp->scp, rp->scp->refCount);
221 * Keep the following list synchronized with the
222 * error code list in cm_BkgStore.
223 * cm_SyncOpDone(CM_SCACHESYNC_ASYNCSTORE) will be called there unless
224 * one of these errors has occurred.
227 case CM_ERROR_TIMEDOUT: /* or server restarting */
229 case CM_ERROR_WOULDBLOCK:
230 case CM_ERROR_ALLBUSY:
231 case CM_ERROR_ALLDOWN:
232 case CM_ERROR_ALLOFFLINE:
233 case CM_ERROR_PARTIALWRITE:
234 if (rp->procp == cm_BkgStore ||
235 rp->procp == RDR_BkgFetch) {
237 "cm_BkgDaemon[%u] re-queueing failed request 0x%p code 0x%x",
239 lock_ObtainWrite(&cm_daemonLockp[daemonID]);
240 cm_bkgQueueCountp[daemonID]++;
241 osi_QAddT((osi_queue_t **) &cm_bkgListpp[daemonID], (osi_queue_t **)&cm_bkgListEndpp[daemonID], &rp->q);
243 } /* otherwise fall through */
244 case 0: /* success */
245 default: /* other error */
247 osi_Log2(afsd_logp,"cm_BkgDaemon[%u] SUCCESS: request 0x%p", daemonID, rp);
249 osi_Log3(afsd_logp,"cm_BkgDaemon[%u] FAILED: request dropped 0x%p code 0x%x",
252 cm_ReleaseUser(rp->userp);
253 cm_ReleaseSCache(rp->scp);
255 lock_ObtainWrite(&cm_daemonLockp[daemonID]);
258 lock_ReleaseWrite(&cm_daemonLockp[daemonID]);
259 thrd_SetEvent(cm_BkgDaemon_ShutdownEvent[daemonID]);
264 void cm_QueueBKGRequest(cm_scache_t *scp, cm_bkgProc_t *procp, afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, afs_uint32 p4,
265 cm_user_t *userp, cm_req_t *reqp)
268 afs_uint32 daemonID = scp->fid.hash % cm_nDaemons;
270 rp = malloc(sizeof(*rp));
271 memset(rp, 0, sizeof(*rp));
284 lock_ObtainWrite(&cm_daemonLockp[daemonID]);
285 cm_bkgQueueCountp[daemonID]++;
286 osi_QAddH((osi_queue_t **) &cm_bkgListpp[daemonID], (osi_queue_t **)&cm_bkgListEndpp[daemonID], &rp->q);
287 lock_ReleaseWrite(&cm_daemonLockp[daemonID]);
289 osi_Wakeup((LONG_PTR) &cm_bkgListpp[daemonID]);
293 IsWindowsFirewallPresent(void)
298 BOOLEAN result = FALSE;
299 LPQUERY_SERVICE_CONFIG pConfig = NULL;
303 /* Open services manager */
304 scm = OpenSCManager(NULL, NULL, GENERIC_READ);
305 if (!scm) return FALSE;
307 /* Open Windows Firewall service */
308 svc = OpenService(scm, "MpsSvc", SERVICE_QUERY_CONFIG);
310 afsi_log("MpsSvc Service could not be opened for query: 0x%x", GetLastError());
311 svc = OpenService(scm, "SharedAccess", SERVICE_QUERY_CONFIG);
313 afsi_log("SharedAccess Service could not be opened for query: 0x%x", GetLastError());
318 /* Query Windows Firewall service config, first just to get buffer size */
319 /* Expected to fail, so don't test return value */
320 (void) QueryServiceConfig(svc, NULL, 0, &BufSize);
321 status = GetLastError();
322 if (status != ERROR_INSUFFICIENT_BUFFER)
325 /* Allocate buffer */
326 pConfig = (LPQUERY_SERVICE_CONFIG)GlobalAlloc(GMEM_FIXED,BufSize);
330 /* Query Windows Firewall service config, this time for real */
331 flag = QueryServiceConfig(svc, pConfig, BufSize, &BufSize);
333 afsi_log("QueryServiceConfig failed: 0x%x", GetLastError());
337 /* Is it autostart? */
338 afsi_log("AutoStart 0x%x", pConfig->dwStartType);
339 if (pConfig->dwStartType < SERVICE_DEMAND_START)
345 CloseServiceHandle(svc);
347 CloseServiceHandle(scm);
353 cm_DaemonCheckInit(void)
360 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
361 0, KEY_QUERY_VALUE, &parmKey);
365 dummyLen = sizeof(DWORD);
366 code = RegQueryValueEx(parmKey, "daemonCheckDownInterval", NULL, NULL,
367 (BYTE *) &dummy, &dummyLen);
368 if (code == ERROR_SUCCESS && dummy)
369 cm_daemonCheckDownInterval = dummy;
370 afsi_log("daemonCheckDownInterval is %d", cm_daemonCheckDownInterval);
372 dummyLen = sizeof(DWORD);
373 code = RegQueryValueEx(parmKey, "daemonCheckUpInterval", NULL, NULL,
374 (BYTE *) &dummy, &dummyLen);
375 if (code == ERROR_SUCCESS && dummy)
376 cm_daemonCheckUpInterval = dummy;
377 afsi_log("daemonCheckUpInterval is %d", cm_daemonCheckUpInterval);
379 dummyLen = sizeof(DWORD);
380 code = RegQueryValueEx(parmKey, "daemonCheckVolInterval", NULL, NULL,
381 (BYTE *) &dummy, &dummyLen);
382 if (code == ERROR_SUCCESS && dummy)
383 cm_daemonCheckVolInterval = dummy;
384 afsi_log("daemonCheckVolInterval is %d", cm_daemonCheckVolInterval);
386 dummyLen = sizeof(DWORD);
387 code = RegQueryValueEx(parmKey, "daemonCheckCBInterval", NULL, NULL,
388 (BYTE *) &dummy, &dummyLen);
389 if (code == ERROR_SUCCESS && dummy)
390 cm_daemonCheckCBInterval = dummy;
391 afsi_log("daemonCheckCBInterval is %d", cm_daemonCheckCBInterval);
393 dummyLen = sizeof(DWORD);
394 code = RegQueryValueEx(parmKey, "daemonCheckVolCBInterval", NULL, NULL,
395 (BYTE *) &dummy, &dummyLen);
396 if (code == ERROR_SUCCESS && dummy)
397 cm_daemonCheckVolCBInterval = dummy;
398 afsi_log("daemonCheckVolCBInterval is %d", cm_daemonCheckVolCBInterval);
400 dummyLen = sizeof(DWORD);
401 code = RegQueryValueEx(parmKey, "daemonCheckLockInterval", NULL, NULL,
402 (BYTE *) &dummy, &dummyLen);
403 if (code == ERROR_SUCCESS && dummy)
404 cm_daemonCheckLockInterval = dummy;
405 afsi_log("daemonCheckLockInterval is %d", cm_daemonCheckLockInterval);
407 dummyLen = sizeof(DWORD);
408 code = RegQueryValueEx(parmKey, "daemonCheckTokenInterval", NULL, NULL,
409 (BYTE *) &dummy, &dummyLen);
410 if (code == ERROR_SUCCESS && dummy)
411 cm_daemonTokenCheckInterval = dummy;
412 afsi_log("daemonCheckTokenInterval is %d", cm_daemonTokenCheckInterval);
414 dummyLen = sizeof(DWORD);
415 code = RegQueryValueEx(parmKey, "daemonCheckOfflineVolInterval", NULL, NULL,
416 (BYTE *) &dummy, &dummyLen);
417 if (code == ERROR_SUCCESS && dummy)
418 cm_daemonCheckOfflineVolInterval = dummy;
419 afsi_log("daemonCheckOfflineVolInterval is %d", cm_daemonCheckOfflineVolInterval);
421 dummyLen = sizeof(DWORD);
422 code = RegQueryValueEx(parmKey, "daemonRDRShakeExtentsInterval", NULL, NULL,
423 (BYTE *) &dummy, &dummyLen);
424 if (code == ERROR_SUCCESS && dummy)
425 cm_daemonRDRShakeExtentsInterval = dummy;
426 afsi_log("daemonRDRShakeExtentsInterval is %d", cm_daemonRDRShakeExtentsInterval);
428 dummyLen = sizeof(DWORD);
429 code = RegQueryValueEx(parmKey, "daemonPerformanceTuningInterval", NULL, NULL,
430 (BYTE *) &dummy, &dummyLen);
431 if (code == ERROR_SUCCESS)
432 cm_daemonPerformanceTuningInterval = dummy;
433 afsi_log("daemonPerformanceTuningInterval is %d", cm_daemonPerformanceTuningInterval);
435 dummyLen = sizeof(DWORD);
436 code = RegQueryValueEx(parmKey, "daemonRankServerInterval", NULL, NULL,
437 (BYTE *) &dummy, &dummyLen);
438 if (code == ERROR_SUCCESS && dummy)
439 cm_daemonRankServerInterval = dummy;
440 afsi_log("daemonRankServerInterval is %d", cm_daemonRankServerInterval);
442 dummyLen = sizeof(DWORD);
443 code = RegQueryValueEx(parmKey, "daemonAfsdHookReloadInterval", NULL, NULL,
444 (BYTE *) &dummy, &dummyLen);
445 if (code == ERROR_SUCCESS && dummy)
446 cm_daemonAfsdHookReloadInterval = dummy;
447 afsi_log("daemonAfsdHookReloadInterval is %d", cm_daemonAfsdHookReloadInterval);
449 RegCloseKey(parmKey);
451 if (cm_daemonPerformanceTuningInterval)
452 cm_PerformanceTuningInit();
455 /* periodic lock check daemon */
456 void * cm_LockDaemon(void * vparm)
459 time_t lastLockCheck;
460 char * name = "cm_LockDaemon_ShutdownEvent";
462 cm_LockDaemon_ShutdownEvent = thrd_CreateEvent(NULL, FALSE, FALSE, name);
463 if ( GetLastError() == ERROR_ALREADY_EXISTS )
464 afsi_log("Event Object Already Exists: %s", name);
467 lastLockCheck = now - cm_daemonCheckLockInterval/2 + (rand() % cm_daemonCheckLockInterval);
469 while (daemon_ShutdownFlag == 0) {
470 if (powerStateSuspended) {
477 if (now > lastLockCheck + cm_daemonCheckLockInterval &&
478 daemon_ShutdownFlag == 0 &&
479 powerStateSuspended == 0) {
482 if (daemon_ShutdownFlag == 1)
486 thrd_Sleep(1000); /* sleep 1 second */
488 thrd_SetEvent(cm_LockDaemon_ShutdownEvent);
493 /* periodic check daemon */
494 void * cm_Daemon(void *vparm)
498 time_t lastCBExpirationCheck;
499 time_t lastVolCBRenewalCheck;
500 time_t lastDownServerCheck;
501 time_t lastUpServerCheck;
502 time_t lastTokenCacheCheck;
503 time_t lastBusyVolCheck;
504 time_t lastPerformanceCheck;
505 time_t lastServerRankCheck;
506 time_t lastRDRShakeExtents;
507 time_t lastAfsdHookReload;
511 HMODULE hHookDll = NULL;
512 AfsdDaemonHook daemonHook = NULL;
513 char * name = "cm_Daemon_ShutdownEvent";
514 int configureFirewall = IsWindowsFirewallPresent();
515 int bAddrChangeCheck = 0;
517 cm_Daemon_ShutdownEvent = thrd_CreateEvent(NULL, FALSE, FALSE, name);
518 if ( GetLastError() == ERROR_ALREADY_EXISTS )
519 afsi_log("Event Object Already Exists: %s", name);
521 if (!configureFirewall) {
522 afsi_log("No Windows Firewall detected");
525 if (cm_freelanceEnabled && cm_freelanceImportCellServDB)
526 cm_FreelanceImportCellServDB();
528 /* ping all file servers, up or down, with unauthenticated connection,
529 * to find out whether we have all our callbacks from the server still.
530 * Also, ping down VLDBs.
533 * Seed the random number generator with our own address, so that
534 * clients starting at the same time don't all do vol checks at the
537 gethostname(thostName, sizeof(thostName));
538 thp = gethostbyname(thostName);
539 if (thp == NULL) /* In djgpp, gethostname returns the netbios
540 name of the machine. gethostbyname will fail
541 looking this up if it differs from DNS name. */
544 memcpy(&code, thp->h_addr_list[0], 4);
548 cm_DaemonCheckInit();
551 lastVolCheck = now - cm_daemonCheckVolInterval/2 + (rand() % cm_daemonCheckVolInterval);
552 lastCBExpirationCheck = now - cm_daemonCheckCBInterval/2 + (rand() % cm_daemonCheckCBInterval);
553 if (cm_daemonCheckVolCBInterval)
554 lastVolCBRenewalCheck = now - cm_daemonCheckVolCBInterval/2 + (rand() % cm_daemonCheckVolCBInterval);
555 lastDownServerCheck = now - cm_daemonCheckDownInterval/2 + (rand() % cm_daemonCheckDownInterval);
556 lastUpServerCheck = now - cm_daemonCheckUpInterval/2 + (rand() % cm_daemonCheckUpInterval);
557 lastTokenCacheCheck = now - cm_daemonTokenCheckInterval/2 + (rand() % cm_daemonTokenCheckInterval);
558 if (cm_daemonCheckOfflineVolInterval)
559 lastBusyVolCheck = now - cm_daemonCheckOfflineVolInterval/2 * (rand() % cm_daemonCheckOfflineVolInterval);
560 if (cm_daemonPerformanceTuningInterval)
561 lastPerformanceCheck = now - cm_daemonPerformanceTuningInterval/2 * (rand() % cm_daemonPerformanceTuningInterval);
562 lastServerRankCheck = now - cm_daemonRankServerInterval/2 * (rand() % cm_daemonRankServerInterval);
563 if (cm_daemonRDRShakeExtentsInterval)
564 lastRDRShakeExtents = now - cm_daemonRDRShakeExtentsInterval/2 * (rand() % cm_daemonRDRShakeExtentsInterval);
565 if (cm_daemonAfsdHookReloadInterval)
566 lastAfsdHookReload = now;
568 hHookDll = cm_LoadAfsdHookLib();
570 daemonHook = ( AfsdDaemonHook ) GetProcAddress(hHookDll, AFSD_DAEMON_HOOK);
572 while (daemon_ShutdownFlag == 0) {
573 if (powerStateSuspended) {
577 /* check to see if the listener threads halted due to network
578 * disconnect or other issues. If so, attempt to restart them.
580 smb_RestartListeners(0);
582 if (daemon_ShutdownFlag == 1)
585 if (configureFirewall) {
586 /* Open Microsoft Firewall to allow in port 7001 */
587 switch (icf_CheckAndAddAFSPorts(AFS_PORTSET_CLIENT)) {
589 afsi_log("Windows Firewall Configuration succeeded");
590 configureFirewall = 0;
593 afsi_log("Invalid Windows Firewall Port Set");
596 afsi_log("Unable to open Windows Firewall Profile");
599 afsi_log("Unable to create/modify Windows Firewall Port entries");
602 afsi_log("Unknown Windows Firewall Configuration error");
606 /* find out what time it is */
609 /* Determine whether an address change took place that we need to respond to */
610 if (bAddrChangeCheck)
611 bAddrChangeCheck = 0;
613 if (lastIPAddrChange != 0 && lastIPAddrChange + 2500 < now) {
614 bAddrChangeCheck = 1;
615 lastIPAddrChange = 0;
618 /* check down servers */
619 if ((bAddrChangeCheck || now > lastDownServerCheck + cm_daemonCheckDownInterval) &&
620 daemon_ShutdownFlag == 0 &&
621 powerStateSuspended == 0) {
622 lastDownServerCheck = now;
623 osi_Log0(afsd_logp, "cm_Daemon CheckDownServers");
624 cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS, NULL);
625 if (daemon_ShutdownFlag == 1)
630 if (bAddrChangeCheck &&
631 daemon_ShutdownFlag == 0 &&
632 powerStateSuspended == 0) {
633 cm_ForceNewConnectionsAllServers();
636 /* check up servers */
637 if ((bAddrChangeCheck || now > lastUpServerCheck + cm_daemonCheckUpInterval) &&
638 daemon_ShutdownFlag == 0 &&
639 powerStateSuspended == 0) {
640 lastUpServerCheck = now;
641 osi_Log0(afsd_logp, "cm_Daemon CheckUpServers");
642 cm_CheckServers(CM_FLAG_CHECKUPSERVERS, NULL);
643 if (daemon_ShutdownFlag == 1)
648 if (bAddrChangeCheck &&
649 daemon_ShutdownFlag == 0 &&
650 powerStateSuspended == 0) {
652 cm_VolStatus_Network_Addr_Change();
656 * Once every five minutes inspect the volume list and enforce
657 * the volume location expiration time.
659 if (now > lastVolCheck + 300 &&
660 daemon_ShutdownFlag == 0 &&
661 powerStateSuspended == 0) {
663 cm_RefreshVolumes(cm_daemonCheckVolInterval);
664 if (daemon_ShutdownFlag == 1)
669 /* Rank all up servers */
670 if ((now > lastServerRankCheck + cm_daemonRankServerInterval) &&
671 daemon_ShutdownFlag == 0 &&
672 powerStateSuspended == 0) {
673 lastServerRankCheck = now;
674 osi_Log0(afsd_logp, "cm_Daemon RankServer");
676 if(daemon_ShutdownFlag == 1)
681 if (cm_daemonCheckVolCBInterval &&
682 now > lastVolCBRenewalCheck + cm_daemonCheckVolCBInterval &&
683 daemon_ShutdownFlag == 0 &&
684 powerStateSuspended == 0) {
685 lastVolCBRenewalCheck = now;
686 cm_VolumeRenewROCallbacks();
687 if (daemon_ShutdownFlag == 1)
692 if ((bAddrChangeCheck || (cm_daemonCheckOfflineVolInterval &&
693 now > lastBusyVolCheck + cm_daemonCheckOfflineVolInterval)) &&
694 daemon_ShutdownFlag == 0 &&
695 powerStateSuspended == 0) {
696 lastBusyVolCheck = now;
697 cm_CheckOfflineVolumes();
698 if (daemon_ShutdownFlag == 1)
703 if (now > lastCBExpirationCheck + cm_daemonCheckCBInterval &&
704 daemon_ShutdownFlag == 0 &&
705 powerStateSuspended == 0) {
706 lastCBExpirationCheck = now;
707 cm_CheckCBExpiration();
708 if (daemon_ShutdownFlag == 1)
713 if (now > lastTokenCacheCheck + cm_daemonTokenCheckInterval &&
714 daemon_ShutdownFlag == 0 &&
715 powerStateSuspended == 0) {
716 lastTokenCacheCheck = now;
717 cm_CheckTokenCache(now);
718 if (daemon_ShutdownFlag == 1)
723 if (cm_daemonRDRShakeExtentsInterval &&
724 now > lastRDRShakeExtents + cm_daemonRDRShakeExtentsInterval &&
725 daemon_ShutdownFlag == 0 &&
726 powerStateSuspended == 0) {
729 lastRDRShakeExtents = now;
730 if (cm_data.buf_redirCount > cm_data.buf_freeCount)
731 buf_RDRShakeSomeExtentsFree(&req, FALSE, 10 /* seconds */);
732 if (daemon_ShutdownFlag == 1)
737 /* allow an exit to be called prior to stopping the service */
738 if (cm_daemonAfsdHookReloadInterval &&
739 lastAfsdHookReload != 0 && lastAfsdHookReload < now) {
741 FreeLibrary(hHookDll);
746 hHookDll = cm_LoadAfsdHookLib();
748 daemonHook = ( AfsdDaemonHook ) GetProcAddress(hHookDll, AFSD_DAEMON_HOOK);
753 BOOL hookRc = daemonHook();
757 SetEvent(WaitToTerminate);
760 if (daemon_ShutdownFlag == 1) {
766 if (cm_daemonPerformanceTuningInterval &&
767 now > lastPerformanceCheck + cm_daemonPerformanceTuningInterval &&
768 daemon_ShutdownFlag == 0 &&
769 powerStateSuspended == 0) {
770 lastPerformanceCheck = now;
771 cm_PerformanceTuningCheck();
772 if (daemon_ShutdownFlag == 1)
778 * sleep .5 seconds. if the thread blocks for a long time
779 * we risk not being able to close the cache before Windows
780 * kills our process during system shutdown.
786 FreeLibrary(hHookDll);
789 thrd_SetEvent(cm_Daemon_ShutdownEvent);
794 void cm_DaemonShutdown(void)
799 daemon_ShutdownFlag = 1;
801 /* wait for shutdown */
802 for ( i=0; i<cm_nDaemons; i++) {
803 osi_Wakeup((LONG_PTR) &cm_bkgListpp[i]);
804 if (cm_BkgDaemon_ShutdownEvent[i])
805 code = thrd_WaitForSingleObject_Event(cm_BkgDaemon_ShutdownEvent[i], INFINITE);
808 if (cm_Daemon_ShutdownEvent)
809 code = thrd_WaitForSingleObject_Event(cm_Daemon_ShutdownEvent, INFINITE);
811 if (cm_LockDaemon_ShutdownEvent)
812 code = thrd_WaitForSingleObject_Event(cm_LockDaemon_ShutdownEvent, INFINITE);
816 * Do not waste precious time waiting for the ipaddr daemon to shutdown.
817 * When it does it means we have lost our network connection and we need
818 * it during cache shutdown in order to notify the file servers that this
819 * client is giving up all callbacks.
821 if (cm_IPAddrDaemon_ShutdownEvent)
822 code = thrd_WaitForSingleObject_Event(cm_IPAddrDaemon_ShutdownEvent, INFINITE);
826 void cm_InitDaemon(int nDaemons)
828 static osi_once_t once;
830 pthread_attr_t tattr;
834 pthread_attr_init(&tattr);
835 pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
837 cm_nDaemons = (nDaemons > CM_MAX_DAEMONS) ? CM_MAX_DAEMONS : nDaemons;
839 if (osi_Once(&once)) {
840 /* creating IP Address Change monitor daemon */
841 pstatus = pthread_create(&phandle, &tattr, cm_IpAddrDaemon, 0);
842 osi_assertx(pstatus == 0, "cm_IpAddrDaemon thread creation failure");
844 /* creating pinging daemon */
845 pstatus = pthread_create(&phandle, &tattr, cm_Daemon, 0);
846 osi_assertx(pstatus == 0, "cm_Daemon thread creation failure");
848 pstatus = pthread_create(&phandle, &tattr, cm_LockDaemon, 0);
849 osi_assertx(pstatus == 0, "cm_LockDaemon thread creation failure");
851 cm_bkgListpp = malloc(nDaemons * sizeof(void *));
852 cm_bkgListEndpp = malloc(nDaemons * sizeof(void *));
853 cm_bkgQueueCountp = malloc(nDaemons * sizeof(afs_uint64));
854 cm_daemonLockp = malloc(nDaemons * sizeof(osi_rwlock_t));
856 for(i=0; i < cm_nDaemons; i++) {
857 lock_InitializeRWLock(&cm_daemonLockp[i], "cm_daemonLock",
858 LOCK_HIERARCHY_DAEMON_GLOBAL);
859 cm_bkgListpp[i] = cm_bkgListEndpp[i] = NULL;
860 pstatus = pthread_create(&phandle, &tattr, cm_BkgDaemon, (LPVOID)(LONG_PTR)i);
861 osi_assertx(pstatus == 0, "cm_BkgDaemon thread creation failure");
866 pthread_attr_destroy(&tattr);