Exemplo n.º 1
0
/* Implements the remote setpag(2) call. Note that unlike the standard call,
 * here we also get back the new pag value; we need this so that the caller
 * can add it to its group list via setgroups() */
afs_int32
SRMTSYS_SetPag(struct rx_call *call, clientcred *creds, afs_int32 *newpag,
	       afs_int32 *errornumber)
{
    afs_uint32 blob[PIOCTL_HEADER];
    struct ViceIoctl data;
    afs_int32 error;

    *errornumber = 0;
    SETCLIENTCONTEXT(blob, rx_HostOf(rx_PeerOf(rx_ConnectionOf(call))), creds->uid,
		     creds->group0, creds->group1, PSETPAG, NFS_EXPORTER);
    data.in = (caddr_t) blob;
    data.in_size = sizeof(blob);
    data.out = (caddr_t) blob;
    data.out_size = sizeof(blob);
    /* force local pioctl call */
    error = lpioctl(0, _VICEIOCTL(PSetClientContext), &data, 1);
    if (error) {
	if (errno == PSETPAG) {
	    *newpag = blob[0];	/* new pag value */
	} else
	    *errornumber = errno;
    }
    return 0;
}
Exemplo n.º 2
0
/*!
 * \brief Call this after getting back a #UNOTSYNC.
 *
 * \note Getting a #UNOTSYNC error code back does \b not guarantee
 * that there is a sync site yet elected.  However, if there is a sync
 * site out there somewhere, and you're trying an operation that
 * requires a sync site, ubik will return #UNOTSYNC, indicating the
 * operation won't work until you find a sync site
 */
static int
try_GetSyncSite(struct ubik_client *aclient, afs_int32 apos)
{
    struct rx_peer *rxp;
    afs_int32 code;
    int i;
    afs_int32 thisHost, newHost;
    struct rx_connection *tc;
    short origLevel;

    origLevel = aclient->initializationState;

    /* get this conn */
    tc = aclient->conns[apos];
    if (tc && rx_ConnError(tc)) {
	aclient->conns[apos] = (tc = ubik_RefreshConn(tc));
    }
    if (!tc) {
	return -1;
    }

    /* now see if we can find the sync site host */
    code = VOTE_GetSyncSite(tc, &newHost);
    if (aclient->initializationState != origLevel) {
	return -1;		/* somebody did a ubik_ClientInit */
    }

    if (!code && newHost) {
	newHost = htonl(newHost);	/* convert back to network order */

	/*
	 * position count at the appropriate slot in the client
	 * structure and retry. If we can't find in slot, we'll just
	 * continue through the whole list
	 */
	for (i = 0; i < MAXSERVERS; i++) {
	    rxp = rx_PeerOf(aclient->conns[i]);
	    thisHost = rx_HostOf(rxp);
	    if (!thisHost) {
		return -1;
	    } else if (thisHost == newHost) {
		return i;	/* we were told to use this one */
	    }
	}
    }
    return -1;
}
Exemplo n.º 3
0
/* Implements the remote pioctl(2) call */
afs_int32
SRMTSYS_Pioctl(struct rx_call *call, clientcred *creds, char *path,
	       afs_int32 cmd, afs_int32 follow, rmtbulk *InData,
	       rmtbulk *OutData, afs_int32 *errornumber)
{
    afs_int32 error;
    struct ViceIoctl data;
    char *pathp = path;
    afs_uint32 blob[PIOCTL_HEADER];

    *errornumber = 0;
    SETCLIENTCONTEXT(blob, rx_HostOf(call->conn->peer), creds->uid,
		     creds->group0, creds->group1, cmd, NFS_EXPORTER);
    data.in =
	(char *)malloc(InData->rmtbulk_len +
		       PIOCTL_HEADER * sizeof(afs_int32));
    if (!data.in)
	return (-1);		/* helpless here */
    if (!strcmp(path, NIL_PATHP))
	pathp = (char *)0;	/* It meant to be NIL */
    memcpy(data.in, blob, sizeof(blob));
    inparam_conversion(cmd, InData->rmtbulk_val, 1);
    memcpy(data.in + sizeof(blob), InData->rmtbulk_val, InData->rmtbulk_len);
    data.in_size = InData->rmtbulk_len + PIOCTL_HEADER * sizeof(afs_int32);
    data.out = OutData->rmtbulk_val;
    data.out_size = OutData->rmtbulk_len;
    /* force local pioctl call */
    error = lpioctl(pathp, _VICEIOCTL(PSetClientContext), &data, follow);
    if (error) {
	*errornumber = errno;
    } else {
	/* Send the results back in network order */
	outparam_conversion(cmd, data.out, 0);
    }
    free(data.in);
    /* Note that we return success (i.e. 0) even when pioctl fails; that's
     * because the actual errno is passed back via 'errornumber' and this call
     * MUST return success error in order to get that OUT params back (YUCK!)
     */
    return (0);
}
Exemplo n.º 4
0
/*!
 * \brief So that intermittent failures that cause connections to die
 *     don't kill whole ubik connection, refresh them when the connection is in
 *     error.
 */
