bozo: pthread support

Adjust our bos and bosserver code to accommodate pthreads:

 - Add a new lock (bozo_logLock) to serialize writes to the log.
 - Add a global lock (bnode_glock) in bosserver, which is held for all
   code that touches bnodes and processes. Acquire this lock for all
   entry points into the relevant bosserver code (including all SBOZO_
   RPC entry points).
 - Make bproc "sleep" using opr_cv_timedwait on bproc_cv/bnode_glock,
   and interrupt bproc's sleep by signalling bproc_cv instead of via
   IOMGR_Cancel.
 - Handle signals via opr softsig in bosserver.
 - Use spawnprocve_sig to clear the signal mask when we spawn a
   new process, so any mucking around with the signal mask doesn't
   leak to the child processes.
 - Use sleep() instead of IOMGR_Sleep() in bosserver and bos.

Using a single global lock for the bnode subsystem is a heavy hammer,
but this greatly simplifies the code changes required for pthread
support. Single-core performance has so far been fine for bosserver,
so the practical benefits of finer-grained locking approaches are
small.

Change-Id: I4bf741e04a6f87a1551dd831a20851b56b10d910
Reviewed-on: https://gerrit.openafs.org/10286
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
This commit is contained in:
Chas Williams (CONTRACTOR) 2012-11-30 16:06:08 -05:00 committed by Benjamin Kaduk
parent 6ff968264f
commit 87555080c3
6 changed files with 364 additions and 27 deletions

View File

