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);
88 thrd_SetEvent(cm_IPAddrDaemon_ShutdownEvent);
93 afs_int32 cm_RequestWillBlock(cm_bkgRequest_t *rp)
95 afs_int32 willBlock = 0;
97 if (rp->procp == cm_BkgStore) {
99 * If the datastoring flag is set, it means that another
100 * thread is already performing an exclusive store operation
101 * on this file. The exclusive state will be cleared once
102 * the file server locks the vnode. Therefore, at most two
103 * threads can be actively involved in storing data at a time
106 lock_ObtainRead(&rp->scp->rw);
107 willBlock = (rp->scp->flags & CM_SCACHEFLAG_DATASTORING);
108 lock_ReleaseRead(&rp->scp->rw);
110 else if (rp->procp == RDR_BkgFetch || rp->procp == cm_BkgPrefetch) {
112 * Attempt to determine if there is a conflict on the requested
113 * range of the file. If the first in the range does not exist
114 * in the cache assume there is no conflict. If the buffer does
115 * exist, check to see if an I/O operation is in progress
116 * by using the writing and reading flags as an indicator.
119 cm_buf_t *bufp = NULL;
121 base.LowPart = rp->p1;
122 base.HighPart = rp->p2;
124 bufp = buf_Find(&rp->scp->fid, &base);
126 willBlock = (bufp->flags & (CM_BUF_WRITING|CM_BUF_READING));
134 void * cm_BkgDaemon(void * vparm)
139 long daemonID = (long)(LONG_PTR)vparm;
141 snprintf(name, sizeof(name), "cm_BkgDaemon_ShutdownEvent%u", daemonID);
143 cm_BkgDaemon_ShutdownEvent[daemonID] = thrd_CreateEvent(NULL, FALSE, FALSE, name);
144 if ( GetLastError() == ERROR_ALREADY_EXISTS )
145 afsi_log("Event Object Already Exists: %s", name);
147 rx_StartClientThread();
149 lock_ObtainWrite(&cm_daemonLockp[daemonID]);
150 while (daemon_ShutdownFlag == 0) {
153 if (powerStateSuspended) {
157 if (!cm_bkgListEndpp[daemonID]) {
158 osi_SleepW((LONG_PTR)&cm_bkgListpp[daemonID], &cm_daemonLockp[daemonID]);
159 lock_ObtainWrite(&cm_daemonLockp[daemonID]);
163 /* we found a request */
164 for (rp = cm_bkgListEndpp[daemonID]; rp; rp = (cm_bkgRequest_t *) osi_QPrev(&rp->q))
166 if (rp->scp->flags & CM_SCACHEFLAG_DELETED)
170 * If the request has active I/O such that this worker would
171 * be forced to block, leave the request in the queue and move
172 * on to one that might be available for servicing.
174 if (cm_RequestWillBlock(rp)) {
179 if (cm_ServerAvailable(&rp->scp->fid, rp->userp))
185 * Couldn't find a request that we could process at the
186 * current time. If there were requests that would cause
187 * the worker to block, sleep for 25ms so it can promptly
188 * respond when it is available. Otherwise, sleep for 1s.
190 * This polling cycle needs to be replaced with a proper
191 * producer/consumer dynamic worker pool.
193 osi_Log2(afsd_logp,"cm_BkgDaemon[%u] sleeping %dms all tasks would block",
194 daemonID, willBlock ? 100 : 1000);
196 lock_ReleaseWrite(&cm_daemonLockp[daemonID]);
197 Sleep(willBlock ? 100 : 1000);
198 lock_ObtainWrite(&cm_daemonLockp[daemonID]);
202 osi_QRemoveHT((osi_queue_t **) &cm_bkgListpp[daemonID], (osi_queue_t **) &cm_bkgListEndpp[daemonID], &rp->q);
203 osi_assertx(cm_bkgQueueCountp[daemonID]-- > 0, "cm_bkgQueueCount 0");
204 lock_ReleaseWrite(&cm_daemonLockp[daemonID]);
206 osi_Log2(afsd_logp,"cm_BkgDaemon[%u] processing request 0x%p", daemonID, rp);
208 if (rp->scp->flags & CM_SCACHEFLAG_DELETED) {
209 osi_Log2(afsd_logp,"cm_BkgDaemon[%u] DELETED scp 0x%x", daemonID, rp->scp);
210 code = CM_ERROR_BADFD;
212 #ifdef DEBUG_REFCOUNT
213 osi_Log3(afsd_logp,"cm_BkgDaemon[%u] (before) scp 0x%x ref %d", daemonID, rp->scp, rp->scp->refCount);
215 code = (*rp->procp)(rp->scp, rp->p1, rp->p2, rp->p3, rp->p4, rp->userp, &rp->req);
216 #ifdef DEBUG_REFCOUNT
217 osi_Log3(afsd_logp,"cm_BkgDaemon[%u] (after) scp 0x%x ref %d", daemonID, rp->scp, rp->scp->refCount);
222 * Keep the following list synchronized with the
223 * error code list in cm_BkgStore.
224 * cm_SyncOpDone(CM_SCACHESYNC_ASYNCSTORE) will be called there unless
225 * one of these errors has occurred.
228 case CM_ERROR_TIMEDOUT: /* or server restarting */
230 case CM_ERROR_WOULDBLOCK:
231 case CM_ERROR_ALLBUSY:
232 case CM_ERROR_ALLDOWN:
233 case CM_ERROR_ALLOFFLINE:
234 case CM_ERROR_PARTIALWRITE:
235 if (rp->procp == cm_BkgStore ||
236 rp->procp == RDR_BkgFetch) {
238 "cm_BkgDaemon[%u] re-queueing failed request 0x%p code 0x%x",
240 lock_ObtainWrite(&cm_daemonLockp[daemonID]);
241 cm_bkgQueueCountp[daemonID]++;
242 osi_QAddT((osi_queue_t **) &cm_bkgListpp[daemonID], (osi_queue_t **)&cm_bkgListEndpp[daemonID], &rp->q);
244 } /* otherwise fall through */
245 case 0: /* success */
246 default: /* other error */
248 osi_Log2(afsd_logp,"cm_BkgDaemon[%u] SUCCESS: request 0x%p", daemonID, rp);
250 osi_Log3(afsd_logp,"cm_BkgDaemon[%u] FAILED: request dropped 0x%p code 0x%x",
253 cm_ReleaseUser(rp->userp);
254 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, afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, afs_uint32 p4,
266 cm_user_t *userp, cm_req_t *reqp)
269 afs_uint32 daemonID = scp->fid.hash % cm_nDaemons;
271 rp = malloc(sizeof(*rp));
272 memset(rp, 0, sizeof(*rp));
285 lock_ObtainWrite(&cm_daemonLockp[daemonID]);
286 cm_bkgQueueCountp[daemonID]++;
287 osi_QAddH((osi_queue_t **) &cm_bkgListpp[daemonID], (osi_queue_t **)&cm_bkgListEndpp[daemonID], &rp->q);
288 lock_ReleaseWrite(&cm_daemonLockp[daemonID]);
290 osi_Wakeup((LONG_PTR) &cm_bkgListpp[daemonID]);
294 IsWindowsFirewallPresent(void)
299 BOOLEAN result = FALSE;
300 LPQUERY_SERVICE_CONFIG pConfig = NULL;
304 /* Open services manager */
305 scm = OpenSCManager(NULL, NULL, GENERIC_READ);
306 if (!scm) return FALSE;
308 /* Open Windows Firewall service */
309 svc = OpenService(scm, "MpsSvc", SERVICE_QUERY_CONFIG);
311 afsi_log("MpsSvc Service could not be opened for query: 0x%x", GetLastError());
312 svc = OpenService(scm, "SharedAccess", SERVICE_QUERY_CONFIG);
314 afsi_log("SharedAccess Service could not be opened for query: 0x%x", GetLastError());
319 /* Query Windows Firewall service config, first just to get buffer size */
320 /* Expected to fail, so don't test return value */
321 (void) QueryServiceConfig(svc, NULL, 0, &BufSize);
322 status = GetLastError();
323 if (status != ERROR_INSUFFICIENT_BUFFER)
326 /* Allocate buffer */
327 pConfig = (LPQUERY_SERVICE_CONFIG)GlobalAlloc(GMEM_FIXED,BufSize);
331 /* Query Windows Firewall service config, this time for real */
332 flag = QueryServiceConfig(svc, pConfig, BufSize, &BufSize);
334 afsi_log("QueryServiceConfig failed: 0x%x", GetLastError());
338 /* Is it autostart? */
339 afsi_log("AutoStart 0x%x", pConfig->dwStartType);
340 if (pConfig->dwStartType < SERVICE_DEMAND_START)
346 CloseServiceHandle(svc);
348 CloseServiceHandle(scm);
354 cm_DaemonCheckInit(void)
361 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
362 0, KEY_QUERY_VALUE, &parmKey);
366 dummyLen = sizeof(DWORD);
367 code = RegQueryValueEx(parmKey, "daemonCheckDownInterval", NULL, NULL,
368 (BYTE *) &dummy, &dummyLen);
369 if (code == ERROR_SUCCESS && dummy)
370 cm_daemonCheckDownInterval = dummy;
371 afsi_log("daemonCheckDownInterval is %d", cm_daemonCheckDownInterval);
373 dummyLen = sizeof(DWORD);
374 code = RegQueryValueEx(parmKey, "daemonCheckUpInterval", NULL, NULL,
375 (BYTE *) &dummy, &dummyLen);
376 if (code == ERROR_SUCCESS && dummy)
377 cm_daemonCheckUpInterval = dummy;
378 afsi_log("daemonCheckUpInterval is %d", cm_daemonCheckUpInterval);
380 dummyLen = sizeof(DWORD);
381 code = RegQueryValueEx(parmKey, "daemonCheckVolInterval", NULL, NULL,
382 (BYTE *) &dummy, &dummyLen);
383 if (code == ERROR_SUCCESS && dummy)
384 cm_daemonCheckVolInterval = dummy;
385 afsi_log("daemonCheckVolInterval is %d", cm_daemonCheckVolInterval);
387 dummyLen = sizeof(DWORD);
388 code = RegQueryValueEx(parmKey, "daemonCheckCBInterval", NULL, NULL,
389 (BYTE *) &dummy, &dummyLen);
390 if (code == ERROR_SUCCESS && dummy)
391 cm_daemonCheckCBInterval = dummy;
392 afsi_log("daemonCheckCBInterval is %d", cm_daemonCheckCBInterval);
394 dummyLen = sizeof(DWORD);
395 code = RegQueryValueEx(parmKey, "daemonCheckVolCBInterval", NULL, NULL,
396 (BYTE *) &dummy, &dummyLen);
397 if (code == ERROR_SUCCESS && dummy)
398 cm_daemonCheckVolCBInterval = dummy;
399 afsi_log("daemonCheckVolCBInterval is %d", cm_daemonCheckVolCBInterval);
401 dummyLen = sizeof(DWORD);
402 code = RegQueryValueEx(parmKey, "daemonCheckLockInterval", NULL, NULL,
403 (BYTE *) &dummy, &dummyLen);
404 if (code == ERROR_SUCCESS && dummy)
405 cm_daemonCheckLockInterval = dummy;
406 afsi_log("daemonCheckLockInterval is %d", cm_daemonCheckLockInterval);
408 dummyLen = sizeof(DWORD);
409 code = RegQueryValueEx(parmKey, "daemonCheckTokenInterval", NULL, NULL,
410 (BYTE *) &dummy, &dummyLen);
411 if (code == ERROR_SUCCESS && dummy)
412 cm_daemonTokenCheckInterval = dummy;
413 afsi_log("daemonCheckTokenInterval is %d", cm_daemonTokenCheckInterval);
415 dummyLen = sizeof(DWORD);
416 code = RegQueryValueEx(parmKey, "daemonCheckOfflineVolInterval", NULL, NULL,
417 (BYTE *) &dummy, &dummyLen);
418 if (code == ERROR_SUCCESS && dummy)
419 cm_daemonCheckOfflineVolInterval = dummy;
420 afsi_log("daemonCheckOfflineVolInterval is %d", cm_daemonCheckOfflineVolInterval);
422 dummyLen = sizeof(DWORD);
423 code = RegQueryValueEx(parmKey, "daemonRDRShakeExtentsInterval", NULL, NULL,
424 (BYTE *) &dummy, &dummyLen);
425 if (code == ERROR_SUCCESS && dummy)
426 cm_daemonRDRShakeExtentsInterval = dummy;
427 afsi_log("daemonRDRShakeExtentsInterval is %d", cm_daemonRDRShakeExtentsInterval);
429 dummyLen = sizeof(DWORD);
430 code = RegQueryValueEx(parmKey, "daemonPerformanceTuningInterval", NULL, NULL,
431 (BYTE *) &dummy, &dummyLen);
432 if (code == ERROR_SUCCESS)
433 cm_daemonPerformanceTuningInterval = dummy;
434 afsi_log("daemonPerformanceTuningInterval is %d", cm_daemonPerformanceTuningInterval);
436 dummyLen = sizeof(DWORD);
437 code = RegQueryValueEx(parmKey, "daemonRankServerInterval", NULL, NULL,
438 (BYTE *) &dummy, &dummyLen);
439 if (code == ERROR_SUCCESS && dummy)
440 cm_daemonRankServerInterval = dummy;
441 afsi_log("daemonRankServerInterval is %d", cm_daemonRankServerInterval);
443 dummyLen = sizeof(DWORD);
444 code = RegQueryValueEx(parmKey, "daemonAfsdHookReloadInterval", NULL, NULL,
445 (BYTE *) &dummy, &dummyLen);
446 if (code == ERROR_SUCCESS && dummy)
447 cm_daemonAfsdHookReloadInterval = dummy;
448 afsi_log("daemonAfsdHookReloadInterval is %d", cm_daemonAfsdHookReloadInterval);
450 RegCloseKey(parmKey);
452 if (cm_daemonPerformanceTuningInterval)
453 cm_PerformanceTuningInit();
456 /* periodic lock check daemon */
457 void * cm_LockDaemon(void * vparm)
460 time_t lastLockCheck;
461 char * name = "cm_LockDaemon_ShutdownEvent";
463 cm_LockDaemon_ShutdownEvent = thrd_CreateEvent(NULL, FALSE, FALSE, name);
464 if ( GetLastError() == ERROR_ALREADY_EXISTS )
465 afsi_log("Event Object Already Exists: %s", name);
468 lastLockCheck = now - cm_daemonCheckLockInterval/2 + (rand() % cm_daemonCheckLockInterval);
470 while (daemon_ShutdownFlag == 0) {
471 if (powerStateSuspended) {
478 if (now > lastLockCheck + cm_daemonCheckLockInterval &&
479 daemon_ShutdownFlag == 0 &&
480 powerStateSuspended == 0) {
483 if (daemon_ShutdownFlag == 1)
487 thrd_Sleep(1000); /* sleep 1 second */
489 thrd_SetEvent(cm_LockDaemon_ShutdownEvent);
494 /* periodic check daemon */
495 void * cm_Daemon(void *vparm)
499 time_t lastCBExpirationCheck;
500 time_t lastVolCBRenewalCheck;
501 time_t lastDownServerCheck;
502 time_t lastUpServerCheck;
503 time_t lastTokenCacheCheck;
504 time_t lastBusyVolCheck;
505 time_t lastPerformanceCheck;
506 time_t lastServerRankCheck;
507 time_t lastRDRShakeExtents;
508 time_t lastAfsdHookReload;
509 time_t lastEAccesCheck;
513 HMODULE hHookDll = NULL;
514 AfsdDaemonHook daemonHook = NULL;
515 char * name = "cm_Daemon_ShutdownEvent";
516 int configureFirewall = IsWindowsFirewallPresent();
517 int bAddrChangeCheck = 0;
519 cm_Daemon_ShutdownEvent = thrd_CreateEvent(NULL, FALSE, FALSE, name);
520 if ( GetLastError() == ERROR_ALREADY_EXISTS )
521 afsi_log("Event Object Already Exists: %s", name);
523 if (!configureFirewall) {
524 afsi_log("No Windows Firewall detected");
527 if (cm_freelanceEnabled && cm_freelanceImportCellServDB)
528 cm_FreelanceImportCellServDB();
530 /* ping all file servers, up or down, with unauthenticated connection,
531 * to find out whether we have all our callbacks from the server still.
532 * Also, ping down VLDBs.
535 * Seed the random number generator with our own address, so that
536 * clients starting at the same time don't all do vol checks at the
539 gethostname(thostName, sizeof(thostName));
540 thp = gethostbyname(thostName);
541 if (thp == NULL) /* In djgpp, gethostname returns the netbios
542 name of the machine. gethostbyname will fail
543 looking this up if it differs from DNS name. */
546 memcpy(&code, thp->h_addr_list[0], 4);
550 cm_DaemonCheckInit();
553 lastVolCheck = now - cm_daemonCheckVolInterval/2 + (rand() % cm_daemonCheckVolInterval);
554 lastCBExpirationCheck = now - cm_daemonCheckCBInterval/2 + (rand() % cm_daemonCheckCBInterval);
555 if (cm_daemonCheckVolCBInterval)
556 lastVolCBRenewalCheck = now - cm_daemonCheckVolCBInterval/2 + (rand() % cm_daemonCheckVolCBInterval);
557 lastDownServerCheck = now - cm_daemonCheckDownInterval/2 + (rand() % cm_daemonCheckDownInterval);
558 lastUpServerCheck = now - cm_daemonCheckUpInterval/2 + (rand() % cm_daemonCheckUpInterval);
559 lastTokenCacheCheck = now - cm_daemonTokenCheckInterval/2 + (rand() % cm_daemonTokenCheckInterval);
560 if (cm_daemonCheckOfflineVolInterval)
561 lastBusyVolCheck = now - cm_daemonCheckOfflineVolInterval/2 * (rand() % cm_daemonCheckOfflineVolInterval);
562 if (cm_daemonPerformanceTuningInterval)
563 lastPerformanceCheck = now - cm_daemonPerformanceTuningInterval/2 * (rand() % cm_daemonPerformanceTuningInterval);
564 lastServerRankCheck = now - cm_daemonRankServerInterval/2 * (rand() % cm_daemonRankServerInterval);
565 if (cm_daemonRDRShakeExtentsInterval)
566 lastRDRShakeExtents = now - cm_daemonRDRShakeExtentsInterval/2 * (rand() % cm_daemonRDRShakeExtentsInterval);
567 if (cm_daemonAfsdHookReloadInterval)
568 lastAfsdHookReload = now;
569 lastEAccesCheck = now;
571 hHookDll = cm_LoadAfsdHookLib();
573 daemonHook = ( AfsdDaemonHook ) GetProcAddress(hHookDll, AFSD_DAEMON_HOOK);
575 while (daemon_ShutdownFlag == 0) {
576 if (powerStateSuspended) {
580 /* check to see if the listener threads halted due to network
581 * disconnect or other issues. If so, attempt to restart them.
583 smb_RestartListeners(0);
585 if (daemon_ShutdownFlag == 1)
588 if (configureFirewall) {
589 /* Open Microsoft Firewall to allow in port 7001 */
590 switch (icf_CheckAndAddAFSPorts(AFS_PORTSET_CLIENT)) {
592 afsi_log("Windows Firewall Configuration succeeded");
593 configureFirewall = 0;
596 afsi_log("Invalid Windows Firewall Port Set");
599 afsi_log("Unable to open Windows Firewall Profile");
602 afsi_log("Unable to create/modify Windows Firewall Port entries");
605 afsi_log("Unknown Windows Firewall Configuration error");
609 /* find out what time it is */
612 /* Determine whether an address change took place that we need to respond to */
613 if (bAddrChangeCheck)
614 bAddrChangeCheck = 0;
616 if (lastIPAddrChange != 0 && lastIPAddrChange + 2500 < now) {
617 bAddrChangeCheck = 1;
618 lastIPAddrChange = 0;
621 /* check down servers */
622 if ((bAddrChangeCheck || now > lastDownServerCheck + cm_daemonCheckDownInterval) &&
623 daemon_ShutdownFlag == 0 &&
624 powerStateSuspended == 0) {
625 lastDownServerCheck = now;
626 osi_Log0(afsd_logp, "cm_Daemon CheckDownServers");
627 cm_CheckServers(CM_FLAG_CHECKDOWNSERVERS, NULL);
628 if (daemon_ShutdownFlag == 1)
633 if (bAddrChangeCheck &&
634 daemon_ShutdownFlag == 0 &&
635 powerStateSuspended == 0) {
636 cm_ForceNewConnectionsAllServers();
639 /* check up servers */
640 if ((bAddrChangeCheck || now > lastUpServerCheck + cm_daemonCheckUpInterval) &&
641 daemon_ShutdownFlag == 0 &&
642 powerStateSuspended == 0) {
643 lastUpServerCheck = now;
644 osi_Log0(afsd_logp, "cm_Daemon CheckUpServers");
645 cm_CheckServers(CM_FLAG_CHECKUPSERVERS, NULL);
646 if (daemon_ShutdownFlag == 1)
651 if (bAddrChangeCheck &&
652 daemon_ShutdownFlag == 0 &&
653 powerStateSuspended == 0) {
655 cm_VolStatus_Network_Addr_Change();
659 * Once every five minutes inspect the volume list and enforce
660 * the volume location expiration time.
662 if (now > lastVolCheck + 300 &&
663 daemon_ShutdownFlag == 0 &&
664 powerStateSuspended == 0) {
666 cm_RefreshVolumes(cm_daemonCheckVolInterval);
667 if (daemon_ShutdownFlag == 1)
672 /* Rank all up servers */
673 if ((now > lastServerRankCheck + cm_daemonRankServerInterval) &&
674 daemon_ShutdownFlag == 0 &&
675 powerStateSuspended == 0) {
676 lastServerRankCheck = now;
677 osi_Log0(afsd_logp, "cm_Daemon RankServer");
679 if(daemon_ShutdownFlag == 1)
684 if (cm_daemonCheckVolCBInterval &&
685 now > lastVolCBRenewalCheck + cm_daemonCheckVolCBInterval &&
686 daemon_ShutdownFlag == 0 &&
687 powerStateSuspended == 0) {
688 lastVolCBRenewalCheck = now;
689 cm_VolumeRenewROCallbacks();
690 if (daemon_ShutdownFlag == 1)
695 if ((bAddrChangeCheck || (cm_daemonCheckOfflineVolInterval &&
696 now > lastBusyVolCheck + cm_daemonCheckOfflineVolInterval)) &&
697 daemon_ShutdownFlag == 0 &&
698 powerStateSuspended == 0) {
699 lastBusyVolCheck = now;
700 cm_CheckOfflineVolumes();
701 if (daemon_ShutdownFlag == 1)
706 if (now > lastCBExpirationCheck + cm_daemonCheckCBInterval &&
707 daemon_ShutdownFlag == 0 &&
708 powerStateSuspended == 0) {
709 lastCBExpirationCheck = now;
710 cm_CheckCBExpiration();
711 if (daemon_ShutdownFlag == 1)
716 if (now > lastTokenCacheCheck + cm_daemonTokenCheckInterval &&
717 daemon_ShutdownFlag == 0 &&
718 powerStateSuspended == 0) {
719 lastTokenCacheCheck = now;
720 cm_CheckTokenCache(now);
721 if (daemon_ShutdownFlag == 1)
726 if (now > lastEAccesCheck + cm_daemonEAccesCheckInterval &&
727 daemon_ShutdownFlag == 0 &&
728 powerStateSuspended == 0) {
729 lastEAccesCheck = now;
730 cm_EAccesClearOutdatedEntries();
731 if (daemon_ShutdownFlag == 1)
736 if (cm_daemonRDRShakeExtentsInterval &&
737 now > lastRDRShakeExtents + cm_daemonRDRShakeExtentsInterval &&
738 daemon_ShutdownFlag == 0 &&
739 powerStateSuspended == 0) {
742 lastRDRShakeExtents = now;
743 if (cm_data.buf_redirCount > cm_data.buf_freeCount)
744 buf_RDRShakeSomeExtentsFree(&req, FALSE, 10 /* seconds */);
745 if (daemon_ShutdownFlag == 1)
750 /* allow an exit to be called prior to stopping the service */
751 if (cm_daemonAfsdHookReloadInterval &&
752 lastAfsdHookReload != 0 && lastAfsdHookReload < now) {
754 FreeLibrary(hHookDll);
759 hHookDll = cm_LoadAfsdHookLib();
761 daemonHook = ( AfsdDaemonHook ) GetProcAddress(hHookDll, AFSD_DAEMON_HOOK);
766 BOOL hookRc = daemonHook();
770 SetEvent(WaitToTerminate);
773 if (daemon_ShutdownFlag == 1) {
779 if (cm_daemonPerformanceTuningInterval &&
780 now > lastPerformanceCheck + cm_daemonPerformanceTuningInterval &&
781 daemon_ShutdownFlag == 0 &&
782 powerStateSuspended == 0) {
783 lastPerformanceCheck = now;
784 cm_PerformanceTuningCheck();
785 if (daemon_ShutdownFlag == 1)
791 * sleep .5 seconds. if the thread blocks for a long time
792 * we risk not being able to close the cache before Windows
793 * kills our process during system shutdown.
799 FreeLibrary(hHookDll);
802 thrd_SetEvent(cm_Daemon_ShutdownEvent);
807 void cm_DaemonShutdown(void)
812 daemon_ShutdownFlag = 1;
814 /* wait for shutdown */
815 for ( i=0; i<cm_nDaemons; i++) {
816 osi_Wakeup((LONG_PTR) &cm_bkgListpp[i]);
817 if (cm_BkgDaemon_ShutdownEvent[i])
818 code = thrd_WaitForSingleObject_Event(cm_BkgDaemon_ShutdownEvent[i], INFINITE);
821 if (cm_Daemon_ShutdownEvent)
822 code = thrd_WaitForSingleObject_Event(cm_Daemon_ShutdownEvent, INFINITE);
824 if (cm_LockDaemon_ShutdownEvent)
825 code = thrd_WaitForSingleObject_Event(cm_LockDaemon_ShutdownEvent, INFINITE);
829 * Do not waste precious time waiting for the ipaddr daemon to shutdown.
830 * When it does it means we have lost our network connection and we need
831 * it during cache shutdown in order to notify the file servers that this
832 * client is giving up all callbacks.
834 if (cm_IPAddrDaemon_ShutdownEvent)
835 code = thrd_WaitForSingleObject_Event(cm_IPAddrDaemon_ShutdownEvent, INFINITE);
839 void cm_InitDaemon(int nDaemons)
841 static osi_once_t once;
843 pthread_attr_t tattr;
847 pthread_attr_init(&tattr);
848 pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
850 cm_nDaemons = (nDaemons > CM_MAX_DAEMONS) ? CM_MAX_DAEMONS : nDaemons;
852 if (osi_Once(&once)) {
853 /* creating IP Address Change monitor daemon */
854 pstatus = pthread_create(&phandle, &tattr, cm_IpAddrDaemon, 0);
855 osi_assertx(pstatus == 0, "cm_IpAddrDaemon thread creation failure");
857 /* creating pinging daemon */
858 pstatus = pthread_create(&phandle, &tattr, cm_Daemon, 0);
859 osi_assertx(pstatus == 0, "cm_Daemon thread creation failure");
861 pstatus = pthread_create(&phandle, &tattr, cm_LockDaemon, 0);
862 osi_assertx(pstatus == 0, "cm_LockDaemon thread creation failure");
864 cm_bkgListpp = malloc(nDaemons * sizeof(void *));
865 cm_bkgListEndpp = malloc(nDaemons * sizeof(void *));
866 cm_bkgQueueCountp = malloc(nDaemons * sizeof(afs_uint64));
867 cm_daemonLockp = malloc(nDaemons * sizeof(osi_rwlock_t));
869 for(i=0; i < cm_nDaemons; i++) {
870 lock_InitializeRWLock(&cm_daemonLockp[i], "cm_daemonLock",
871 LOCK_HIERARCHY_DAEMON_GLOBAL);
872 cm_bkgListpp[i] = cm_bkgListEndpp[i] = NULL;
873 pstatus = pthread_create(&phandle, &tattr, cm_BkgDaemon, (LPVOID)(LONG_PTR)i);
874 osi_assertx(pstatus == 0, "cm_BkgDaemon thread creation failure");
879 pthread_attr_destroy(&tattr);