struct rx_connection *
ubik_RefreshConn(struct rx_connection *tc)
{
    afs_uint32 host;
    u_short port;
    u_short service;
    struct rx_securityClass *sc;
    int si;
    struct rx_connection *newTc;

    host = rx_HostOf(rx_PeerOf(tc));
    port = rx_PortOf(rx_PeerOf(tc));
    service = rx_ServiceIdOf(tc);
    sc = rx_SecurityObjectOf(tc);
    si = rx_SecurityClassOf(tc);

    /*
     * destroy old one after creating new one so that refCount on security
     * object cannot reach zero.
     */
    newTc = rx_NewConnection(host, port, service, sc, si);
    rx_DestroyConnection(tc);
    return newTc;
}
Exemplo n.º 5
0
afs_int32
SDISK_SendFile(struct rx_call *rxcall, afs_int32 file,
	       afs_int32 length, struct ubik_version *avers)
{
    afs_int32 code;
    struct ubik_dbase *dbase = NULL;
    char tbuffer[1024];
    afs_int32 offset;
    struct ubik_version tversion;
    int tlen;
    struct rx_peer *tpeer;
    struct rx_connection *tconn;
    afs_uint32 otherHost = 0;
    char hoststr[16];
    char pbuffer[1028];
    int fd = -1;
    afs_int32 epoch = 0;
    afs_int32 pass;

    /* send the file back to the requester */

    dbase = ubik_dbase;

    if ((code = ubik_CheckAuth(rxcall))) {
	DBHOLD(dbase);
	goto failed;
    }

    /* next, we do a sanity check to see if the guy sending us the database is
     * the guy we think is the sync site.  It turns out that we might not have
     * decided yet that someone's the sync site, but they could have enough
     * votes from others to be sync site anyway, and could send us the database
     * in advance of getting our votes.  This is fine, what we're really trying
     * to check is that some authenticated bogon isn't sending a random database
     * into another configuration.  This could happen on a bad configuration
     * screwup.  Thus, we only object if we're sure we know who the sync site
     * is, and it ain't the guy talking to us.
     */
    offset = uvote_GetSyncSite();
    tconn = rx_ConnectionOf(rxcall);
    tpeer = rx_PeerOf(tconn);
    otherHost = ubikGetPrimaryInterfaceAddr(rx_HostOf(tpeer));
    if (offset && offset != otherHost) {
	/* we *know* this is the wrong guy */
	code = USYNC;
	DBHOLD(dbase);
	goto failed;
    }

    DBHOLD(dbase);

    /* abort any active trans that may scribble over the database */
    urecovery_AbortAll(dbase);

    ubik_print("Ubik: Synchronize database with server %s\n",
	       afs_inet_ntoa_r(otherHost, hoststr));

    offset = 0;
    UBIK_VERSION_LOCK;
    epoch = tversion.epoch = 0;		/* start off by labelling in-transit db as invalid */
    (*dbase->setlabel) (dbase, file, &tversion);	/* setlabel does sync */
    snprintf(pbuffer, sizeof(pbuffer), "%s.DB%s%d.TMP",
	     ubik_dbase->pathName, (file<0)?"SYS":"",
	     (file<0)?-file:file);
    fd = open(pbuffer, O_CREAT | O_RDWR | O_TRUNC, 0600);
    if (fd < 0) {
	code = errno;
	goto failed_locked;
    }
    code = lseek(fd, HDRSIZE, 0);
    if (code != HDRSIZE) {
	close(fd);
	goto failed_locked;
    }
    pass = 0;
    memcpy(&ubik_dbase->version, &tversion, sizeof(struct ubik_version));
    UBIK_VERSION_UNLOCK;
    while (length > 0) {
	tlen = (length > sizeof(tbuffer) ? sizeof(tbuffer) : length);
#if !defined(AFS_PTHREAD_ENV)
	if (pass % 4 == 0)
	    IOMGR_Poll();
#endif
	code = rx_Read(rxcall, tbuffer, tlen);
	if (code != tlen) {
	    ubik_dprint("Rx-read length error=%d\n", code);
	    code = BULK_ERROR;
	    close(fd);
	    goto failed;
	}
	code = write(fd, tbuffer, tlen);
	pass++;
	if (code != tlen) {
	    ubik_dprint("write failed error=%d\n", code);
	    code = UIOERROR;
	    close(fd);
	    goto failed;
	}
	offset += tlen;
	length -= tlen;
    }
    code = close(fd);
    if (code)
	goto failed;

    /* sync data first, then write label and resync (resync done by setlabel call).
     * This way, good label is only on good database. */
    snprintf(tbuffer, sizeof(tbuffer), "%s.DB%s%d",
	     ubik_dbase->pathName, (file<0)?"SYS":"", (file<0)?-file:file);
#ifdef AFS_NT40_ENV
    snprintf(pbuffer, sizeof(pbuffer), "%s.DB%s%d.OLD",
	     ubik_dbase->pathName, (file<0)?"SYS":"", (file<0)?-file:file);
    code = unlink(pbuffer);
    if (!code)
	code = rename(tbuffer, pbuffer);
    snprintf(pbuffer, sizeof(pbuffer), "%s.DB%s%d.TMP",
	     ubik_dbase->pathName, (file<0)?"SYS":"", (file<0)?-file:file);
#endif
    if (!code)
	code = rename(pbuffer, tbuffer);
    UBIK_VERSION_LOCK;
    if (!code) {
	(*ubik_dbase->open) (ubik_dbase, file);
	code = (*ubik_dbase->setlabel) (dbase, file, avers);
    }
#ifdef AFS_NT40_ENV
    snprintf(pbuffer, sizeof(pbuffer), "%s.DB%s%d.OLD",
	     ubik_dbase->pathName, (file<0)?"SYS":"", (file<0)?-file:file);
    unlink(pbuffer);
#endif
    memcpy(&ubik_dbase->version, avers, sizeof(struct ubik_version));
    udisk_Invalidate(dbase, file);	/* new dbase, flush disk buffers */
#ifdef AFS_PTHREAD_ENV
    assert(pthread_cond_broadcast(&dbase->version_cond) == 0);
#else
    LWP_NoYieldSignal(&dbase->version);
#endif

failed_locked:
    UBIK_VERSION_UNLOCK;

failed:
    if (code) {
	unlink(pbuffer);
	/* Failed to sync. Allow reads again for now. */
	if (dbase != NULL) {
	    UBIK_VERSION_LOCK;
	    tversion.epoch = epoch;
	    (*dbase->setlabel) (dbase, file, &tversion);
	    UBIK_VERSION_UNLOCK;
	}
	ubik_print
	    ("Ubik: Synchronize database with server %s failed (error = %d)\n",
	     afs_inet_ntoa_r(otherHost, hoststr), code);
    } else {
	ubik_print("Ubik: Synchronize database completed\n");
    }
    DBRELE(dbase);
    return code;
}
Exemplo n.º 6
0
int
SPAGCB_GetCreds(struct rx_call *a_call, afs_int32 a_uid,
                CredInfos *a_creds)
{
    struct unixuser *tu;
    CredInfo *tci;
    int bucket, count, i = 0, clen;
    char *cellname;

    RX_AFS_GLOCK();

    memset(a_creds, 0, sizeof(struct CredInfos));
    if ((rx_HostOf(rx_PeerOf(rx_ConnectionOf(a_call))) != afs_nfs_server_addr
	||  rx_PortOf(rx_PeerOf(rx_ConnectionOf(a_call))) != htons(7001))
#if 0 /* for debugging ONLY! */
	&&  rx_PortOf(rx_PeerOf(rx_ConnectionOf(a_call))) != htons(7901)
#endif
        ) {
	RX_AFS_GUNLOCK();
	return UAEPERM;
    }

    ObtainWriteLock(&afs_xuser, 823);

    /* count them first */
    bucket = UHash(a_uid);
    for (count = 0, tu = afs_users[bucket]; tu; tu = tu->next) {
	if (tu->uid == a_uid) count++;
    }

    if (!count) {
	ReleaseWriteLock(&afs_xuser);
	RX_AFS_GUNLOCK();
	return UAESRCH;
    }

    a_creds->CredInfos_val =
	(CredInfo *)afs_osi_Alloc(count * sizeof(CredInfo));
    if (!a_creds->CredInfos_val)
	goto out;
    a_creds->CredInfos_len = count;
    memset(a_creds->CredInfos_val, 0, count * sizeof(CredInfo));

    for (i = 0, tu = afs_users[bucket]; tu; tu = tu->next, i++) {
	if (tu->uid == a_uid && tu->cellinfo &&
	    (tu->states & UHasTokens) && !(tu->states & UTokensBad)) {

	    tci = &a_creds->CredInfos_val[i];
	    tci->vid               = tu->vid;
	    tci->ct.AuthHandle     = tu->ct.AuthHandle;
	    memcpy(tci->ct.HandShakeKey, tu->ct.HandShakeKey, 8);
	    tci->ct.ViceId         = tu->ct.ViceId;
	    tci->ct.BeginTimestamp = tu->ct.BeginTimestamp;
	    tci->ct.EndTimestamp   = tu->ct.EndTimestamp;

	    cellname = ((struct afspag_cell *)(tu->cellinfo))->cellname;
	    clen = strlen(cellname) + 1;
	    tci->cellname = afs_osi_Alloc(clen);
	    if (!tci->cellname)
		goto out;
	    memcpy(tci->cellname, cellname, clen);

	    tci->st.st_len = tu->stLen;
	    tci->st.st_val = afs_osi_Alloc(tu->stLen);
	    if (!tci->st.st_val) {
		afs_osi_Free(tci->cellname, clen);
		goto out;
	    }
	    memcpy(tci->st.st_val, tu->stp, tu->stLen);
	    if (tu->states & UPrimary)
		tci->states |= UPrimary;
	}
    }

    ReleaseWriteLock(&afs_xuser);
    RX_AFS_GUNLOCK();
    return 0;

out:
    if (a_creds->CredInfos_val) {
	while (i-- > 0) {
	    afs_osi_Free(a_creds->CredInfos_val[i].st.st_val,
			 a_creds->CredInfos_val[i].st.st_len);
	    afs_osi_Free(a_creds->CredInfos_val[i].cellname,
			 strlen(a_creds->CredInfos_val[i].cellname) + 1);
	}
	afs_osi_Free(a_creds->CredInfos_val, count * sizeof(CredInfo));
    }

    ReleaseWriteLock(&afs_xuser);
    RX_AFS_GUNLOCK();
    return UAENOMEM;
}
Exemplo n.º 7
0
/*!
 * call this instead of stub and we'll guarantee to find a host that's up.
 *
 * \todo In the future, we should also put in a protocol to find the sync site.
 */
