#include <afs/audit.h>
#include <afs/afsutil.h>
#include <afs/fileutil.h>
+#include <opr/queue.h>
#include "bnode.h"
+#include "bnode_internal.h"
#include "bosprototypes.h"
#ifndef WCOREDUMP
#define BNODE_LWP_STACKSIZE (16 * 1024)
#define BNODE_ERROR_COUNT_MAX 16 /* maximum number of retries */
+#define BNODE_ERROR_DELAY_MAX 60 /* maximum retry delay (seconds) */
-int bnode_waiting = 0;
static PROCESS bproc_pid; /* pid of waker-upper */
-static struct bnode *allBnodes = 0; /* list of all bnodes */
-static struct bnode_proc *allProcs = 0; /* list of all processes for which we're waiting */
-static struct bnode_type *allTypes = 0; /* list of registered type handlers */
+static struct opr_queue allBnodes; /**< List of all bnodes */
+static struct opr_queue allProcs; /**< List of all processes for which we're waiting */
+static struct opr_queue allTypes; /**< List of all registered type handlers */
static struct bnode_stats {
int weirdPids;
if (code) {
DIR *logdir;
struct dirent *file;
- size_t length;
unsigned long pid;
const char *coredir = AFSDIR_LOGS_DIR;
continue;
pid = atol(file->d_name + 5);
if (pid == aproc->pid) {
- length = strlen(coredir) + strlen(file->d_name) + 2;
- corefile = malloc(length);
+ asprintf(&corefile, "%s/%s", coredir, file->d_name);
if (corefile == NULL) {
closedir(logdir);
return;
}
- snprintf(corefile, length, "%s/%s", coredir, file->d_name);
code = 0;
break;
}
TimeFields->tm_hour, TimeFields->tm_min, TimeFields->tm_sec);
strcpy(tbuffer, FileName);
#endif
- code = renamefile(corefile, tbuffer);
+ rk_rename(corefile, tbuffer);
free(corefile);
}
int
bnode_WaitAll(void)
{
- struct bnode *tb;
+ struct opr_queue *cursor;
afs_int32 code;
afs_int32 stat;
retry:
- for (tb = allBnodes; tb; tb = tb->next) {
+ for (opr_queue_Scan(&allBnodes, cursor)) {
+ struct bnode *tb = opr_queue_Entry(cursor, struct bnode, q);
+
bnode_Hold(tb);
code = BOP_GETSTAT(tb, &stat);
if (code) {
int
bnode_ApplyInstance(int (*aproc) (struct bnode *tb, void *), void *arock)
{
- struct bnode *tb, *nb;
+ struct opr_queue *cursor, *store;
afs_int32 code;
- for (tb = allBnodes; tb; tb = nb) {
- nb = tb->next;
+ for (opr_queue_ScanSafe(&allBnodes, cursor, store)) {
+ struct bnode *tb = opr_queue_Entry(cursor, struct bnode, q);
code = (*aproc) (tb, arock);
if (code)
return code;
struct bnode *
bnode_FindInstance(char *aname)
{
- struct bnode *tb;
+ struct opr_queue *cursor;
+
+ for (opr_queue_Scan(&allBnodes, cursor)) {
+ struct bnode *tb = opr_queue_Entry(cursor, struct bnode, q);
- for (tb = allBnodes; tb; tb = tb->next) {
if (!strcmp(tb->name, aname))
return tb;
}
static struct bnode_type *
FindType(char *aname)
{
- struct bnode_type *tt;
+ struct opr_queue *cursor;
+
+ for (opr_queue_Scan(&allTypes, cursor)) {
+ struct bnode_type *tt = opr_queue_Entry(cursor, struct bnode_type, q);
- for (tt = allTypes; tt; tt = tt->next) {
if (!strcmp(tt->name, aname))
return tt;
}
- return (struct bnode_type *)0;
+ return NULL;
}
int
bnode_Register(char *atype, struct bnode_ops *aprocs, int anparms)
{
- struct bnode_type *tt;
+ struct opr_queue *cursor;
+ struct bnode_type *tt = NULL;
- for (tt = allTypes; tt; tt = tt->next) {
+ for (opr_queue_Scan(&allTypes, cursor), tt = NULL) {
+ tt = opr_queue_Entry(cursor, struct bnode_type, q);
if (!strcmp(tt->name, atype))
break;
}
if (!tt) {
- tt = (struct bnode_type *)malloc(sizeof(struct bnode_type));
- memset(tt, 0, sizeof(struct bnode_type));
- tt->next = allTypes;
- allTypes = tt;
+ tt = calloc(1, sizeof(struct bnode_type));
+ opr_queue_Init(&tt->q);
+ opr_queue_Prepend(&allTypes, &tt->q);
tt->name = atype;
}
tt->ops = aprocs;
bnode_Delete(struct bnode *abnode)
{
afs_int32 code;
- struct bnode **lb, *ub;
afs_int32 temp;
if (abnode->refCount != 0) {
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;
- }
- }
+ opr_queue_Remove(&abnode->q);
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);
bnode_InitBnode(struct bnode *abnode, struct bnode_ops *abnodeops,
char *aname)
{
- struct bnode **lb, *nb;
-
/* format the bnode properly */
memset(abnode, 0, sizeof(struct bnode));
+ opr_queue_Init(&abnode->q);
abnode->ops = abnodeops;
abnode->name = strdup(aname);
if (!abnode->name)
abnode->goal = BSTAT_SHUTDOWN;
/* put the bnode at the end of the list so we write bnode file in same order */
- for (lb = &allBnodes, nb = *lb; nb; lb = &nb->next, nb = *lb);
- *lb = abnode;
+ opr_queue_Append(&allBnodes, &abnode->q);
return 0;
}
-static int
-DeleteProc(struct bnode_proc *abproc)
-{
- struct bnode_proc **pb, *tb;
- struct bnode_proc *nb;
-
- for (pb = &allProcs, tb = *pb; tb; pb = &tb->next, tb = nb) {
- nb = tb->next;
- if (tb == abproc) {
- *pb = nb;
- free(tb);
- return 0;
- }
- }
- return BZNOENT;
-}
-
/* bnode lwp executes this code repeatedly */
static void *
bproc(void *unused)
afs_int32 code;
struct bnode *tb;
afs_int32 temp;
+ struct opr_queue *cursor, *store;
struct bnode_proc *tp;
- struct bnode *nb;
int options; /* must not be register */
struct timeval tv;
int setAny;
/* 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) {
+ for (opr_queue_Scan(&allBnodes, cursor)) {
+ tb = opr_queue_Entry(cursor, struct bnode, q);
if (tb->flags & BNODE_NEEDTIMEOUT) {
if (tb->nextTimeout < temp) {
setAny = 1;
temp = tv.tv_sec;
/* check all bnodes to see which ones need timeout events */
- for (tb = allBnodes; tb; tb = nb) {
+ for (opr_queue_ScanSafe(&allBnodes, cursor, store)) {
+ tb = opr_queue_Entry(cursor, struct bnode, q);
if ((tb->flags & BNODE_NEEDTIMEOUT) && temp > tb->nextTimeout) {
bnode_Hold(tb);
BOP_TIMEOUT(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)
+ for (tp = NULL, opr_queue_Scan(&allProcs, cursor), tp = NULL) {
+ tp = opr_queue_Entry(cursor, struct bnode_proc, q);
+
if (tp->pid == code)
break;
+ }
if (tp) {
/* found the pid */
tb = tp->bnode;
} else {
tb->errorStopCount++;
if (!tb->errorStopDelay) {
- tb->errorStopDelay = 1;
+ tb->errorStopDelay = 1; /* wait a second, then retry */
} else {
- tb->errorStopDelay *= 2;
+ tb->errorStopDelay *= 2; /* ramp up the retry delays */
+ }
+ if (tb->errorStopDelay > BNODE_ERROR_DELAY_MAX) {
+ tb->errorStopDelay = BNODE_ERROR_DELAY_MAX; /* cap the delay */
}
}
tb->flags |= BNODE_ERRORSTOP;
BOP_PROCEXIT(tb, tp);
bnode_Check(tb);
bnode_Release(tb); /* bnode delete can happen here */
- DeleteProc(tp);
+ opr_queue_Remove(&tp->q);
+ free(tp);
} else
bnode_stats.weirdPids++;
}
/* int asignal = (int) param; */
IOMGR_Cancel(bproc_pid);
- return 0;
+ return NULL;
}
/* Called at signal interrupt level; queues function to be called
if (initDone)
return 0;
initDone = 1;
+ opr_queue_Init(&allTypes);
+ opr_queue_Init(&allProcs);
+ opr_queue_Init(&allBnodes);
memset(&bnode_stats, 0, sizeof(bnode_stats));
LWP_InitializeProcessSupport(1, &junk); /* just in case */
IOMGR_Initialize();
if (inToken) {
inToken = 0; /* end of this token */
*tptr++ = 0;
- ttok =
- (struct bnode_token *)malloc(sizeof(struct bnode_token));
+ ttok = malloc(sizeof(struct bnode_token));
ttok->next = (struct bnode_token *)0;
ttok->key = strdup(tbuffer);
if (last) {
code = bnode_ParseLine(aexecString, &tlist); /* try parsing first */
if (code)
return code;
- tp = (struct bnode_proc *)malloc(sizeof(struct bnode_proc));
- memset(tp, 0, sizeof(struct bnode_proc));
- tp->next = allProcs;
+ tp = calloc(1, sizeof(struct bnode_proc));
+ opr_queue_Init(&tp->q);
tp->bnode = abnode;
tp->comLine = aexecString;
tp->coreName = coreName; /* may be null */
bozo_Log("%s started pid %ld: %s\n", abnode->name, cpid, aexecString);
bnode_FreeTokens(tlist);
- allProcs = tp;
+ opr_queue_Prepend(&allProcs, &tp->q);
*aproc = tp;
tp->pid = cpid;
tp->flags = BPROC_STARTED;
bnode_Check(aproc->bnode);
return code;
}
-
-int
-bnode_Deactivate(struct bnode *abnode)
-{
- struct bnode **pb, *tb;
- struct bnode *nb;
- if (!(abnode->flags & BNODE_ACTIVE))
- return BZNOTACTIVE;
- for (pb = &allBnodes, tb = *pb; tb; tb = nb) {
- nb = tb->next;
- if (tb == abnode) {
- *pb = nb;
- tb->flags &= ~BNODE_ACTIVE;
- return 0;
- }
- }
- return BZNOENT;
-}