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 osi_rwlock_t *cm_daemonLockp;
48 afs_uint64 *cm_bkgQueueCountp; /* # of queued requests */
49 cm_bkgRequest_t **cm_bkgListpp; /* first elt in the list of requests */
50 cm_bkgRequest_t **cm_bkgListEndpp; /* last elt in the list of requests */
52 extern int powerStateSuspended;
53 int daemon_ShutdownFlag = 0;
55 static time_t lastIPAddrChange = 0;
57 static EVENT_HANDLE cm_Daemon_ShutdownEvent = NULL;
58 static EVENT_HANDLE cm_LockDaemon_ShutdownEvent = NULL;
59 static EVENT_HANDLE cm_IPAddrDaemon_ShutdownEvent = NULL;
60 static EVENT_HANDLE cm_BkgDaemon_ShutdownEvent[CM_MAX_DAEMONS] =
61 {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
63 void * cm_IpAddrDaemon(void * vparm)
65 extern void smb_CheckVCs(void);
66 char * name = "cm_IPAddrDaemon_ShutdownEvent";
68 cm_IPAddrDaemon_ShutdownEvent = thrd_CreateEvent(NULL, FALSE, FALSE, name);
69 if ( GetLastError() == ERROR_ALREADY_EXISTS )
70 afsi_log("Event Object Already Exists: %s", name);
72 rx_StartClientThread();
74 while (daemon_ShutdownFlag == 0) {
77 thrd_SetEvent(cm_IPAddrDaemon_ShutdownEvent);
78 Result = NotifyAddrChange(NULL,NULL);
79 if (Result == NO_ERROR && daemon_ShutdownFlag == 0) {
80 lastIPAddrChange = osi_Time();
82 smb_SetLanAdapterChangeDetected();
83 cm_SetLanAdapterChangeDetected();
84 thrd_ResetEvent(cm_IPAddrDaemon_ShutdownEvent);
86 cm_ServerClearRPCStats();
90 thrd_SetEvent(cm_IPAddrDaemon_ShutdownEvent);
95 afs_int32 cm_RequestWillBlock(cm_bkgRequest_t *rp)
97 afs_int32 willBlock = 0;
99 if (rp->procp == cm_BkgStore) {
101 * If the datastoring flag is set, it means that another
102 * thread is already performing an exclusive store operation
103 * on this file. The exclusive state will be cleared once
104 * the file server locks the vnode. Therefore, at most two
105 * threads can be actively involved in storing data at a time
108 lock_ObtainRead(&rp->scp->rw);
109 willBlock = (rp->scp->flags & CM_SCACHEFLAG_DATASTORING);
110 lock_ReleaseRead(&rp->scp->rw);
112 else if (rp->procp == RDR_BkgFetch || rp->procp == cm_BkgPrefetch) {
114 * Attempt to determine if there is a conflict on the requested
115 * range of the file. If the first in the range does not exist
116 * in the cache assume there is no conflict. If the buffer does
117 * exist, check to see if an I/O operation is in progress
118 * by using the writing and reading flags as an indicator.
120 cm_buf_t *bufp = NULL;
121 rock_BkgFetch_t *rockp = (rock_BkgFetch_t *)rp->rockp;
123 bufp = buf_Find(&rp->scp->fid, &rockp->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->rockp, 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);
256 lock_ObtainWrite(&cm_daemonLockp[daemonID]);
259 lock_ReleaseWrite(&cm_daemonLockp[daemonID]);
260 thrd_SetEvent(cm_BkgDaemon_ShutdownEvent[daemonID]);
265 void cm_QueueBKGRequest(cm_scache_t *scp, cm_bkgProc_t *procp, void *rockp,
266 cm_user_t *userp, cm_req_t *reqp)
268 cm_bkgRequest_t *rp, *rpq;
272 rp = malloc(sizeof(*rp));
273 memset(rp, 0, sizeof(*rp));
283 /* Use separate queues for fetch and store operations */
284 daemonID = scp->fid.hash % (cm_nDaemons/2) * 2;
285 if (procp == cm_BkgStore)
288 lock_ObtainWrite(&cm_daemonLockp[daemonID]);
289 /* Check to see if this is a duplicate request */
290 for (rpq = cm_bkgListpp[daemonID]; rpq; rpq = (cm_bkgRequest_t *) osi_QNext(&rpq->q))
292 if ( rpq->procp == procp &&
296 if (rp->procp == cm_BkgStore) {
297 rock_BkgStore_t *rock1p = (rock_BkgStore_t *)rp->rockp;
298 rock_BkgStore_t *rock2p = (rock_BkgStore_t *)rpq->rockp;
300 duplicate = (memcmp(rock1p, rock2p, sizeof(*rock1p)) == 0);
302 else if (rp->procp == RDR_BkgFetch || rp->procp == cm_BkgPrefetch) {
303 rock_BkgFetch_t *rock1p = (rock_BkgFetch_t *)rp->rockp;
304 rock_BkgFetch_t *rock2p = (rock_BkgFetch_t *)rpq->rockp;
306 duplicate = (memcmp(rock1p, rock2p, sizeof(*rock1p)) == 0);
310 /* found a duplicate; update request with latest info */
317 cm_bkgQueueCountp[daemonID]++;
318 osi_QAddH((osi_queue_t **) &cm_bkgListpp[daemonID], (osi_queue_t **)&cm_bkgListEndpp[daemonID], &rp->q);
320 lock_ReleaseWrite(&cm_daemonLockp[daemonID]);
323 cm_ReleaseSCache(scp);
324 cm_ReleaseUser(userp);
328 osi_Wakeup((LONG_PTR) &cm_bkgListpp[daemonID]);
333 IsWindowsFirewallPresent(void)
338 BOOLEAN result = FALSE;
339 LPQUERY_SERVICE_CONFIG pConfig = NULL;
343 /* Open services manager */
344 scm = OpenSCManager(NULL, NULL, GENERIC_READ);
345 if (!scm) return FALSE;
347 /* Open Windows Firewall service */
348 svc = OpenService(scm, "MpsSvc", SERVICE_QUERY_CONFIG);
350 afsi_log("MpsSvc Service could not be opened for query: 0x%x", GetLastError());
351 svc = OpenService(scm, "SharedAccess", SERVICE_QUERY_CONFIG);
353 afsi_log("SharedAccess Service could not be opened for query: 0x%x", GetLastError());
358 /* Query Windows Firewall service config, first just to get buffer size */
359 /* Expected to fail, so don't test return value */
360 (void) QueryServiceConfig(svc, NULL, 0, &BufSize);
361 status = GetLastError();
362 if (status != ERROR_INSUFFICIENT_BUFFER)
365 /* Allocate buffer */
366 pConfig = (LPQUERY_SERVICE_CONFIG)GlobalAlloc(GMEM_FIXED,BufSize);
370 /* Query Windows Firewall service config, this time for real */
371 flag = QueryServiceConfig(svc, pConfig, BufSize, &BufSize);
373 afsi_log("QueryServiceConfig failed: 0x%x", GetLastError());
377 /* Is it autostart? */
378 afsi_log("AutoStart 0x%x", pConfig->dwStartType);
379 if (pConfig->dwStartType < SERVICE_DEMAND_START)
385 CloseServiceHandle(svc);
387 CloseServiceHandle(scm);
393 cm_DaemonCheckInit(void)
400 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
401 0, KEY_QUERY_VALUE, &parmKey);
405 dummyLen = sizeof(DWORD);
406 code = RegQueryValueEx(parmKey, "daemonCheckDownInterval", NULL, NULL,
407 (BYTE *) &dummy, &dummyLen);
408 if (code == ERROR_SUCCESS && dummy)
409 cm_daemonCheckDownInterval = dummy;
410 afsi_log("daemonCheckDownInterval is %d", cm_daemonCheckDownInterval);
412 dummyLen = sizeof(DWORD);
413 code = RegQueryValueEx(parmKey, "daemonCheckUpInterval", NULL, NULL,
414 (BYTE *) &dummy, &dummyLen);
415 if (code == ERROR_SUCCESS && dummy)
416 cm_daemonCheckUpInterval = dummy;
417 afsi_log("daemonCheckUpInterval is %d", cm_daemonCheckUpInterval);
419 dummyLen = sizeof(DWORD);
420 code = RegQueryValueEx(parmKey, "daemonCheckVolInterval", NULL, NULL,
421 (BYTE *) &dummy, &dummyLen);
422 if (code == ERROR_SUCCESS && dummy)
423 cm_daemonCheckVolInterval = dummy;
424 afsi_log("daemonCheckVolInterval is %d", cm_daemonCheckVolInterval);
426 dummyLen = sizeof(DWORD);
427 code = RegQueryValueEx(parmKey, "daemonCheckCBInterval", NULL, NULL,
428 (BYTE *) &dummy, &dummyLen);
429 if (code == ERROR_SUCCESS && dummy)
430 cm_daemonCheckCBInterval = dummy;
431 afsi_log("daemonCheckCBInterval is %d", cm_daemonCheckCBInterval);
433 dummyLen = sizeof(DWORD);
434 code = RegQueryValueEx(parmKey, "daemonCheckVolCBInterval", NULL, NULL,
435 (BYTE *) &dummy, &dummyLen);
436 if (code == ERROR_SUCCESS && dummy)
437 cm_daemonCheckVolCBInterval = dummy;
438 afsi_log("daemonCheckVolCBInterval is %d", cm_daemonCheckVolCBInterval);
440 dummyLen = sizeof(DWORD);
441 code = RegQueryValueEx(parmKey, "daemonCheckLockInterval", NULL, NULL,
442 (BYTE *) &dummy, &dummyLen);
443 if (code == ERROR_SUCCESS && dummy)
444 cm_daemonCheckLockInterval = dummy;
445 afsi_log("daemonCheckLockInterval is %d", cm_daemonCheckLockInterval);
447 dummyLen = sizeof(DWORD);
448 code = RegQueryValueEx(parmKey, "daemonCheckTokenInterval", NULL, NULL,
449 (BYTE *) &dummy, &dummyLen);
450 if (code == ERROR_SUCCESS && dummy)
451 cm_daemonTokenCheckInterval = dummy;
452 afsi_log("daemonCheckTokenInterval is %d", cm_daemonTokenCheckInterval);
454 dummyLen = sizeof(DWORD);
455 code = RegQueryValueEx(parmKey, "daemonCheckOfflineVolInterval", NULL, NULL,
456 (BYTE *) &dummy, &dummyLen);
457 if (code == ERROR_SUCCESS && dummy)
458 cm_daemonCheckOfflineVolInterval = dummy;
459 afsi_log("daemonCheckOfflineVolInterval is %d", cm_daemonCheckOfflineVolInterval);
461 dummyLen = sizeof(DWORD);
462 code = RegQueryValueEx(parmKey, "daemonRDRShakeExtentsInterval", NULL, NULL,
463 (BYTE *) &dummy, &dummyLen);
464 if (code == ERROR_SUCCESS && dummy)
465 cm_daemonRDRShakeExtentsInterval = dummy;
466 afsi_log("daemonRDRShakeExtentsInterval is %d", cm_daemonRDRShakeExtentsInterval);
468 dummyLen = sizeof(DWORD);
469 code = RegQueryValueEx(parmKey, "daemonPerformanceTuningInterval", NULL, NULL,
470 (BYTE *) &dummy, &dummyLen);
471 if (code == ERROR_SUCCESS)
472 cm_daemonPerformanceTuningInterval = dummy;
473 afsi_log("daemonPerformanceTuningInterval is %d", cm_daemonPerformanceTuningInterval);
475 dummyLen = sizeof(DWORD);
476 code = RegQueryValueEx(parmKey, "daemonRankServerInterval", NULL, NULL,
477 (BYTE *) &dummy, &dummyLen);
478 if (code == ERROR_SUCCESS && dummy)
479 cm_daemonRankServerInterval = dummy;
480 afsi_log("daemonRankServerInterval is %d", cm_daemonRankServerInterval);
482 dummyLen = sizeof(DWORD);
483 code = RegQueryValueEx(parmKey, "daemonAfsdHookReloadInterval", NULL, NULL,
484 (BYTE *) &dummy, &dummyLen);
485 if (code == ERROR_SUCCESS && dummy)
486 cm_daemonAfsdHookReloadInterval = dummy;
487 afsi_log("daemonAfsdHookReloadInterval is %d", cm_daemonAfsdHookReloadInterval);
489 RegCloseKey(parmKey);
491 if (cm_daemonPerformanceTuningInterval)
492 cm_PerformanceTuningInit();
495 /* periodic lock check daemon */
496 void * cm_LockDaemon(void * vparm)
499 time_t lastLockCheck;
500 char * name = "cm_LockDaemon_ShutdownEvent";
502 cm_LockDaemon_ShutdownEvent = thrd_CreateEvent(NULL, FALSE, FALSE, name);
503 if ( GetLastError() == ERROR_ALREADY_EXISTS )
504 afsi_log("Event Object Already Exists: %s", name);
507 lastLockCheck = now - cm_daemonCheckLockInterval/2 + (rand() % cm_daemonCheckLockInterval);
509 while (daemon_ShutdownFlag == 0) {
510 if (powerStateSuspended) {
517 if (now > lastLockCheck + cm_daemonCheckLockInterval &&
518 daemon_ShutdownFlag == 0 &&
519 powerStateSuspended == 0) {
522 if (daemon_ShutdownFlag == 1)
526 thrd_Sleep(1000); /* sleep 1 second */
528 thrd_SetEvent(cm_LockDaemon_ShutdownEvent);
533 /* periodic check daemon */
534 void * cm_Daemon(void *vparm)
538 time_t lastCBExpirationCheck;
539 time_t lastVolCBRenewalCheck;
540 time_t lastDownServerCheck;
541 time_t lastUpServerCheck;
542 time_t lastTokenCacheCheck;
543 time_t lastBusyVolCheck;
544 time_t lastPerformanceCheck;
545 time_t lastServerRankCheck;
546 time_t lastRDRShakeExtents;
547 time_t lastAfsdHookReload;
548 time_t lastEAccesCheck;
552 HMODULE hHookDll = NULL;
553 AfsdDaemonHook daemonHook = NULL;
554 char * name = "cm_Daemon_ShutdownEvent";
555 int configureFirewall = IsWindowsFirewallPresent();
556 int bAddrChangeCheck = 0;
558 cm_Daemon_ShutdownEvent = thrd_CreateEvent(NULL, FALSE, FALSE, name);
559 if ( GetLastError() == ERROR_ALREADY_EXISTS )
560 afsi_log("Event Object Already Exists: %s", name);
562 if (!configureFirewall) {
563 afsi_log("No Windows Firewall detected");
566 if (cm_freelanceEnabled && cm_freelanceImportCellServDB)
567 cm_FreelanceImportCellServDB();
569 /* ping all file servers, up or down, with unauthenticated connection,
570 * to find out whether we have all our callbacks from the server still.
571 * Also, ping down VLDBs.
574 * Seed the random number generator with our own address, so that
575 * clients starting at the same time don't all do vol checks at the
578 gethostname(thostName, sizeof(thostName));
579 thp = gethostbyname(thostName);
580 if (thp == NULL) /* In djgpp, gethostname returns the netbios
581 name of the machine. gethostbyname will fail
582 looking this up if it differs from DNS name. */
585 memcpy(&code, thp->h_addr_list[0], 4);
589 cm_DaemonCheckInit();
592 lastVolCheck = now - cm_daemonCheckVolInterval/2 + (rand() % cm_daemonCheckVolInterval);
593 lastCBExpirationCheck = now - cm_daemonCheckCBInterval/2 + (rand() % cm_daemonCheckCBInterval);
594 if (cm_daemonCheckVolCBInterval)
595 lastVolCBRenewalCheck = now - cm_daemonCheckVolCBInterval/2 + (rand() % cm_daemonCheckVolCBInterval);
596 lastDownServerCheck = now - cm_daemonCheckDownInterval/2 + (rand() % cm_daemonCheckDownInterval);
597 lastUpServerCheck = now - cm_daemonCheckUpInterval/2 + (rand() % cm_daemonCheckUpInterval);
598 lastTokenCacheCheck = now - cm_daemonTokenCheckInterval/2 + (rand() % cm_daemonTokenCheckInterval);
599 if (cm_daemonCheckOfflineVolInterval)
600 lastBusyVolCheck = now - cm_daemonCheckOfflineVolInterval/2 * (rand() % cm_daemonCheckOfflineVolInterval);
601 if (cm_daemonPerformanceTuningInterval)
602 lastPerformanceCheck = now - cm_daemonPerformanceTuningInterval/2 * (rand() % cm_daemonPerformanceTuningInterval);
603 lastServerRankCheck = now - cm_daemonRankServerInterval/2 * (rand() % cm_daemonRankServerInterval);
604 if (cm_daemonRDRShakeExtentsInterval)
605 lastRDRShakeExtents = now - cm_daemonRDRShakeExtentsInterval/2 * (rand() % cm_daemonRDRShakeExtentsInterval);
606 if (cm_daemonAfsdHookReloadInterval)
607 lastAfsdHookReload = now;
608 lastEAccesCheck = now;
610 hHookDll = cm_LoadAfsdHookLib();
612 daemonHook = ( AfsdDaemonHook ) GetProcAddress(hHookDll, AFSD_DAEMON_HOOK);
614 while (daemon_ShutdownFlag == 0) {
615 if (powerStateSuspended) {
619 /* check to see if the listener threads halted due to network
620 * disconnect or other issues. If so, attempt to restart them.
622 smb_RestartListeners(0);
624 if (daemon_ShutdownFlag == 1)
627 if (configureFirewall) {
628 /* Open Microsoft Firewall to allow in port 7001 */
629 switch (icf_CheckAndAddAFSPorts(AFS_PORTSET_CLIENT)) {
631 afsi_log("Windows Firewall Configuration succeeded");
632 configureFirewall = 0;
635 afsi_log("Invalid Windows Firewall Port Set");
638 afsi_log("Unable to open Windows Firewall Profile");
641 afsi_log("Unable to create/modify Windows Firewall Port entries");
644 afsi_log("Unknown Windows Firewall Configuration error");
648 /* find out what time it is */
651 /* Determine whether an address change took place that we need to respond to */
652 if (bAddrChangeCheck)
653 bAddrChangeCheck = 0;
655 if (lastIPAddrChange != 0 && lastIPAddrChange + 2500 < now) {
656 bAddrChangeCheck = 1;
657 lastIPAddrChange = 0;
660 /* check down servers */
661 if ((bAddrChangeCheck || now > lastDownServerCheck + cm_daemonCheckDownInterval) &&
662 daemon_ShutdownFlag == 0 &&
663 powerStateSuspended == 0) {
664 lastDownServerCheck = now;
665 osi_Log0(afsd_logp, "cm_Daemon CheckDownServers");
666 cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS, NULL);
667 if (daemon_ShutdownFlag == 1)
672 if (bAddrChangeCheck &&
673 daemon_ShutdownFlag == 0 &&
674 powerStateSuspended == 0) {
675 cm_ForceNewConnectionsAllServers();
678 /* check up servers */
679 if ((bAddrChangeCheck || now > lastUpServerCheck + cm_daemonCheckUpInterval) &&
680 daemon_ShutdownFlag == 0 &&
681 powerStateSuspended == 0) {
682 lastUpServerCheck = now;
683 osi_Log0(afsd_logp, "cm_Daemon CheckUpServers");
684 cm_CheckServers(CM_FLAG_CHECKUPSERVERS, NULL);
685 if (daemon_ShutdownFlag == 1)
690 if (bAddrChangeCheck &&
691 daemon_ShutdownFlag == 0 &&
692 powerStateSuspended == 0) {
694 cm_VolStatus_Network_Addr_Change();
698 * Once every five minutes inspect the volume list and enforce
699 * the volume location expiration time.
701 if (now > lastVolCheck + 300 &&
702 daemon_ShutdownFlag == 0 &&
703 powerStateSuspended == 0) {
705 cm_RefreshVolumes(cm_daemonCheckVolInterval);
706 if (daemon_ShutdownFlag == 1)
711 /* Rank all up servers */
712 if ((now > lastServerRankCheck + cm_daemonRankServerInterval) &&
713 daemon_ShutdownFlag == 0 &&
714 powerStateSuspended == 0) {
715 lastServerRankCheck = now;
716 osi_Log0(afsd_logp, "cm_Daemon RankServer");
718 if(daemon_ShutdownFlag == 1)
723 if (cm_daemonCheckVolCBInterval &&
724 now > lastVolCBRenewalCheck + cm_daemonCheckVolCBInterval &&
725 daemon_ShutdownFlag == 0 &&
726 powerStateSuspended == 0) {
727 lastVolCBRenewalCheck = now;
728 cm_VolumeRenewROCallbacks();
729 if (daemon_ShutdownFlag == 1)
734 if ((bAddrChangeCheck || (cm_daemonCheckOfflineVolInterval &&
735 now > lastBusyVolCheck + cm_daemonCheckOfflineVolInterval)) &&
736 daemon_ShutdownFlag == 0 &&
737 powerStateSuspended == 0) {
738 lastBusyVolCheck = now;
739 cm_CheckOfflineVolumes();
740 if (daemon_ShutdownFlag == 1)
745 if (now > lastCBExpirationCheck + cm_daemonCheckCBInterval &&
746 daemon_ShutdownFlag == 0 &&
747 powerStateSuspended == 0) {
748 lastCBExpirationCheck = now;
749 cm_CheckCBExpiration();
750 if (daemon_ShutdownFlag == 1)
755 if (now > lastTokenCacheCheck + cm_daemonTokenCheckInterval &&
756 daemon_ShutdownFlag == 0 &&
757 powerStateSuspended == 0) {
758 lastTokenCacheCheck = now;
759 cm_CheckTokenCache(now);
760 if (daemon_ShutdownFlag == 1)
765 if (now > lastEAccesCheck + cm_daemonEAccesCheckInterval &&
766 daemon_ShutdownFlag == 0 &&
767 powerStateSuspended == 0) {
768 lastEAccesCheck = now;
769 cm_EAccesClearOutdatedEntries();
770 if (daemon_ShutdownFlag == 1)
775 if (cm_daemonRDRShakeExtentsInterval &&
776 now > lastRDRShakeExtents + cm_daemonRDRShakeExtentsInterval &&
777 daemon_ShutdownFlag == 0 &&
778 powerStateSuspended == 0) {
781 lastRDRShakeExtents = now;
782 if (cm_data.buf_redirCount > cm_data.buf_freeCount)
783 buf_RDRShakeSomeExtentsFree(&req, FALSE, 10 /* seconds */);
784 if (daemon_ShutdownFlag == 1)
789 /* allow an exit to be called prior to stopping the service */
790 if (cm_daemonAfsdHookReloadInterval &&
791 lastAfsdHookReload != 0 && lastAfsdHookReload < now) {
793 FreeLibrary(hHookDll);
798 hHookDll = cm_LoadAfsdHookLib();
800 daemonHook = ( AfsdDaemonHook ) GetProcAddress(hHookDll, AFSD_DAEMON_HOOK);
805 BOOL hookRc = daemonHook();
809 SetEvent(WaitToTerminate);
812 if (daemon_ShutdownFlag == 1) {
818 if (cm_daemonPerformanceTuningInterval &&
819 now > lastPerformanceCheck + cm_daemonPerformanceTuningInterval &&
820 daemon_ShutdownFlag == 0 &&
821 powerStateSuspended == 0) {
822 lastPerformanceCheck = now;
823 cm_PerformanceTuningCheck();
824 if (daemon_ShutdownFlag == 1)
830 * sleep .5 seconds. if the thread blocks for a long time
831 * we risk not being able to close the cache before Windows
832 * kills our process during system shutdown.
838 FreeLibrary(hHookDll);
841 thrd_SetEvent(cm_Daemon_ShutdownEvent);
846 void cm_DaemonShutdown(void)
851 daemon_ShutdownFlag = 1;
853 /* wait for shutdown */
854 for ( i=0; i<cm_nDaemons; i++) {
855 osi_Wakeup((LONG_PTR) &cm_bkgListpp[i]);
856 if (cm_BkgDaemon_ShutdownEvent[i])
857 code = thrd_WaitForSingleObject_Event(cm_BkgDaemon_ShutdownEvent[i], INFINITE);
860 if (cm_Daemon_ShutdownEvent)
861 code = thrd_WaitForSingleObject_Event(cm_Daemon_ShutdownEvent, INFINITE);
863 if (cm_LockDaemon_ShutdownEvent)
864 code = thrd_WaitForSingleObject_Event(cm_LockDaemon_ShutdownEvent, INFINITE);
868 * Do not waste precious time waiting for the ipaddr daemon to shutdown.
869 * When it does it means we have lost our network connection and we need
870 * it during cache shutdown in order to notify the file servers that this
871 * client is giving up all callbacks.
873 if (cm_IPAddrDaemon_ShutdownEvent)
874 code = thrd_WaitForSingleObject_Event(cm_IPAddrDaemon_ShutdownEvent, INFINITE);
878 void cm_InitDaemon(int nDaemons)
880 static osi_once_t once;
882 pthread_attr_t tattr;
886 pthread_attr_init(&tattr);
887 pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
889 cm_nDaemons = (nDaemons > CM_MAX_DAEMONS) ? CM_MAX_DAEMONS : nDaemons;
891 if (osi_Once(&once)) {
892 /* creating IP Address Change monitor daemon */
893 pstatus = pthread_create(&phandle, &tattr, cm_IpAddrDaemon, 0);
894 osi_assertx(pstatus == 0, "cm_IpAddrDaemon thread creation failure");
896 /* creating pinging daemon */
897 pstatus = pthread_create(&phandle, &tattr, cm_Daemon, 0);
898 osi_assertx(pstatus == 0, "cm_Daemon thread creation failure");
900 pstatus = pthread_create(&phandle, &tattr, cm_LockDaemon, 0);
901 osi_assertx(pstatus == 0, "cm_LockDaemon thread creation failure");
903 cm_bkgListpp = malloc(nDaemons * sizeof(void *));
904 cm_bkgListEndpp = malloc(nDaemons * sizeof(void *));
905 cm_bkgQueueCountp = malloc(nDaemons * sizeof(afs_uint64));
906 cm_daemonLockp = malloc(nDaemons * sizeof(osi_rwlock_t));
908 for(i=0; i < cm_nDaemons; i++) {
909 lock_InitializeRWLock(&cm_daemonLockp[i], "cm_daemonLock",
910 LOCK_HIERARCHY_DAEMON_GLOBAL);
911 cm_bkgListpp[i] = cm_bkgListEndpp[i] = NULL;
912 cm_bkgQueueCountp[i]=0;
913 pstatus = pthread_create(&phandle, &tattr, cm_BkgDaemon, (LPVOID)(LONG_PTR)i);
914 osi_assertx(pstatus == 0, "cm_BkgDaemon thread creation failure");
919 pthread_attr_destroy(&tattr);