/* wait for all bnodes to stabilize */ int bnode_WaitAll(void) { struct bnode *tb; afs_int32 code; afs_int32 stat; retry: for (tb = allBnodes; tb; tb = tb->next) { bnode_Hold(tb); code = BOP_GETSTAT(tb, &stat); if (code) { bnode_Release(tb); return code; } if (stat != tb->goal) { tb->flags |= BNODE_WAIT; LWP_WaitProcess(tb); bnode_Release(tb); goto retry; } bnode_Release(tb); } return 0; }
/* wait until bnode status is correct */ int bnode_WaitStatus(struct bnode *abnode, int astatus) { afs_int32 code; afs_int32 stat; bnode_Hold(abnode); while (1) { /* get the status */ code = BOP_GETSTAT(abnode, &stat); if (code) return code; /* otherwise, check if we're done */ if (stat == astatus) { bnode_Release(abnode); return 0; /* done */ } if (astatus != abnode->goal) { bnode_Release(abnode); return -1; /* no longer our goal, don't keep waiting */ } /* otherwise, block */ abnode->flags |= BNODE_WAIT; LWP_WaitProcess(abnode); } }
afs_int32 SBOZO_GetStatus(struct rx_call *acall, char *ainstance, afs_int32 *astat, char **astatDescr) { struct bnode *tb; afs_int32 code; tb = bnode_FindInstance(ainstance); if (!tb) { code = BZNOENT; goto fail; } bnode_Hold(tb); code = bnode_GetStat(tb, astat); if (code) { bnode_Release(tb); goto fail; } *astatDescr = malloc(BOZO_BSSIZE); code = bnode_GetString(tb, *astatDescr, BOZO_BSSIZE); bnode_Release(tb); if (code) (*astatDescr)[0] = 0; /* null string means no further info */ return 0; fail: *astatDescr = malloc(1); **astatDescr = 0; return code; }
int bnode_Delete(struct bnode *abnode) { afs_int32 code; struct bnode **lb, *ub; afs_int32 temp; if (abnode->refCount != 0) { abnode->flags |= BNODE_DELETE; return 0; } /* make sure the bnode is idle before zapping */ bnode_Hold(abnode); code = BOP_GETSTAT(abnode, &temp); bnode_Release(abnode); if (code) return code; if (temp != BSTAT_SHUTDOWN) return BZBUSY; /* all clear to zap */ for (lb = &allBnodes, ub = *lb; ub; lb = &ub->next, ub = *lb) { if (ub == abnode) { /* unthread it from the list */ *lb = ub->next; break; } } free(abnode->name); /* do this first, since bnode fields may be bad after BOP_DELETE */ code = BOP_DELETE(abnode); /* don't play games like holding over this one */ WriteBozoFile(0); return code; }
afs_int32 SBOZO_Restart(struct rx_call *acall, char *ainstance) { struct bnode *tb; afs_int32 code; char caller[MAXKTCNAMELEN]; if (!afsconf_SuperUser(bozo_confdir, acall, caller)) { code = BZACCESS; goto fail; } if (DoLogging) bozo_Log("%s is executing Restart '%s'\n", caller, ainstance); tb = bnode_FindInstance(ainstance); if (!tb) { code = BZNOENT; goto fail; } bnode_Hold(tb); bnode_SetStat(tb, BSTAT_SHUTDOWN); code = bnode_WaitStatus(tb, BSTAT_SHUTDOWN); /* this can fail */ bnode_ResetErrorCount(tb); bnode_SetStat(tb, BSTAT_NORMAL); bnode_Release(tb); fail: osi_auditU(acall, BOS_RestartEvent, code, AUD_STR, ainstance, AUD_END); return code; }
afs_int32 SBOZO_GetInstanceParm(struct rx_call *acall, char *ainstance, afs_int32 anum, char **aparm) { struct bnode *tb; char *tp; afs_int32 code; tp = malloc(BOZO_BSSIZE); *aparm = tp; *tp = 0; /* null-terminate string in error case */ tb = bnode_FindInstance(ainstance); if (!tb) return BZNOENT; bnode_Hold(tb); if (anum == 999) { if (tb->notifier) { memcpy(tp, tb->notifier, strlen(tb->notifier) + 1); code = 0; } else code = BZNOENT; /* XXXXX */ } else code = bnode_GetParm(tb, anum, tp, BOZO_BSSIZE); bnode_Release(tb); /* Not Currently Audited */ return code; }
afs_int32 SBOZO_SetStatus(struct rx_call *acall, char *ainstance, afs_int32 astatus) { struct bnode *tb; afs_int32 code; char caller[MAXKTCNAMELEN]; if (!afsconf_SuperUser(bozo_confdir, acall, caller)) { code = BZACCESS; goto fail; } if (DoLogging) bozo_Log("%s is executing SetStatus '%s' (status = %d)\n", caller, ainstance, astatus); tb = bnode_FindInstance(ainstance); if (!tb) { code = BZNOENT; goto fail; } bnode_Hold(tb); bnode_SetFileGoal(tb, astatus); code = bnode_SetStat(tb, astatus); bnode_Release(tb); fail: osi_auditU(acall, BOS_SetStatusEvent, code, AUD_STR, ainstance, AUD_END); return code; }
static int sdproc(struct bnode *abnode, void *arock) { bnode_Hold(abnode); bnode_SetStat(abnode, BSTAT_SHUTDOWN); bnode_Release(abnode); return 0; }
static int swproc(struct bnode *abnode, void *arock) { if (abnode->goal == BSTAT_NORMAL) return 0; /* this one's not shutting down */ /* otherwise, we are shutting down */ bnode_Hold(abnode); bnode_WaitStatus(abnode, BSTAT_SHUTDOWN); bnode_Release(abnode); return 0; /* don't stop apply function early, no matter what */ }
static int stproc(struct bnode *abnode, void *arock) { if (abnode->fileGoal == BSTAT_SHUTDOWN) return 0; /* don't do these guys */ bnode_Hold(abnode); bnode_SetStat(abnode, BSTAT_NORMAL); bnode_Release(abnode); return 0; }
static int bdrestart(struct bnode *abnode, void *arock) { afs_int32 code; if (abnode->fileGoal != BSTAT_NORMAL || abnode->goal != BSTAT_NORMAL) return 0; /* don't restart stopped bnodes */ bnode_Hold(abnode); code = bnode_RestartP(abnode); if (code) { /* restart the dude */ bnode_SetStat(abnode, BSTAT_SHUTDOWN); bnode_WaitStatus(abnode, BSTAT_SHUTDOWN); bnode_SetStat(abnode, BSTAT_NORMAL); } bnode_Release(abnode); return 0; /* keep trying all bnodes */ }
/* bnode lwp executes this code repeatedly */ static void * bproc(void *unused) { afs_int32 code; struct bnode *tb; afs_int32 temp; struct bnode_proc *tp; struct bnode *nb; int options; /* must not be register */ struct timeval tv; int setAny; int status; while (1) { /* first figure out how long to sleep for */ temp = 0x7fffffff; /* afs_int32 time; maxint doesn't work in select */ setAny = 0; for (tb = allBnodes; tb; tb = tb->next) { if (tb->flags & BNODE_NEEDTIMEOUT) { if (tb->nextTimeout < temp) { setAny = 1; temp = tb->nextTimeout; } } } /* now temp has the time at which we should wakeup next */ /* sleep */ if (setAny) temp -= FT_ApproxTime(); /* how many seconds until next event */ else temp = 999999; if (temp > 0) { tv.tv_sec = temp; tv.tv_usec = 0; code = IOMGR_Select(0, 0, 0, 0, &tv); } else code = 0; /* fake timeout code */ /* figure out why we woke up; child exit or timeouts */ FT_GetTimeOfDay(&tv, 0); /* must do the real gettimeofday once and a while */ temp = tv.tv_sec; /* check all bnodes to see which ones need timeout events */ for (tb = allBnodes; tb; tb = nb) { if ((tb->flags & BNODE_NEEDTIMEOUT) && temp > tb->nextTimeout) { bnode_Hold(tb); BOP_TIMEOUT(tb); bnode_Check(tb); if (tb->flags & BNODE_NEEDTIMEOUT) { /* check again, BOP_TIMEOUT could change */ tb->nextTimeout = FT_ApproxTime() + tb->period; } nb = tb->next; bnode_Release(tb); /* delete may occur here */ } else nb = tb->next; } if (code < 0) { /* signalled, probably by incoming signal */ while (1) { options = WNOHANG; bnode_waiting = options | 0x800000; code = waitpid((pid_t) - 1, &status, options); bnode_waiting = 0; if (code == 0 || code == -1) break; /* all done */ /* otherwise code has a process id, which we now search for */ for (tp = allProcs; tp; tp = tp->next) if (tp->pid == code) break; if (tp) { /* found the pid */ tb = tp->bnode; bnode_Hold(tb); /* count restarts in last 10 seconds */ if (temp > tb->rsTime + 30) { /* it's been 10 seconds we've been counting */ tb->rsTime = temp; tb->rsCount = 0; } if (WIFSIGNALED(status) == 0) { /* exited, not signalled */ tp->lastExit = WEXITSTATUS(status); tp->lastSignal = 0; if (tp->lastExit) { tb->errorCode = tp->lastExit; tb->lastErrorExit = FT_ApproxTime(); RememberProcName(tp); tb->errorSignal = 0; } if (tp->coreName) bozo_Log("%s:%s exited with code %d\n", tb->name, tp->coreName, tp->lastExit); else bozo_Log("%s exited with code %d\n", tb->name, tp->lastExit); } else { /* Signal occurred, perhaps spurious due to shutdown request. * If due to a shutdown request, don't overwrite last error * information. */ tp->lastSignal = WTERMSIG(status); tp->lastExit = 0; if (tp->lastSignal != SIGQUIT && tp->lastSignal != SIGTERM && tp->lastSignal != SIGKILL) { tb->errorSignal = tp->lastSignal; tb->lastErrorExit = FT_ApproxTime(); RememberProcName(tp); } if (tp->coreName) bozo_Log("%s:%s exited on signal %d%s\n", tb->name, tp->coreName, tp->lastSignal, WCOREDUMP(status) ? " (core dumped)" : ""); else bozo_Log("%s exited on signal %d%s\n", tb->name, tp->lastSignal, WCOREDUMP(status) ? " (core dumped)" : ""); SaveCore(tb, tp); } tb->lastAnyExit = FT_ApproxTime(); if (tb->notifier) { bozo_Log("BNODE: Notifier %s will be called\n", tb->notifier); hdl_notifier(tp); } BOP_PROCEXIT(tb, tp); bnode_Check(tb); if (tb->rsCount++ > 10) { /* 10 in 10 seconds */ tb->flags |= BNODE_ERRORSTOP; bnode_SetGoal(tb, BSTAT_SHUTDOWN); bozo_Log ("BNODE '%s' repeatedly failed to start, perhaps missing executable.\n", tb->name); } bnode_Release(tb); /* bnode delete can happen here */ DeleteProc(tp); } else bnode_stats.weirdPids++; } } } return NULL; }