afs_int32
ubik_Call(int (*aproc) (), struct ubik_client *aclient,
	  afs_int32 aflags, long p1, long p2, long p3, long p4,
	  long p5, long p6, long p7, long p8, long p9, long p10,
	  long p11, long p12, long p13, long p14, long p15, long p16)
{
    afs_int32 rcode, code, newHost, thisHost, i, count;
    int chaseCount, pass, needsync, inlist, j;
    struct rx_connection *tc;
    struct rx_peer *rxp;
    short origLevel;

    if (aflags & UBIK_CALL_NEW)
	return ubik_Call_New(aproc, aclient, aflags, p1, p2, p3, p4,
			     p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15,
			     p16);

    if (!aclient)
	return UNOENT;
    LOCK_UBIK_CLIENT(aclient);

  restart:
    origLevel = aclient->initializationState;
    rcode = UNOSERVERS;
    chaseCount = inlist = needsync = 0;

    LOCK_UCLNT_CACHE;
    for (j = 0; ((j < SYNCCOUNT) && calls_needsync[j]); j++) {
	if (calls_needsync[j] == (int *)aproc) {
	    inlist = needsync = 1;
	    break;
	}
    }
    UNLOCK_UCLNT_CACHE;
    /*
     * First  pass, we try all servers that are up.
     * Second pass, we try all servers.
     */
    for (pass = 0; pass < 2; pass++) {	/*p */
	/* For each entry in our servers list */
	for (count = 0;; count++) {	/*s */

	    if (needsync) {
		/* Need a sync site. Lets try to quickly find it */
		if (aclient->syncSite) {
		    newHost = aclient->syncSite;	/* already in network order */
		    aclient->syncSite = 0;	/* Will reset if it works */
		} else if (aclient->conns[3]) {
		    /* If there are fewer than four db servers in a cell,
		     * there's no point in making the GetSyncSite call.
		     * At best, it's a wash. At worst, it results in more
		     * RPCs than you would otherwise make.
		     */
		    tc = aclient->conns[count];
		    if (tc && rx_ConnError(tc)) {
			aclient->conns[count] = tc = ubik_RefreshConn(tc);
		    }
		    if (!tc)
			break;
		    code = VOTE_GetSyncSite(tc, &newHost);
		    if (aclient->initializationState != origLevel)
			goto restart;	/* somebody did a ubik_ClientInit */
		    if (code)
			newHost = 0;
		    newHost = htonl(newHost);	/* convert to network order */
		} else {
		    newHost = 0;
		}
		if (newHost) {
		    /* position count at the appropriate slot in the client
		     * structure and retry. If we can't find in slot, we'll
		     * just continue through the whole list
		     */
		    for (i = 0; i < MAXSERVERS && aclient->conns[i]; i++) {
			rxp = rx_PeerOf(aclient->conns[i]);
			thisHost = rx_HostOf(rxp);
			if (!thisHost)
			    break;
			if (thisHost == newHost) {
			    if (chaseCount++ > 2)
				break;	/* avoid loop asking */
			    count = i;	/* this index is the sync site */
			    break;
			}
		    }
		}
	    }
	    /*needsync */
	    tc = aclient->conns[count];
	    if (tc && rx_ConnError(tc)) {
		aclient->conns[count] = tc = ubik_RefreshConn(tc);
	    }
	    if (!tc)
		break;

	    if ((pass == 0) && (aclient->states[count] & CFLastFailed)) {
		continue;	/* this guy's down */
	    }

	    rcode =
		(*aproc) (tc, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11,
			  p12, p13, p14, p15, p16);
	    if (aclient->initializationState != origLevel) {
		/* somebody did a ubik_ClientInit */
		if (rcode)
		    goto restart;	/* call failed */
		else
		    goto done;	/* call suceeded */
	    }
	    if (rcode < 0) {	/* network errors */
		aclient->states[count] |= CFLastFailed;	/* Mark serer down */
	    } else if (rcode == UNOTSYNC) {
		needsync = 1;
	    } else if (rcode != UNOQUORUM) {
		/* either misc ubik code, or misc appl code, or success. */
		aclient->states[count] &= ~CFLastFailed;	/* mark server up */
		goto done;	/* all done */
	    }
	}			/*s */
    }				/*p */

  done:
    if (needsync) {
	if (!inlist) {		/* Remember proc call that needs sync site */
	    LOCK_UCLNT_CACHE;
	    calls_needsync[synccount % SYNCCOUNT] = (int *)aproc;
	    synccount++;
	    UNLOCK_UCLNT_CACHE;
	    inlist = 1;
	}
	if (!rcode) {		/* Remember the sync site - cmd successful */
	    rxp = rx_PeerOf(aclient->conns[count]);
	    aclient->syncSite = rx_HostOf(rxp);
	}
    }
    UNLOCK_UBIK_CLIENT(aclient);
    return rcode;
}
Exemplo n.º 8
0
static int
Main(struct cmd_syndesc *as, void *arock)
{
    int code;
    char name[MAXKTCNAMELEN];
    char instance[MAXKTCNAMELEN];
    char newCell[MAXKTCREALMLEN];
    char *cell;

    long serverList[MAXSERVERS];
    extern struct passwd *getpwuid();

    struct passwd *pw;
    struct ktc_encryptionKey key;

    char passwd[BUFSIZ];

    int cellSpecified;
    int i;
    int verbose = (as->parms[1].items != 0);
    int hostUsage = (as->parms[2].items != 0);
    int waitReap = (as->parms[4].items != 0);
    int doAuth = (as->parms[5].items != 0);
    int number;			/* number of iterations */
    int callsPerSecond;		/* to allow conn GC to run */

    unsigned long lo, hi;	/* mem usage */
    unsigned long highWater;	/* mem usage after reap period */
    unsigned long lastWater;	/* mem usage after last msg */
    int serversUse[MAXSERVERS];	/* usage of each server */
    long serversHost[MAXSERVERS];	/* host addr */
    unsigned long startTime;
    unsigned long now;

    lo = 0;
    whoami = as->a0name;
    newCell[0] = 0;

    if (as->parms[0].items)
	number = atoi(as->parms[0].items->data);
    else
	number = 100;
    if (as->parms[3].items)
	callsPerSecond = atoi(as->parms[3].items->data);
    else
	callsPerSecond = 1;
    if (doAuth && hostUsage) {
	fprintf(stderr,
		"Can't report host usage when calling UserAuthenticate\n");
	return -1;
    }

    if (as->parms[12].items) {	/* if username specified */
	code =
	    ka_ParseLoginName(as->parms[12].items->data, name, instance,
			      newCell);
	if (code) {
	    afs_com_err(whoami, code, "parsing user's name '%s'",
		    as->parms[12].items->data);
	    return code;
	}
	if (strlen(newCell) > 0)
	    cellSpecified = 1;
    } else {
	/* No explicit name provided: use Unix uid. */
	pw = getpwuid(getuid());
	if (pw == 0) {
	    printf("Can't figure out your name from your user id.\n");
	    return KABADCMD;
	}
	strncpy(name, pw->pw_name, sizeof(name));
	strcpy(instance, "");
	strcpy(newCell, "");
    }
    if (strcmp(as->parms[14].name, "-cell") == 0) {
	if (as->parms[14].items) {	/* if cell specified */
	    if (cellSpecified)
		printf("Duplicate cell specification not allowed\n");
	    else
		strncpy(newCell, as->parms[14].items->data, sizeof(newCell));
	}
    }

    code = ka_ExpandCell(newCell, newCell, 0 /*local */ );
    if (code) {
	afs_com_err(whoami, code, "Can't expand cell name");
	return code;
    }
    cell = newCell;

    if (as->parms[13].items) {	/* if password specified */
	strncpy(passwd, as->parms[13].items->data, sizeof(passwd));
	memset(as->parms[13].items->data, 0,
	       strlen(as->parms[13].items->data));
    } else {
	char msg[sizeof(name) + 15];
	if (as->parms[12].items)
	    strcpy(msg, "Admin Password: "******"Password for %s: ", name);
	code = read_pw_string(passwd, sizeof(passwd), msg, 0);
	if (code)
	    code = KAREADPW;
	else if (strlen(passwd) == 0)
	    code = KANULLPASSWORD;
	if (code) {
	    afs_com_err(whoami, code, "reading password");
	    return code;
	}
    }
    if (as->parms[15].items) {
	struct cmd_item *ip;
	char *ap[MAXSERVERS + 2];

	for (ip = as->parms[15].items, i = 2; ip; ip = ip->next, i++)
	    ap[i] = ip->data;
	ap[0] = "";
	ap[1] = "-servers";
	code = ubik_ParseClientList(i, ap, serverList);
	if (code) {
	    afs_com_err(whoami, code, "could not parse server list");
	    return code;
	}
	ka_ExplicitCell(cell, serverList);
    }

    if (!doAuth) {
	ka_StringToKey(passwd, cell, &key);
	memset(passwd, 0, sizeof(passwd));
    }
    if (hostUsage) {
	memset(serversUse, 0, sizeof(serversUse));
	memset(serversHost, 0, sizeof(serversHost));
    }

    startTime = time(0);
    for (i = 0; i < number; i++) {
	if (doAuth) {
	    char *reason;
	    code =
		ka_UserAuthenticateLife(0, name, instance, cell, passwd, 0,
					&reason);
	    if (code) {
		fprintf(stderr, "Unable to authenticate to AFS because %s.\n",
			reason);
		return code;
	    }
	} else {
	    struct ktc_token token;
	    struct ktc_token *pToken;
	    struct ubik_client *ubikConn;
	    struct kaentryinfo tentry;
	    int c;

	    code =
		ka_GetAdminToken(name, instance, cell, &key, 3600, &token,
				 1 /*new */ );
	    if (code) {
		afs_com_err(whoami, code, "getting admin token");
		return code;
	    }
	    pToken = &token;
	    if (token.ticketLen == 0) {
		fprintf("Can't get admin token\n");
		return -1;
	    }

	    code =
		ka_AuthServerConn(cell, KA_MAINTENANCE_SERVICE, pToken,
				  &ubikConn);
	    if (code) {
		afs_com_err(whoami, code, "Getting AuthServer ubik conn");
		return code;
	    }

	    if (verbose)
		for (c = 0; c < MAXSERVERS; c++) {
		    struct rx_connection *rxConn =
			ubik_GetRPCConn(ubikConn, c);
		    struct rx_peer *peer;

		    if (rxConn == 0)
			break;
		    peer = rx_PeerOf(rxConn);
		    printf("conn to %s:%d secObj:%x\n",
			   inet_ntoa(rx_HostOf(peer)), ntohs(rx_PortOf(peer)),
			   rxConn->securityObject);
		}

	    code =
		ubik_Call(KAM_GetEntry, ubikConn, 0, name, instance,
			  KAMAJORVERSION, &tentry);
	    if (code) {
		afs_com_err(whoami, code, "getting information for %s.%s", name,
			instance);
		return code;
	    }

	    for (c = 0; c < MAXSERVERS; c++) {
		struct rx_connection *rxConn = ubik_GetRPCConn(ubikConn, c);
		int d;
		if (rxConn == 0)
		    break;
		if (rxConn->serial > 0) {
		    long host = rx_HostOf(rx_PeerOf(rxConn));
		    for (d = 0; d < MAXSERVERS; d++) {
			if (serversHost[d] == 0)
			    serversHost[d] = host;
			if (host == serversHost[d]) {
			    serversUse[d]++;
			    break;
			}
		    }
		}
		if (verbose)
		    printf("serial is %d\n", rxConn->serial);
	    }
	    ubik_ClientDestroy(ubikConn);
	}

	now = time(0);
	if (!lo)
	    lo = sbrk(0);
	if (i && ((i & 0x3f) == 0)) {
	    unsigned long this = sbrk(0);
	    printf("  mem after %d: lo=%x, cur=%x => %d (@ %d)\n", i, lo,
		   this, this - lo, (this - lo) / i);
	    if (highWater && (lastWater != this)) {
		lastWater = this;
		printf("  core leaking (after %d) should be %x, is %x\n", i,
		       highWater, this);
	    }
	}
	if ((highWater == 0) && ((now - startTime) > 61)) {
	    highWater = sbrk(0);
	    lastWater = highWater;
	    printf("  mem highWater mark (after %d) should be %x\n", i,
		   highWater);
	}
	if (callsPerSecond) {
	    long target;
	    if (callsPerSecond > 0)
		target = i / callsPerSecond;
	    else		/* if negative interpret as seconds per call */
		target = i * (-callsPerSecond);
	    target = (startTime + target) - now;
	    if (target > 0)
		IOMGR_Sleep(target);
	}
    }
Exemplo n.º 9
0
afs_int32
ubik_Call_SingleServer(int (*aproc) (), struct ubik_client *aclient,
		       afs_int32 aflags, char *p1, char *p2, char *p3,
		       char *p4, char *p5, char *p6, char *p7, char *p8,
		       char *p9, char *p10, char *p11, char *p12, char *p13,
		       char *p14, char *p15, char *p16)
{
    afs_int32 code;
    afs_int32 someCode, newHost, thisHost;
    afs_int32 i;
    afs_int32 count;
    int chaseCount;
    int pass;
    struct rx_connection *tc;
    struct rx_peer *rxp;

    if ((aflags & (UF_SINGLESERVER | UF_END_SINGLESERVER)) != 0) {
	if (((aflags & UF_SINGLESERVER) != 0)
	    && ((uServer.ucs_flags & UF_SINGLESERVER) != 0)
	    ) {

	    /* have a selected server */
	    tc = aclient->conns[uServer.ucs_selectedServer];

	    code =
		(*aproc) (tc, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11,
			  p12, p13, p14, p15, p16);
	    if (code) {
		/* error. Clean up single server state */
		memset(&uServer, 0, sizeof(uServer));
	    }
	    return (code);
	} else if ((aflags & UF_END_SINGLESERVER) != 0) {
	    memset(&uServer, 0, sizeof(uServer));
	    return (0);
	}
    }

    someCode = UNOSERVERS;
    chaseCount = 0;
    pass = 0;
    count = 0;
    while (1) {			/*w */

	/* tc is the next conn to try */
	tc = aclient->conns[count];
	if (tc == 0) {
	    if (pass == 0) {
		pass = 1;	/* in pass 1, we look at down hosts, too */
		count = 0;
		continue;
	    } else
		break;		/* nothing left to try */
	}
	if (pass == 0 && (aclient->states[count] & CFLastFailed)) {
	    count++;
	    continue;		/* this guy's down, try someone else first */
	}

	code =
	    (*aproc) (tc, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12,
		      p13, p14, p15, p16);

	/* note that getting a UNOTSYNC error code back does *not* guarantee
	 * that there is a sync site yet elected.  However, if there is a
	 * sync site out there somewhere, and you're trying an operation that
	 * requires a sync site, ubik will return UNOTSYNC, indicating the
	 * operation won't work until you find a sync site
	 */
	if (code == UNOTSYNC) {	/*ns */
	    /* means that this requires a sync site to work */
	    someCode = code;	/* remember an error, if this fails */

	    /* now see if we can find the sync site host */
	    code = VOTE_GetSyncSite(tc, &newHost);
	    if (code == 0 && newHost != 0) {
		newHost = htonl(newHost);	/* convert back to network order */

		/* position count at the appropriate slot in the client
		 * structure and retry. If we can't find in slot, we'll just
		 * continue through the whole list
		 */
		for (i = 0; i < MAXSERVERS; i++) {	/*f */
		    rxp = rx_PeerOf(aclient->conns[i]);
		    if (!(thisHost = rx_HostOf(rxp))) {
			count++;	/* host not found, try the next dude */
			break;
		    }
		    if (thisHost == newHost) {
			/* avoid asking in a loop */
			if (chaseCount++ > 2)
			    break;
			count = i;	/* we were told to use this one */
			break;
		    }
		}		/*f */
	    } else
		count++;	/* not directed, keep looking for a sync site */
	    continue;
	} /*ns */
	else if (code == UNOQUORUM) {	/* this guy is still recovering */
	    someCode = code;
	    count++;
	    continue;
	} else if (code < 0) {	/* network errors */
	    someCode = code;
	    aclient->states[count] |= CFLastFailed;
	    count++;
	    continue;
	} else {
	    /* ok, operation worked */
	    aclient->states[count] &= ~CFLastFailed;
	    /* either misc ubik code, or misc application code (incl success)
	     */

	    /* if the call succeeded, setup connection state for subsequent
	     * calls
	     */
	    if ((code == 0)
		&& ((aflags & UF_SINGLESERVER) != 0)
		) {
		/* need to save state */
		uServer.ucs_flags = UF_SINGLESERVER;
		uServer.ucs_selectedServer = count;
	    }

	    return code;
	}
    }				/*w */
    return someCode;
}
Exemplo n.º 10
0
/*!
 * \brief called by the sync site to handle vote beacons; if aconn is null, this is a
 * local call
 *
 * \returns 0 or time when the vote was sent.  It returns 0 if we are
 * not voting for this sync site, or the time we actually voted yes, if
 * non-zero.
 */
afs_int32
SVOTE_Beacon(struct rx_call * rxcall, afs_int32 astate,
	     afs_int32 astart, struct ubik_version * avers,
	     struct ubik_tid * atid)
{
    afs_int32 otherHost;
    afs_int32 now;
    afs_int32 vote;
    struct rx_connection *aconn;
    struct rx_peer *rxp;
    struct ubik_server *ts;
    int isClone = 0;
    char hoststr[16];

    if (rxcall) {		/* caller's host */
	aconn = rx_ConnectionOf(rxcall);
	rxp = rx_PeerOf(aconn);
	otherHost = rx_HostOf(rxp);

	/* get the primary interface address for this host.  */
	/* This is the identifier that ubik uses. */
	otherHost = ubikGetPrimaryInterfaceAddr(otherHost);
	if (!otherHost) {
	    ubik_dprint("Received beacon from unknown host %s\n",
			afs_inet_ntoa_r(rx_HostOf(rxp), hoststr));
	    return 0;		/* I don't know about you: vote no */
	}
	for (ts = ubik_servers; ts; ts = ts->next) {
	    if (ts->addr[0] == otherHost)
		break;
	}
	if (!ts)
	    ubik_dprint("Unknown host %x has sent a beacon\n", otherHost);
	if (ts && ts->isClone)
	    isClone = 1;
    } else {
	otherHost = ubik_host[0];	/* this host */
	isClone = amIClone;
    }

    ubik_dprint("Received beacon type %d from host %s\n", astate,
		afs_inet_ntoa_r(otherHost, hoststr));

    /* compute the lowest server we've heard from.  We'll try to only vote for
     * this dude if we don't already have a synchronization site.  Also, don't
     * let a very old lowestHost confusing things forever.  We pick a new
     * lowestHost after BIGTIME seconds to limit the damage if this host
     * actually crashes.  Finally, we also count in this computation: don't
     * pick someone else if we're even better!
     *
     * Note that the test below must be <=, not <, so that we keep refreshing
     * lowestTime.  Otherwise it will look like we haven't heard from
     * lowestHost in a while and another host could slip in.  */


    /* First compute the lowest host we've heard from, whether we want them
     * for a sync site or not.  If we haven't heard from a site in BIGTIME
     * seconds, we ignore its presence in lowestHost: it may have crashed.
     * Note that we don't ever let anyone appear in our lowestHost if we're
     * lower than them, 'cause we know we're up. */
    /* But do not consider clones for lowesHost since they never may become
     * sync site */
    UBIK_VOTE_LOCK;
    now = FT_ApproxTime();	/* close to current time */
    if (!isClone
	&& (ntohl((afs_uint32)otherHost) <= ntohl((afs_uint32)vote_globals.lowestHost)
	    || vote_globals.lowestTime + BIGTIME < now)) {
	vote_globals.lowestTime = now;
	vote_globals.lowestHost = otherHost;
    }
    /* why do we need this next check?  Consider the case where each of two
     * servers decides the other is lowestHost.  Each stops sending beacons
     * 'cause the other is there.  Not obvious that this process terminates:
     * i.e. each guy could restart procedure and again think other side is
     * lowest.  Need to prove: if one guy in the system is lowest and knows
     * he's lowest, these loops don't occur.  because if someone knows he's
     * lowest, he will send out beacons telling others to vote for him. */
    if (!amIClone
	&& (ntohl((afs_uint32) ubik_host[0]) <= ntohl((afs_uint32)vote_globals.lowestHost)
	    || vote_globals.lowestTime + BIGTIME < now)) {
	vote_globals.lowestTime = now;
	vote_globals.lowestHost = ubik_host[0];
    }

    /* tell if we've heard from a sync site recently (even if we're not voting
     * for this dude yet).  After a while, time the guy out. */
    if (astate) {		/* this guy is a sync site */
	vote_globals.syncHost = otherHost;
	vote_globals.syncTime = now;
    } else if (vote_globals.syncTime + BIGTIME < now) {
	if (vote_globals.syncHost) {
	    ubik_dprint
		("Ubik: Lost contact with sync-site %s (NOT in quorum)\n",
		 afs_inet_ntoa_r(vote_globals.syncHost, hoststr));
	}
	vote_globals.syncHost = 0;
    }

    /* decide how to vote */
    vote = 0;			/* start off voting no */

    /* if we this guy isn't a sync site, we don't really have to vote for him.
     * We get to apply some heuristics to try to avoid weird oscillation sates
     * in the voting procedure. */
    if (astate == 0) {
	/* in here only if this guy doesn't claim to be a sync site */

	/* lowestHost is also trying for our votes, then just say no. */
	if (ntohl(vote_globals.lowestHost) != ntohl(otherHost)) {
	    goto done_zero;
	}

	/* someone else *is* a sync site, just say no */
	if (vote_globals.syncHost && vote_globals.syncHost != otherHost)
	    goto done_zero;
    } else if (vote_globals.lastYesHost == 0xffffffff && otherHost == ubik_host[0]) {
	/* fast startup if this is the only non-clone */
	int i = 0;
	for (ts = ubik_servers; ts; ts = ts->next) {
	    if (ts->addr[0] == otherHost)
		continue;
	    if (!ts->isClone)
		i++;
	}
	if (!i)
	    vote_globals.lastYesHost = otherHost;
    }


    if (isClone)
	goto done_zero;		/* clone never can become sync site */

    /* Don't promise sync site support to more than one host every BIGTIME
     * seconds.  This is the heart of our invariants in this system. */
    if (vote_globals.ubik_lastYesTime + BIGTIME < now || otherHost == vote_globals.lastYesHost) {
	if ((vote_globals.ubik_lastYesTime + BIGTIME < now) || (otherHost != vote_globals.lastYesHost)
	    || (vote_globals.lastYesState != astate)) {
	    /* A new vote or a change in the vote or changed quorum */
	    ubik_dprint("Ubik: vote 'yes' for %s %s\n",
			afs_inet_ntoa_r(otherHost, hoststr),
			(astate ? "(in quorum)" : "(NOT in quorum)"));
	}

	vote = now;		/* vote yes */
	vote_globals.ubik_lastYesTime = now;	/* remember when we voted yes */
	vote_globals.lastYesClaim = astart;	/* remember for computing when sync site expires */
	vote_globals.lastYesHost = otherHost;	/* and who for */
	vote_globals.lastYesState = astate;	/* remember if site is a sync site */
	vote_globals.ubik_dbVersion = *avers;	/* resync value */
	vote_globals.ubik_dbTid = *atid;	/* transaction id, if any, of active trans */
	UBIK_VOTE_UNLOCK;
	DBHOLD(ubik_dbase);
	urecovery_CheckTid(atid, 0);	/* check if current write trans needs aborted */
	DBRELE(ubik_dbase);
    } else {
	UBIK_VOTE_UNLOCK;
    }
    return vote;
done_zero:
    UBIK_VOTE_UNLOCK;
    return 0;
}
Exemplo n.º 11
0
int
SRXAFSCB_InitCallBackState(struct rx_call *a_call)
{
    int i;
    struct vcache *tvc;
    struct rx_connection *tconn;
    struct rx_peer *peer;
    struct server *ts;
    int code = 0;
    XSTATS_DECLS;

    RX_AFS_GLOCK();

    XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_INITCALLBACKSTATE);
    AFS_STATCNT(SRXAFSCB_InitCallBackState);

    /*
     * Find the address of the host making this call
     */
    if ((tconn = rx_ConnectionOf(a_call)) && (peer = rx_PeerOf(tconn))) {

	afs_allCBs++;
	afs_oddCBs++;		/*Including any missed via create race */
	afs_evenCBs++;		/*Including any missed via create race */

	ts = afs_FindServer(rx_HostOf(peer), rx_PortOf(peer), (afsUUID *) 0,
			    0);
	if (ts) {
	    for (i = 0; i < VCSIZE; i++)
		for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
		    if (tvc->callback == ts) {
			ObtainWriteLock(&afs_xcbhash, 451);
			afs_DequeueCallback(tvc);
			tvc->callback = NULL;
			tvc->f.states &= ~(CStatd | CUnique | CBulkFetching);
			ReleaseWriteLock(&afs_xcbhash);
		    }
		}

	    /* capabilities need be requested again */
	    ObtainWriteLock(&afs_xserver, 877);
	    ts->flags &= ~SCAPS_KNOWN;
	    ReleaseWriteLock(&afs_xserver);
	}



	/* find any volumes residing on this server and flush their state */
	{
	    struct volume *tv;
	    int j;

	    for (i = 0; i < NVOLS; i++)
		for (tv = afs_volumes[i]; tv; tv = tv->next) {
		    for (j = 0; j < AFS_MAXHOSTS; j++)
			if (tv->serverHost[j] == ts)
			    afs_ResetVolumeInfo(tv);
		}
	}
	osi_dnlc_purge();	/* may be a little bit extreme */
    }

    XSTATS_END_TIME;

    RX_AFS_GUNLOCK();

    return (0);

}				/*SRXAFSCB_InitCallBackState */