#include <roken.h>
-#include <sys/types.h>
-#include <string.h>
-#include <stdarg.h>
-#include <time.h>
-
-#ifdef AFS_NT40_ENV
-#include <winsock2.h>
-#else
-#include <sys/file.h>
-#include <netinet/in.h>
-#include <sys/param.h>
-#endif
-
#include <lock.h>
#include <rx/xdr.h>
#include <rx/rx.h>
afs_uint32 ubik_host[UBIK_MAX_INTERFACE_ADDR];
afs_int32 ubik_epochTime = 0;
afs_int32 urecovery_state = 0;
-int (*ubik_SRXSecurityProc) (void *, struct rx_securityClass **, afs_int32 *);
-void *ubik_SRXSecurityRock;
int (*ubik_SyncWriterCacheProc) (void);
struct ubik_server *ubik_servers;
short ubik_callPortal;
+/* These global variables were used to control the server security layers.
+ * They are retained for backwards compatibility with legacy callers.
+ *
+ * The ubik_SetServerSecurityProcs() interface should be used instead.
+ */
+
+int (*ubik_SRXSecurityProc) (void *, struct rx_securityClass **, afs_int32 *);
+void *ubik_SRXSecurityRock;
+int (*ubik_CheckRXSecurityProc) (void *, struct rx_call *);
+void *ubik_CheckRXSecurityRock;
+
+
+
static int BeginTrans(struct ubik_dbase *dbase, afs_int32 transMode,
struct ubik_trans **transPtr, int readAny);
-struct rx_securityClass *ubik_sc[3];
+static struct rx_securityClass **ubik_sc = NULL;
+static void (*buildSecClassesProc)(void *, struct rx_securityClass ***,
+ afs_int32 *) = NULL;
+static int (*checkSecurityProc)(void *, struct rx_call *) = NULL;
+static void *securityRock = NULL;
+
+struct version_data version_globals;
#define CStampVersion 1 /* meaning set ts->version */
{
struct rx_connection *conn;
+ UBIK_ADDR_LOCK;
conn = as->disk_rxcid;
#ifdef AFS_PTHREAD_ENV
rx_GetConnection(conn);
+ UBIK_ADDR_UNLOCK;
DBRELE(atrans->dbase);
+#else
+ UBIK_ADDR_UNLOCK;
#endif /* AFS_PTHREAD_ENV */
return conn;
*conn = NULL;
if (code) { /* failure */
*rcode = code;
+ UBIK_BEACON_LOCK;
(*ts)->up = 0; /* mark as down now; beacons will no longer be sent */
(*ts)->beaconSinceDown = 0;
+ UBIK_BEACON_UNLOCK;
(*ts)->currentDB = 0;
urecovery_LostServer(*ts); /* tell recovery to try to resend dbase later */
} else { /* success */
}
if (!(*ts))
return 1;
+ UBIK_BEACON_LOCK;
if (!(*ts)->up || !(*ts)->currentDB) {
+ UBIK_BEACON_UNLOCK;
(*ts)->currentDB = 0; /* db is no longer current; we just missed an update */
return 0; /* not up-to-date, don't bother. NULL conn will tell caller not to use */
}
+ UBIK_BEACON_UNLOCK;
*conn = Quorum_StartIO(atrans, *ts);
return 0;
}
bulkdata tcbs;
afs_int32 i, offset;
- Quorum_EndIO(atrans, conn);
- conn = Quorum_StartIO(atrans, ts);
-
for (i = 0, offset = 0; i < io_vector->iovec_wrt_len; i++) {
/* Sanity check for going off end of buffer */
if ((offset + iovec[i].length) > io_buffer->iovec_buf_len) {
return ContactQuorum_rcode(okcalls, rcode);
}
+#if defined(AFS_PTHREAD_ENV)
+static int
+ubik_thread_create(pthread_attr_t *tattr, pthread_t *thread, void *proc) {
+ osi_Assert(pthread_attr_init(tattr) == 0);
+ osi_Assert(pthread_attr_setdetachstate(tattr, PTHREAD_CREATE_DETACHED) == 0);
+ osi_Assert(pthread_create(thread, tattr, proc, NULL) == 0);
+ return 0;
+}
+#endif
/*!
* \brief This routine initializes the ubik system for a set of servers.
afs_int32 secIndex;
struct rx_securityClass *secClass;
+ int numClasses;
struct rx_service *tservice;
memset(&tdb->cachedVersion, 0, sizeof(struct ubik_version));
#ifdef AFS_PTHREAD_ENV
MUTEX_INIT(&tdb->versionLock, "version lock", MUTEX_DEFAULT, 0);
+ MUTEX_INIT(&beacon_globals.beacon_lock, "beacon lock", MUTEX_DEFAULT, 0);
+ MUTEX_INIT(&vote_globals.vote_lock, "vote lock", MUTEX_DEFAULT, 0);
+ MUTEX_INIT(&addr_globals.addr_lock, "address lock", MUTEX_DEFAULT, 0);
#else
Lock_Init(&tdb->versionLock);
#endif
return code;
udisk_Init(ubik_nBuffers);
+ ulock_Init();
+
+ code = uvote_Init();
+ if (code)
+ return code;
+ code = urecovery_Initialize(tdb);
+ if (code)
+ return code;
+ if (info)
+ code = ubeacon_InitServerListByInfo(myHost, info, clones);
+ else
+ code = ubeacon_InitServerList(myHost, serverList);
+ if (code)
+ return code;
ubik_callPortal = myPort;
/* try to get an additional security object */
- ubik_sc[0] = rxnull_NewServerSecurityObject();
- ubik_sc[1] = 0;
- ubik_sc[2] = 0;
- if (ubik_SRXSecurityProc) {
- code =
- (*ubik_SRXSecurityProc) (ubik_SRXSecurityRock, &secClass,
- &secIndex);
- if (code == 0) {
- ubik_sc[secIndex] = secClass;
+ if (buildSecClassesProc == NULL) {
+ numClasses = 3;
+ ubik_sc = calloc(numClasses, sizeof(struct rx_securityClass *));
+ ubik_sc[0] = rxnull_NewServerSecurityObject();
+ if (ubik_SRXSecurityProc) {
+ code = (*ubik_SRXSecurityProc) (ubik_SRXSecurityRock,
+ &secClass,
+ &secIndex);
+ if (code == 0) {
+ ubik_sc[secIndex] = secClass;
+ }
}
+ } else {
+ (*buildSecClassesProc) (securityRock, &ubik_sc, &numClasses);
}
/* for backwards compat this should keep working as it does now
and not host bind */
-#if 0
- /* This really needs to be up above, where I have put it. It works
- * here when we're non-pthreaded, but the code above, when using
- * pthreads may (and almost certainly does) end up calling on a
- * pthread resource which gets initialized by rx_Init. The end
- * result is that an assert fails and the program dies. -- klm
- */
- code = rx_Init(myPort);
- if (code < 0)
- return code;
-#endif
tservice =
- rx_NewService(0, VOTE_SERVICE_ID, "VOTE", ubik_sc, 3,
+ rx_NewService(0, VOTE_SERVICE_ID, "VOTE", ubik_sc, numClasses,
VOTE_ExecuteRequest);
if (tservice == (struct rx_service *)0) {
ubik_dprint("Could not create VOTE rx service!\n");
rx_SetMaxProcs(tservice, 3);
tservice =
- rx_NewService(0, DISK_SERVICE_ID, "DISK", ubik_sc, 3,
+ rx_NewService(0, DISK_SERVICE_ID, "DISK", ubik_sc, numClasses,
DISK_ExecuteRequest);
if (tservice == (struct rx_service *)0) {
ubik_dprint("Could not create DISK rx service!\n");
* the "steplock" problem in ubik initialization. Defect 11037.
*/
#ifdef AFS_PTHREAD_ENV
-/* do assert stuff */
- osi_Assert(pthread_attr_init(&rxServer_tattr) == 0);
- osi_Assert(pthread_attr_setdetachstate(&rxServer_tattr, PTHREAD_CREATE_DETACHED) == 0);
-/* osi_Assert(pthread_attr_setstacksize(&rxServer_tattr, rx_stackSize) == 0); */
-
- osi_Assert(pthread_create(&rxServerThread, &rxServer_tattr, (void *)rx_ServerProc, NULL) == 0);
+ ubik_thread_create(&rxServer_tattr, &rxServerThread, (void *)rx_ServerProc);
#else
LWP_CreateProcess(rx_ServerProc, rx_stackSize, RX_PROCESS_PRIORITY,
NULL, "rx_ServerProc", &junk);
#endif
- /* do basic initialization */
- code = uvote_Init();
- if (code)
- return code;
- code = urecovery_Initialize(tdb);
- if (code)
- return code;
- if (info)
- code = ubeacon_InitServerListByInfo(myHost, info, clones);
- else
- code = ubeacon_InitServerList(myHost, serverList);
- if (code)
- return code;
-
/* now start up async processes */
#ifdef AFS_PTHREAD_ENV
-/* do assert stuff */
- osi_Assert(pthread_attr_init(&ubeacon_Interact_tattr) == 0);
- osi_Assert(pthread_attr_setdetachstate(&ubeacon_Interact_tattr, PTHREAD_CREATE_DETACHED) == 0);
-/* osi_Assert(pthread_attr_setstacksize(&ubeacon_Interact_tattr, 16384) == 0); */
- /* need another attr set here for priority??? - klm */
-
- osi_Assert(pthread_create(&ubeacon_InteractThread, &ubeacon_Interact_tattr,
- (void *)ubeacon_Interact, NULL) == 0);
+ ubik_thread_create(&ubeacon_Interact_tattr, &ubeacon_InteractThread,
+ (void *)ubeacon_Interact);
#else
code = LWP_CreateProcess(ubeacon_Interact, 16384 /*8192 */ ,
LWP_MAX_PRIORITY - 1, (void *)0, "beacon",
#endif
#ifdef AFS_PTHREAD_ENV
-/* do assert stuff */
- osi_Assert(pthread_attr_init(&urecovery_Interact_tattr) == 0);
- osi_Assert(pthread_attr_setdetachstate(&urecovery_Interact_tattr, PTHREAD_CREATE_DETACHED) == 0);
-/* osi_Assert(pthread_attr_setstacksize(&urecovery_Interact_tattr, 16384) == 0); */
- /* need another attr set here for priority??? - klm */
-
- osi_Assert(pthread_create(&urecovery_InteractThread, &urecovery_Interact_tattr,
- (void *)urecovery_Interact, NULL) == 0);
-
+ ubik_thread_create(&urecovery_Interact_tattr, &urecovery_InteractThread,
+ (void *)urecovery_Interact);
return 0; /* is this correct? - klm */
#else
code = LWP_CreateProcess(urecovery_Interact, 16384 /*8192 */ ,
DBRELE(dbase);
return code;
}
+ UBIK_VERSION_LOCK;
if (readAny) {
tt->flags |= TRREADANY;
if (readAny > 1) {
udisk_abort(tt);
ContactQuorum_NoArguments(DISK_Abort, tt, 0); /* force aborts to the others */
udisk_end(tt);
+ UBIK_VERSION_UNLOCK;
DBRELE(dbase);
return code;
}
}
*transPtr = tt;
+ UBIK_VERSION_UNLOCK;
DBRELE(dbase);
return 0;
}
break;
}
for (ts = ubik_servers; ts; ts = ts->next) {
+ UBIK_BEACON_LOCK;
if (!ts->beaconSinceDown && now <= ts->lastBeaconSent + BIGTIME) {
+ UBIK_BEACON_UNLOCK;
/* this guy could have some damaged data, wait for him */
code = 1;
break;
}
+ UBIK_BEACON_UNLOCK;
}
if (code == 0)
break; /* no down ones still pseudo-active */
if (transPtr->type != UBIK_WRITETRANS)
return UBADTYPE;
+
+ DBHOLD(transPtr->dbase);
if (!transPtr->iovec_info.iovec_wrt_len
- || !transPtr->iovec_info.iovec_wrt_val)
+ || !transPtr->iovec_info.iovec_wrt_val) {
+ DBRELE(transPtr->dbase);
return 0;
+ }
- DBHOLD(transPtr->dbase);
if (!urecovery_AllBetter(transPtr->dbase, transPtr->flags & TRREADANY))
ERROR_EXIT(UNOQUORUM);
if (!ubeacon_AmSyncSite()) /* only sync site can write */
return 0;
}
+ DBHOLD(transPtr->dbase);
if (!transPtr->iovec_info.iovec_wrt_val) {
transPtr->iovec_info.iovec_wrt_len = 0;
transPtr->iovec_info.iovec_wrt_val =
if (transPtr->iovec_data.iovec_buf_val)
free(transPtr->iovec_data.iovec_buf_val);
transPtr->iovec_data.iovec_buf_val = 0;
+ DBRELE(transPtr->dbase);
return UNOMEM;
}
}
/* If this write won't fit in the structure, then flush it out and start anew */
if ((transPtr->iovec_info.iovec_wrt_len >= IOVEC_MAXWRT)
|| ((length + transPtr->iovec_data.iovec_buf_len) > IOVEC_MAXBUF)) {
+ /* Can't hold the DB lock over ubik_Flush */
+ DBRELE(transPtr->dbase);
code = ubik_Flush(transPtr);
if (code)
return (code);
+ DBHOLD(transPtr->dbase);
}
- DBHOLD(transPtr->dbase);
if (!urecovery_AllBetter(transPtr->dbase, transPtr->flags & TRREADANY))
ERROR_EXIT(UNOQUORUM);
if (!ubeacon_AmSyncSite()) /* only sync site can write */
ubik_GetVersion(struct ubik_trans *atrans,
struct ubik_version *avers)
{
+ DBHOLD(atrans->dbase);
*avers = atrans->dbase->version;
+ DBRELE(atrans->dbase);
return 0;
}
struct ubik_server *ts;
int j;
+ UBIK_ADDR_LOCK;
for (ts = ubik_servers; ts; ts = ts->next)
for (j = 0; j < UBIK_MAX_INTERFACE_ADDR; j++)
- if (ts->addr[j] == addr)
+ if (ts->addr[j] == addr) {
+ UBIK_ADDR_UNLOCK;
return ts->addr[0]; /* net byte order */
+ }
+ UBIK_ADDR_UNLOCK;
return 0; /* if not in server database, return error */
}
+
+int
+ubik_CheckAuth(struct rx_call *acall)
+{
+ if (checkSecurityProc)
+ return (*checkSecurityProc) (securityRock, acall);
+ else if (ubik_CheckRXSecurityProc) {
+ return (*ubik_CheckRXSecurityProc) (ubik_CheckRXSecurityRock, acall);
+ } else
+ return 0;
+}
+
+void
+ubik_SetServerSecurityProcs(void (*buildproc) (void *,
+ struct rx_securityClass ***,
+ afs_int32 *),
+ int (*checkproc) (void *, struct rx_call *),
+ void *rock)
+{
+ buildSecClassesProc = buildproc;
+ checkSecurityProc = checkproc;
+ securityRock = rock;
+}