@ -21,6 +21,7 @@
#include <afs/afsutil.h>
#include <afs/fileutil.h>
#include <opr/queue.h>
#include <opr/softsig.h>
#include "bnode.h"
#include "bnode_internal.h"
@ -34,11 +35,16 @@
#define BNODE_ERROR_COUNT_MAX 16 /* maximum number of retries */
#define BNODE_ERROR_DELAY_MAX 60 /* maximum retry delay (seconds) */
static PROCESS bproc_pid; /* pid of waker-upper */
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 */
#ifdef AFS_PTHREAD_ENV
static opr_cv_t bproc_cv;
#else
static PROCESS bproc_pid; /* pid of waker-upper */
#endif
static struct bnode_stats {
int weirdPids;
} bnode_stats;
@ -160,24 +166,29 @@ SaveCore(struct bnode *abnode, struct bnode_proc
int
bnode_GetString(struct bnode *abnode, char **adesc)
{
BNODE_ASSERT_LOCK();
return BOP_GETSTRING(abnode, adesc);
}
int
bnode_GetParm(struct bnode *abnode, afs_int32 aindex, char **aparm)
{
BNODE_ASSERT_LOCK();
return BOP_GETPARM(abnode, aindex, aparm);
}
int
bnode_GetStat(struct bnode *abnode, afs_int32 * astatus)
{
BNODE_ASSERT_LOCK();
return BOP_GETSTAT(abnode, astatus);
}
int
bnode_GetNotifier(struct bnode *abnode, char **anotifier)
{
BNODE_ASSERT_LOCK();
if (abnode->notifier == NULL)
return BZNOENT;
*anotifier = strdup(abnode->notifier);
@ -189,15 +200,22 @@ bnode_GetNotifier(struct bnode *abnode, char **anotifier)
int
bnode_RestartP(struct bnode *abnode)
{
BNODE_ASSERT_LOCK();
return BOP_RESTARTP(abnode);
}
static int
bnode_Check(struct bnode *abnode)
{
BNODE_ASSERT_LOCK();
if (abnode->flags & BNODE_WAIT) {
abnode->flags &= ~BNODE_WAIT;
#ifdef AFS_PTHREAD_ENV
opr_cv_broadcast(&abnode->bn_cv);
#else
LWP_NoYieldSignal(abnode);
#endif
}
return 0;
}
@ -206,6 +224,7 @@ bnode_Check(struct bnode *abnode)
int
bnode_HasCore(struct bnode *abnode)
{
BNODE_ASSERT_LOCK();
return BOP_HASCORE(abnode);
}
@ -213,8 +232,16 @@ bnode_HasCore(struct bnode *abnode)
static void
bnode_Wait(struct bnode *abnode)
{
BNODE_ASSERT_LOCK();
abnode->flags |= BNODE_WAIT;
#ifdef AFS_PTHREAD_ENV
do {
opr_cv_wait(&abnode->bn_cv, &bnode_glock);
} while ((abnode->flags & BNODE_WAIT) != 0);
#else
LWP_WaitProcess(abnode);
#endif
}
/* wait for all bnodes to stabilize */
@ -225,6 +252,8 @@ bnode_WaitAll(void)
afs_int32 code;
afs_int32 stat;
BNODE_ASSERT_LOCK();
retry:
for (opr_queue_Scan(&allBnodes, cursor)) {
struct bnode *tb = opr_queue_Entry(cursor, struct bnode, q);
@ -252,6 +281,8 @@ bnode_WaitStatus(struct bnode *abnode, int astatus)
afs_int32 code;
afs_int32 stat;
BNODE_ASSERT_LOCK();
bnode_Hold(abnode);
while (1) {
/* get the status */
@ -276,6 +307,8 @@ bnode_WaitStatus(struct bnode *abnode, int astatus)
int
bnode_ResetErrorCount(struct bnode *abnode)
{
BNODE_ASSERT_LOCK();
abnode->errorStopCount = 0;
abnode->errorStopDelay = 0;
return 0;
@ -302,6 +335,8 @@ bnode_SetGoal(struct bnode *abnode, int agoal)
int
bnode_SetFileGoal(struct bnode *abnode, int agoal)
{
BNODE_ASSERT_LOCK();
if (abnode->fileGoal == agoal)
return 0; /* already done */
abnode->fileGoal = agoal;
@ -316,6 +351,8 @@ bnode_ApplyInstance(int (*aproc) (struct bnode *tb, void *), void *arock)
struct opr_queue *cursor, *store;
afs_int32 code;
BNODE_ASSERT_LOCK();
for (opr_queue_ScanSafe(&allBnodes, cursor, store)) {
struct bnode *tb = opr_queue_Entry(cursor, struct bnode, q);
code = (*aproc) (tb, arock);
@ -330,6 +367,8 @@ bnode_FindInstance(char *aname)
{
struct opr_queue *cursor;
BNODE_ASSERT_LOCK();
for (opr_queue_Scan(&allBnodes, cursor)) {
struct bnode *tb = opr_queue_Entry(cursor, struct bnode, q);
@ -344,6 +383,8 @@ FindType(char *aname)
{
struct opr_queue *cursor;
BNODE_ASSERT_LOCK();
for (opr_queue_Scan(&allTypes, cursor)) {
struct bnode_type *tt = opr_queue_Entry(cursor, struct bnode_type, q);
@ -359,6 +400,8 @@ bnode_Register(char *atype, struct bnode_ops *aprocs, int anparms)
struct opr_queue *cursor;
struct bnode_type *tt = NULL;
BNODE_ASSERT_LOCK();
for (opr_queue_Scan(&allTypes, cursor), tt = NULL) {
tt = opr_queue_Entry(cursor, struct bnode_type, q);
if (!strcmp(tt->name, atype))
@ -384,6 +427,8 @@ bnode_Create(char *atype, char *ainstance, struct bnode ** abp, char *ap1,
char *notifierpath = NULL;
struct stat tstat;
BNODE_ASSERT_LOCK();
if (bnode_FindInstance(ainstance))
return BZEXISTS;
type = FindType(atype);
@ -442,6 +487,8 @@ bnode_DeleteName(char *ainstance)
int
bnode_Hold(struct bnode *abnode)
{
BNODE_ASSERT_LOCK();
abnode->refCount++;
return 0;
}
@ -449,6 +496,8 @@ bnode_Hold(struct bnode *abnode)
int
bnode_Release(struct bnode *abnode)
{
BNODE_ASSERT_LOCK();
abnode->refCount--;
if (abnode->refCount == 0 && abnode->flags & BNODE_DELETE) {
abnode->flags &= ~BNODE_DELETE; /* we're going for it */
@ -463,6 +512,8 @@ bnode_Delete(struct bnode *abnode)
afs_int32 code;
afs_int32 temp;
BNODE_ASSERT_LOCK();
if (abnode->refCount != 0) {
abnode->flags |= BNODE_DELETE;
return 0;
@ -479,6 +530,7 @@ bnode_Delete(struct bnode *abnode)
/* all clear to zap */
opr_queue_Remove(&abnode->q);
opr_cv_destroy(&abnode->bn_cv);
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);
@ -496,11 +548,17 @@ bnode_PendingTimeout(struct bnode *abnode)
int
bnode_SetTimeout(struct bnode *abnode, afs_int32 atimeout)
{
BNODE_ASSERT_LOCK();
if (atimeout != 0) {
abnode->nextTimeout = FT_ApproxTime() + atimeout;
abnode->flags |= BNODE_NEEDTIMEOUT;
abnode->period = atimeout;
#ifdef AFS_PTHREAD_ENV
opr_cv_broadcast(&bproc_cv);
#else
IOMGR_Cancel(bproc_pid);
#endif
} else {
abnode->flags &= ~BNODE_NEEDTIMEOUT;
}
@ -512,9 +570,12 @@ int
bnode_InitBnode(struct bnode *abnode, struct bnode_ops *abnodeops,
char *aname)
{
BNODE_ASSERT_LOCK();
/* format the bnode properly */
memset(abnode, 0, sizeof(struct bnode));
opr_queue_Init(&abnode->q);
opr_cv_init(&abnode->bn_cv);
abnode->ops = abnodeops;
abnode->name = strdup(aname);
if (!abnode->name)
@ -529,6 +590,41 @@ bnode_InitBnode(struct bnode *abnode, struct bnode_ops *abnodeops,
return 0;
}
#ifdef AFS_PTHREAD_ENV
/*
* Returns a negative value if we were interrupted. Returns 0 if we slept
* without interruption.
*/
static int
bproc_IntSleep(afs_int32 secs)
{
struct timeval tv;
struct timespec ts;
BNODE_ASSERT_LOCK();
opr_Verify(gettimeofday(&tv, NULL) == 0);
ts.tv_sec = tv.tv_sec + secs;
ts.tv_nsec = tv.tv_usec * 1000;
if (opr_cv_timedwait(&bproc_cv, &bnode_glock, &ts) == 0) {
/* We were interrupted. */
return -1;
} else {
/* We timed out. */
return 0;
}
}
#else
static int
bproc_IntSleep(afs_int32 secs)
{
struct timeval tv;
tv.tv_sec = secs;
tv.tv_usec = 0;
return IOMGR_Select(0, 0, 0, 0, &tv);
}
#endif
/* bnode lwp executes this code repeatedly */
static void *
bproc(void *unused)
@ -543,6 +639,8 @@ bproc(void *unused)
int setAny;
int status;
BNODE_LOCK();
while (1) {
/* first figure out how long to sleep for */
temp = 0x7fffffff; /* afs_int32 time; maxint doesn't work in select */
@ -564,9 +662,7 @@ bproc(void *unused)
else
temp = 999999;
if (temp > 0) {
tv.tv_sec = temp;
tv.tv_usec = 0;
code = IOMGR_Select(0, 0, 0, 0, &tv);
code = bproc_IntSleep(temp);
} else
code = 0; /* fake timeout code */
@ -745,6 +841,8 @@ hdl_notifier(struct bnode_proc *tp)
int pid;
struct stat tstat;
BNODE_ASSERT_LOCK();
if (stat(tp->bnode->notifier, &tstat)) {
bozo_Log("BNODE: Failed to find notifier '%s'; ignored\n",
tp->bnode->notifier);
@ -786,9 +884,54 @@ hdl_notifier(struct bnode_proc *tp)
return (0);
}
#ifdef AFS_PTHREAD_ENV
/**
* Called from the opr softsig thread to handle incoming signals.
*
* @param[in] asignal The signal number of the received signal.
*
* @pre BNODE_LOCK must _not_ be held
*/
static void
bnode_Int(int asignal)
{
if (asignal == SIGQUIT || asignal == SIGTERM) {
/*
* Note that we are only called from the opr softsig thread, so we
* cannot reach this code from multiple threads. So, we can safely
* access 'shuttingdown' without any locks.
*/
static int shuttingdown;
if (!shuttingdown) {
/*
* We can't just run bozo_ShutdownAndExit here directly, since it
* will block the signal handler thread while we wait for children
* to die. So create a new thread to run the shutdown process; but
* only run one, just in case we keep getting QUIT signals while
* the shutdown process runs.
*/
pthread_t pid;
pthread_attr_t attr;
shuttingdown = 1;
opr_Verify(pthread_attr_init(&attr) == 0);
opr_Verify(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) == 0);
opr_Verify(pthread_create(&pid, &attr, bozo_ShutdownAndExit, (void *)(intptr_t)asignal) == 0);
opr_Verify(pthread_attr_destroy(&attr) == 0);
}
} else {
/* SIGCHLD: wake up bproc. */
BNODE_LOCK();
opr_cv_broadcast(&bproc_cv);
BNODE_UNLOCK();
}
}
#else /* AFS_PTHREAD_ENV */
/* Called by IOMGR at low priority on IOMGR's stack shortly after a SIGCHLD
* occurs. Wakes up bproc do redo things */
void *
static void *
bnode_SoftInt(void *param)
{
/* int asignal = (int) param; */
@ -800,7 +943,7 @@ bnode_SoftInt(void *param)
/* Called at signal interrupt level; queues function to be called
* when IOMGR runs again.
*/
void
static void
bnode_Int(int asignal)
{
if (asignal == SIGQUIT || asignal == SIGTERM) {
@ -809,15 +952,25 @@ bnode_Int(int asignal)
IOMGR_SoftSig(bnode_SoftInt, (void *)(intptr_t)asignal);
}
}
#endif /* AFS_PTHREAD_ENV */
/* intialize the whole system */
/**
* intialize the whole system
*
* @pre BNODE_LOCK must be held
*/
int
bnode_Init(void)
{
#ifdef AFS_PTHREAD_ENV
pthread_attr_t tattr;
pthread_t bproc_thread;
#else
PROCESS junk;
afs_int32 code;
struct sigaction newaction;
#endif
afs_int32 code;
static int initDone = 0;
if (initDone)
@ -827,13 +980,28 @@ bnode_Init(void)
opr_queue_Init(&allProcs);
opr_queue_Init(&allBnodes);
memset(&bnode_stats, 0, sizeof(bnode_stats));
#ifdef AFS_PTHREAD_ENV
opr_cv_init(&bproc_cv);
opr_Verify(pthread_attr_init(&tattr) == 0);
opr_Verify(pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED) == 0);
code = pthread_create(&bproc_thread, &tattr, bproc, NULL);
opr_Verify(pthread_attr_destroy(&tattr) == 0);
#else
LWP_InitializeProcessSupport(1, &junk); /* just in case */
IOMGR_Initialize();
code = LWP_CreateProcess(bproc, BNODE_LWP_STACKSIZE,
/* priority */ 1, (void *) /* parm */ 0,
"bnode-manager", &bproc_pid);
#endif
if (code)
return code;
#ifdef AFS_PTHREAD_ENV
opr_Verify(opr_softsig_Register(SIGCHLD, bnode_Int) == 0);
opr_Verify(opr_softsig_Register(SIGQUIT, bnode_Int) == 0);
opr_Verify(opr_softsig_Register(SIGTERM, bnode_Int) == 0);
#else
memset(&newaction, 0, sizeof(newaction));
newaction.sa_handler = bnode_Int;
code = sigaction(SIGCHLD, &newaction, NULL);
@ -845,7 +1013,8 @@ bnode_Init(void)
code = sigaction(SIGTERM, &newaction, NULL);
if (code)
return errno;
return code;
#endif
return 0;
}
/* free token list returned by parseLine */
@ -931,6 +1100,9 @@ bnode_NewProc(struct bnode *abnode, char *aexecString, char *coreName,
pid_t cpid;
char *argv[MAXVARGS];
int i;
sigset_t set;
BNODE_ASSERT_LOCK();
code = bnode_ParseLine(aexecString, &tlist); /* try parsing first */
if (code)
@ -949,7 +1121,9 @@ bnode_NewProc(struct bnode *abnode, char *aexecString, char *coreName,
}
argv[i] = NULL; /* null-terminated */
cpid = spawnprocve(argv[0], argv, environ, -1);
/* Don't block any signals in child procs. */
sigemptyset(&set);
cpid = spawnprocve_sig(argv[0], argv, environ, -1, &set);
osi_audit(BOSSpawnProcEvent, 0, AUD_STR, aexecString, AUD_END);
if (cpid == (pid_t) - 1) {
@ -975,6 +1149,9 @@ int
bnode_StopProc(struct bnode_proc *aproc, int asignal)
{
int code;
BNODE_ASSERT_LOCK();
if (!(aproc->flags & BPROC_STARTED) || (aproc->flags & BPROC_EXITED))
return BZNOTACTIVE;

View File

@ -7,6 +7,32 @@
* directory or online at http://www.openafs.org/dl/license10.html
*/
#include <afs/opr.h>
#ifdef AFS_PTHREAD_ENV
# include <opr/lock.h>
#else
# include <opr/lockstub.h>
#endif
/*
* To keep things simple, we have one big lock for the entire bnode subsystem.
* Generally, that means you must hold BNODE_LOCK before interacting with any
* bnodes or bnode processes, and before calling any bnode_* functions (with
* some exceptions noted in function comments).
*
* More specifically, BNODE_LOCK protects:
* - allBnodes (and all 'struct bnode')
* - allProcs (and all 'struct bnode_proc')
* - allTypes (and all 'struct bnode_type')
* - bozo_newKTs, bozo_nextRestartKT, bozo_nextDayKT, bnode_stats
*
* For LWP, BNODE_LOCK does nothing.
*/
extern opr_mutex_t bnode_glock;
#define BNODE_LOCK() opr_mutex_enter(&bnode_glock)
#define BNODE_UNLOCK() opr_mutex_exit(&bnode_glock)
#define BNODE_ASSERT_LOCK() opr_mutex_assert(&bnode_glock)
#define BOP_TIMEOUT(bnode) ((*(bnode)->ops->timeout)((bnode)))
#define BOP_GETSTAT(bnode, a) ((*(bnode)->ops->getstat)((bnode),(a)))
#define BOP_SETSTAT(bnode, a) ((*(bnode)->ops->setstat)((bnode),(a)))
@ -68,6 +94,7 @@ struct bnode {
char fileGoal; /* same, but to be stored in file */
afs_int32 errorStopCount; /* number of recent error stops */
afs_int32 errorStopDelay; /* seconds to wait before retrying start */
opr_cv_t bn_cv; /* condvar for bnode_Wait/bnode_Check */
};
struct bnode_proc {

View File

@ -1256,7 +1256,11 @@ DoSalvage(struct rx_connection * aconn, char * aparm1, char * aparm2,
count = 0;
while (1) {
char *itype = NULL;
#ifdef AFS_PTHREAD_ENV
sleep(1);
#else
IOMGR_Sleep(1);
#endif
code = BOZO_GetInstanceInfo(aconn, "salvage-tmp", &itype, &istatus);
xdr_free((xdrproc_t)xdr_string, &itype);
if (code)

View File

@ -45,6 +45,8 @@ SBOZO_GetRestartTime(struct rx_call *acall, afs_int32 atype, struct bozo_netKTim
{
afs_int32 code;
BNODE_LOCK();
code = 0; /* assume success */
switch (atype) {
case 1:
@ -60,6 +62,8 @@ SBOZO_GetRestartTime(struct rx_call *acall, afs_int32 atype, struct bozo_netKTim
break;
}
BNODE_UNLOCK();
return code;
}
@ -69,6 +73,8 @@ SBOZO_SetRestartTime(struct rx_call *acall, afs_int32 atype, struct bozo_netKTim
afs_int32 code;
char caller[MAXKTCNAMELEN];
BNODE_LOCK();
/* check for proper permissions */
if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
code = BZACCESS;
@ -99,6 +105,7 @@ SBOZO_SetRestartTime(struct rx_call *acall, afs_int32 atype, struct bozo_netKTim
}
fail:
BNODE_UNLOCK();
osi_auditU(acall, BOS_SetRestartEvent, code, AUD_END);
return code;
}
@ -798,6 +805,8 @@ SBOZO_CreateBnode(struct rx_call *acall, char *atype, char *ainstance,
afs_int32 code;
char caller[MAXKTCNAMELEN];
BNODE_LOCK();
if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
code = BZACCESS;
goto fail;
@ -825,6 +834,7 @@ SBOZO_CreateBnode(struct rx_call *acall, char *atype, char *ainstance,
bnode_SetStat(tb, BSTAT_NORMAL);
fail:
BNODE_UNLOCK();
osi_auditU(acall, BOS_CreateBnodeEvent, code, AUD_END);
return code;
}
@ -835,6 +845,8 @@ SBOZO_WaitAll(struct rx_call *acall)
afs_int32 code;
char caller[MAXKTCNAMELEN];
BNODE_LOCK();
if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
code = BZACCESS;
goto fail;
@ -846,6 +858,7 @@ SBOZO_WaitAll(struct rx_call *acall)
code = bnode_WaitAll();
fail:
BNODE_UNLOCK();
osi_auditU(acall, BOS_WaitAllEvent, code, AUD_END);
return code;
}
@ -856,6 +869,8 @@ SBOZO_DeleteBnode(struct rx_call *acall, char *ainstance)
afs_int32 code;
char caller[MAXKTCNAMELEN];
BNODE_LOCK();
if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
code = BZACCESS;
goto fail;
@ -870,6 +885,7 @@ SBOZO_DeleteBnode(struct rx_call *acall, char *ainstance)
code = bnode_DeleteName(ainstance);
fail:
BNODE_UNLOCK();
osi_auditU(acall, BOS_DeleteBnodeEvent, code, AUD_STR, ainstance,
AUD_END);
return code;
@ -917,6 +933,8 @@ SBOZO_ShutdownAll(struct rx_call *acall)
afs_int32 code;
char caller[MAXKTCNAMELEN];
BNODE_LOCK();
/* check for authorization */
if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
code = BZACCESS;
@ -928,6 +946,7 @@ SBOZO_ShutdownAll(struct rx_call *acall)
code = bnode_ApplyInstance(sdproc, NULL);
fail:
BNODE_UNLOCK();
osi_auditU(acall, BOS_ShutdownAllEvent, code, AUD_END);
return code;
}
@ -939,6 +958,8 @@ SBOZO_RestartAll(struct rx_call *acall)
afs_int32 code;
char caller[MAXKTCNAMELEN];
BNODE_LOCK();
if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
code = BZACCESS;
goto fail;
@ -960,6 +981,7 @@ SBOZO_RestartAll(struct rx_call *acall)
code = bnode_ApplyInstance(stproc, NULL);
fail:
BNODE_UNLOCK();
osi_auditU(acall, BOS_RestartAllEvent, code, AUD_END);
return code;
}
@ -970,6 +992,8 @@ SBOZO_ReBozo(struct rx_call *acall)
afs_int32 code;
char caller[MAXKTCNAMELEN];
BNODE_LOCK();
/* acall is null if called internally to restart bosserver */
if (acall && !afsconf_SuperUser(bozo_confdir, acall, caller)) {
code = BZACCESS;
@ -988,6 +1012,8 @@ SBOZO_ReBozo(struct rx_call *acall)
if (code)
goto fail;
BNODE_UNLOCK();
if (acall)
osi_auditU(acall, BOS_RebozoEvent, code, AUD_END);
else
@ -999,6 +1025,7 @@ SBOZO_ReBozo(struct rx_call *acall)
bozo_ReBozo(); /* this reexecs us, and doesn't return, of course */
fail:
BNODE_UNLOCK();
/* Differentiate between external and internal ReBozo; prevents AFS_Aud_NoCall event */
if (acall)
osi_auditU(acall, BOS_RebozoEvent, code, AUD_END);
@ -1014,6 +1041,8 @@ SBOZO_StartupAll(struct rx_call *acall)
afs_int32 code;
char caller[MAXKTCNAMELEN];
BNODE_LOCK();
if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
code = BZACCESS;
goto fail;
@ -1023,6 +1052,7 @@ SBOZO_StartupAll(struct rx_call *acall)
code = bnode_ApplyInstance(stproc, NULL);
fail:
BNODE_UNLOCK();
osi_auditU(acall, BOS_StartupAllEvent, code, AUD_END);
return code;
}
@ -1034,6 +1064,8 @@ SBOZO_Restart(struct rx_call *acall, char *ainstance)
afs_int32 code;
char caller[MAXKTCNAMELEN];
BNODE_LOCK();
if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
code = BZACCESS;
goto fail;
@ -1055,6 +1087,7 @@ SBOZO_Restart(struct rx_call *acall, char *ainstance)
bnode_Release(tb);
fail:
BNODE_UNLOCK();
osi_auditU(acall, BOS_RestartEvent, code, AUD_STR, ainstance, AUD_END);
return code;
}
@ -1067,6 +1100,8 @@ SBOZO_SetTStatus(struct rx_call *acall, char *ainstance, afs_int32 astatus)
afs_int32 code;
char caller[MAXKTCNAMELEN];
BNODE_LOCK();
if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
code = BZACCESS;
goto fail;
@ -1085,6 +1120,7 @@ SBOZO_SetTStatus(struct rx_call *acall, char *ainstance, afs_int32 astatus)
bnode_Release(tb);
fail:
BNODE_UNLOCK();
osi_auditU(acall, BOS_SetTempStatusEvent, code, AUD_STR, ainstance,
AUD_END);
return code;
@ -1097,6 +1133,8 @@ SBOZO_SetStatus(struct rx_call *acall, char *ainstance, afs_int32 astatus)
afs_int32 code;
char caller[MAXKTCNAMELEN];
BNODE_LOCK();
if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
code = BZACCESS;
goto fail;
@ -1116,6 +1154,7 @@ SBOZO_SetStatus(struct rx_call *acall, char *ainstance, afs_int32 astatus)
bnode_Release(tb);
fail:
BNODE_UNLOCK();
osi_auditU(acall, BOS_SetStatusEvent, code, AUD_STR, ainstance, AUD_END);
return code;
}
@ -1127,9 +1166,13 @@ SBOZO_GetStatus(struct rx_call *acall, char *ainstance, afs_int32 *astat,
struct bnode *tb;
afs_int32 code;
BNODE_LOCK();
tb = bnode_FindInstance(ainstance);
if (!tb)
if (!tb) {
BNODE_UNLOCK();
return BZNOENT;
}
bnode_Hold(tb);
code = bnode_GetStat(tb, astat);
@ -1137,6 +1180,8 @@ SBOZO_GetStatus(struct rx_call *acall, char *ainstance, afs_int32 *astat,
code = bnode_GetString(tb, astatDescr);
bnode_Release(tb);
BNODE_UNLOCK();
return code;
}
@ -1236,7 +1281,9 @@ SBOZO_EnumerateInstance(struct rx_call *acall, afs_int32 anum,
tdata.counter = anum;
tdata.iname = NULL;
BNODE_LOCK();
bnode_ApplyInstance(eifunc, &tdata);
BNODE_UNLOCK();
if (tdata.counter >= 0)
return BZDOM; /* anum > # of actual instances */
if (tdata.iname == NULL)
@ -1375,15 +1422,21 @@ SBOZO_GetInstanceInfo(IN struct rx_call *acall,
{
struct bnode *tb;
BNODE_LOCK();
tb = bnode_FindInstance(ainstance);
if (!tb)
if (!tb) {
BNODE_UNLOCK();
return BZNOENT;
}
if (tb->type)
*atype = strdup(tb->type->name);
else
*atype = strdup("");
if (*atype == NULL)
if (*atype == NULL) {
BNODE_UNLOCK();
return BZIO;
}
memset(astatus, 0, sizeof(struct bozo_status)); /* good defaults */
astatus->goal = tb->goal;
@ -1400,6 +1453,7 @@ SBOZO_GetInstanceInfo(IN struct rx_call *acall,
astatus->flags |= BOZO_HASCORE;
if (!DirAccessOK())
astatus->flags |= BOZO_BADDIRACCESS;
BNODE_UNLOCK();
return 0;
}
@ -1412,10 +1466,12 @@ SBOZO_GetInstanceParm(struct rx_call *acall,
struct bnode *tb;
afs_int32 code;
BNODE_LOCK();
tb = bnode_FindInstance(ainstance);
if (!tb)
if (!tb) {
BNODE_UNLOCK();
return BZNOENT;
}
bnode_Hold(tb);
if (anum == 999) {
code = bnode_GetNotifier(tb, aparm);
@ -1424,6 +1480,8 @@ SBOZO_GetInstanceParm(struct rx_call *acall,
}
bnode_Release(tb);
BNODE_UNLOCK();
/* Not Currently Audited */
return code;
}
@ -1498,6 +1556,8 @@ SBOZO_GetInstanceStrings(struct rx_call *acall, char *abnodeName,
{
struct bnode *tb;
BNODE_LOCK();
*as2 = malloc(1);
**as2 = 0;
*as3 = malloc(1);
@ -1515,9 +1575,11 @@ SBOZO_GetInstanceStrings(struct rx_call *acall, char *abnodeName,
*as1 = malloc(1);
**as1 = 0;
}
BNODE_UNLOCK();
return 0;
fail:
BNODE_UNLOCK();
*as1 = malloc(1);
**as1 = 0;
return BZNOENT;
@ -1536,18 +1598,25 @@ SBOZO_SetRestrictedMode(struct rx_call *acall, afs_int32 arestmode)
afs_int32 code;
char caller[MAXKTCNAMELEN];
BNODE_LOCK();
if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
return BZACCESS;
code = BZACCESS;
goto done;
}
if (bozo_isrestricted) {
return BZACCESS;
code = BZACCESS;
goto done;
}
if (arestmode != 0 && arestmode != 1) {
return BZDOM;
code = BZDOM;
goto done;
}
bozo_isrestricted = arestmode;
code = WriteBozoFile(0);
done:
BNODE_UNLOCK();
return code;
}
@ -1557,6 +1626,8 @@ bozo_ShutdownAndExit(void *param)
int asignal = (intptr_t)param;
int code;
BNODE_LOCK();
bozo_Log
("Shutdown of BOS server and processes in response to signal %d\n",
asignal);
@ -1572,6 +1643,8 @@ bozo_ShutdownAndExit(void *param)
code);
}
BNODE_UNLOCK();
rx_Finalize();
exit(code);
}

View File

@ -30,7 +30,6 @@ int bnode_Hold(struct bnode *);
int bnode_Release(struct bnode *);
int bnode_Delete(struct bnode *);
int bnode_PendingTimeout(struct bnode *abnode);
void bnode_Int(int asignal);
int bnode_Init(void);
int bnode_FreeTokens(struct bnode_token *alist);
int bnode_ParseLine(char *aline, struct bnode_token **alist);

View File

@ -47,6 +47,7 @@
#include <afs/authcon.h>
#include <afs/cellconfig.h>
#include <afs/cmd.h>
#include <opr/softsig.h>
#if defined(AFS_SGI_ENV)
#include <afs/afs_args.h>
@ -60,10 +61,22 @@
#define BOZO_LWP_STACKSIZE 16000
extern struct bnode_ops fsbnode_ops, dafsbnode_ops, ezbnode_ops, cronbnode_ops;
struct afsconf_dir *bozo_confdir = 0; /* bozo configuration dir */
static PROCESS bozo_pid;
/*
* bozo configuration dir. This can be accessed outside of any locks; we
* initialize it in main() before any useful threads have started.
*/
struct afsconf_dir *bozo_confdir;
const char *bozo_fileName;
FILE *bozo_logFile;
/* Protects the entire bnode subsystem. */
opr_mutex_t bnode_glock;
#ifdef AFS_PTHREAD_ENV
/* Protects writing to the log file. */
static opr_mutex_t bozo_logLock;
#endif
#ifndef AFS_NT40_ENV
static int bozo_argc = 0;
static char** bozo_argv = NULL;
@ -81,7 +94,7 @@ static afs_int32 nextRestart;
static afs_int32 nextDay;
struct ktime bozo_nextRestartKT, bozo_nextDayKT;
int bozo_newKTs;
int bozo_newKTs = 1;
int rxBind = 0;
int rxkadDisableDotCheck = 0;
@ -91,7 +104,9 @@ int bozo_restdisable = 0;
void
bozo_insecureme(int sig)
{
#ifndef AFS_PTHREAD_ENV
signal(SIGFPE, bozo_insecureme);
#endif
bozo_isrestricted = 0;
bozo_restdisable = 1;
}
@ -530,6 +545,8 @@ WriteBozoFile(char *aname)
struct bztemp btemp;
int ret = 0;
BNODE_ASSERT_LOCK();
if (!aname)
aname = (char *)bozo_fileName;
if (asprintf(&tbuffer, "%s.NBZ", aname) < 0)
@ -600,10 +617,15 @@ BozoDaemon(void *unused)
{
afs_int32 now;
/* now initialize the values */
bozo_newKTs = 1;
while (1) {
#ifdef AFS_PTHREAD_ENV
sleep(60);
#else
IOMGR_Sleep(60);
#endif
BNODE_LOCK();
now = FT_ApproxTime();
if (bozo_restdisable) {
@ -619,7 +641,9 @@ BozoDaemon(void *unused)
/* see if we should do a restart */
if (now > nextRestart) {
BNODE_UNLOCK();
SBOZO_ReBozo(0); /* doesn't come back */
BNODE_LOCK();
}
/* see if we should restart a server */
@ -629,6 +653,8 @@ BozoDaemon(void *unused)
/* call the bnode restartp function, and restart all that require it */
bnode_ApplyInstance(bdrestart, 0);
}
BNODE_UNLOCK();
}
AFS_UNREACHED(return(NULL));
}
@ -880,6 +906,12 @@ main(int argc, char **argv, char **envp)
int DoProcessRPCStats = 0;
struct stat sb;
struct afsconf_bsso_info bsso;
#ifdef AFS_PTHREAD_ENV
pthread_attr_t tattr;
pthread_t bozo_pid;
#else
PROCESS bozo_pid;
#endif
#ifndef AFS_NT40_ENV
int nofork = 0;
#endif
@ -905,7 +937,6 @@ main(int argc, char **argv, char **envp)
sigaction(SIGABRT, &nsa, NULL);
#endif
osi_audit_init();
signal(SIGFPE, bozo_insecureme);
memset(&bsso, 0, sizeof(bsso));
@ -918,6 +949,9 @@ main(int argc, char **argv, char **envp)
}
#endif
opr_mutex_init(&bozo_logLock);
opr_mutex_init(&bnode_glock);
/* Initialize dirpaths */
if (!(initAFSDirPath() & AFSDIR_SERVER_PATHS_OK)) {
#ifdef AFS_NT40_ENV
@ -1078,6 +1112,7 @@ main(int argc, char **argv, char **envp)
}
if (!DoSyslog) {
FILE *bozo_logFile;
/* Support logging to named pipes by not renaming. */
if (DoTransarcLogs
&& (lstat(AFSDIR_SERVER_BOZLOG_FILEPATH, &sb) == 0)
@ -1105,7 +1140,8 @@ main(int argc, char **argv, char **envp)
/*
* go into the background and remove our controlling tty, close open
* file desriptors
* file desriptors. we should delay creating any pthreads until after this
* point, since they will be destroyed here (unless -nofork was given).
*/
#ifndef AFS_NT40_ENV
@ -1115,6 +1151,13 @@ main(int argc, char **argv, char **envp)
}
#endif /* ! AFS_NT40_ENV */
#ifdef AFS_PTHREAD_ENV
opr_softsig_Init();
opr_Verify(opr_softsig_Register(SIGFPE, bozo_insecureme) == 0);
#else
signal(SIGFPE, bozo_insecureme);
#endif
/* Write current state of directory permissions to log file */
DirAccessOK();
@ -1144,6 +1187,8 @@ main(int argc, char **argv, char **envp)
/* opened the cell databse */
bozo_confdir = tdir;
BNODE_LOCK();
code = bnode_Init();
if (code) {
printf("bosserver: could not init bnode package, code %d\n", code);
@ -1218,8 +1263,15 @@ main(int argc, char **argv, char **envp)
}
}
#ifdef AFS_PTHREAD_ENV
opr_Verify(pthread_attr_init(&tattr) == 0);
opr_Verify(pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED) == 0);
code = pthread_create(&bozo_pid, &tattr, BozoDaemon, NULL);
opr_Verify(pthread_attr_destroy(&tattr) == 0);
#else
code = LWP_CreateProcess(BozoDaemon, BOZO_LWP_STACKSIZE, /* priority */ 1,
/* param */ NULL , "bozo-the-clown", &bozo_pid);
#endif
if (code) {
bozo_Log("Failed to create daemon thread\n");
exit(1);
@ -1246,6 +1298,8 @@ main(int argc, char **argv, char **envp)
bozo_CreatePidFile("bosserver", NULL, getpid());
}
BNODE_UNLOCK();
tservice = rx_NewServiceHost(host, 0, /* service id */ 1,
"bozo", securityClasses, numClasses,
BOZO_ExecuteRequest);
@ -1284,6 +1338,8 @@ bozo_Log(const char *format, ...)
vsyslog(LOG_INFO, format, ap);
#endif
} else {
FILE *bozo_logFile;
opr_mutex_enter(&bozo_logLock);
myTime = time(0);
strcpy(tdate, ctime(&myTime)); /* copy out of static area asap */
tdate[24] = ':';
@ -1304,6 +1360,7 @@ bozo_Log(const char *format, ...)
/* close so rm BosLog works */
fclose(bozo_logFile);
}
opr_mutex_exit(&bozo_logLock);
}
va_end(ap);
}