Esempio n. 1
0
afs_int32
SDISK_Abort(struct rx_call *rxcall, struct ubik_tid *atid)
{
    afs_int32 code;

    if ((code = ubik_CheckAuth(rxcall))) {
	return code;
    }
    DBHOLD(ubik_dbase);
    if (!ubik_currentTrans) {
	code = USYNC;
	goto done;
    }
    /* sanity check to make sure only write trans appear here  */
    if (ubik_currentTrans->type != UBIK_WRITETRANS) {
	code = UBADTYPE;
	goto done;
    }

    urecovery_CheckTid(atid, 0);
    if (!ubik_currentTrans) {
	code = USYNC;
	goto done;
    }

    code = udisk_abort(ubik_currentTrans);
    /* If the thread is not waiting for lock - ok to end it */
    if (ubik_currentTrans->locktype != LOCKWAIT) {
	udisk_end(ubik_currentTrans);
    }
    ubik_currentTrans = (struct ubik_trans *)0;
done:
    DBRELE(ubik_dbase);
    return code;
}
Esempio n. 2
0
/* apos and alen are not used */
afs_int32
SDISK_Lock(struct rx_call *rxcall, struct ubik_tid *atid, afs_int32 index,
	   afs_int32 afile, afs_int32 apos, afs_int32 alen, afs_int32 atype)
{
    afs_int32 code;
    struct ubik_dbase *dbase;
    struct ubik_trans *ubik_thisTrans;

    if ((code = ubik_CheckAuth(rxcall))) {
	return code;
    }
    if (!ubik_currentTrans[index]) {
	return USYNC;
    }
    if (!ubik_dbase[index]) {
	return ENOENT;
    }

    /* sanity check to make sure only write trans appear here */
    if (ubik_currentTrans[index]->type != UBIK_WRITETRANS) {
	return UBADTYPE;
    }
    if (alen != 1) {
	return UBADLOCK;
    }
    dbase = ubik_currentTrans[index]->dbase;
    DBHOLD(dbase);
    urecovery_CheckTid(atid, index);
    if (!ubik_currentTrans[index]) {
	DBRELE(dbase);
	return USYNC;
    }

    ubik_thisTrans = ubik_currentTrans[index];
    code = ulock_getLock(ubik_currentTrans[index], atype, 1);

    /* While waiting, the transaction may have been ended/
     * aborted from under us (urecovery_CheckTid). In that
     * case, end the transaction here.
     */
    if (!code && (ubik_currentTrans[index] != ubik_thisTrans)) {
	udisk_end(ubik_thisTrans);
	code = USYNC;
    }

    DBRELE(dbase);
    return code;
}
Esempio n. 3
0
/*!
 * \brief this routine aborts the current remote transaction, if any, if the tid is wrong
 */
int
urecovery_CheckTid(struct ubik_tid *atid, int abortalways)
{
    if (ubik_currentTrans) {
	/* there is remote write trans, see if we match, see if this
	 * is a new transaction */
	if (atid->epoch != ubik_currentTrans->tid.epoch
	    || atid->counter > ubik_currentTrans->tid.counter || abortalways) {
	    /* don't match, abort it */
	    /* If the thread is not waiting for lock - ok to end it */
	    if (ubik_currentTrans->locktype != LOCKWAIT) {
		udisk_end(ubik_currentTrans);
	    }
	    ubik_currentTrans = (struct ubik_trans *)0;
	}
    }
    return 0;
}
Esempio n. 4
0
afs_int32
SDISK_Abort(struct rx_call *rxcall, struct ubik_tid *atid, afs_int32 index)
{
    afs_int32 code;
    struct ubik_dbase *dbase;

    if ((code = ubik_CheckAuth(rxcall))) {
	return code;
    }

    if (!ubik_currentTrans[index]) {
	return USYNC;
    }
    /* sanity check to make sure only write trans appear here  */
    if (ubik_currentTrans[index]->type != UBIK_WRITETRANS) {
	return UBADTYPE;
    }

    if (!ubik_dbase[index]) {
	return ENOENT;
    }

    dbase = ubik_currentTrans[index]->dbase;
    DBHOLD(dbase);
    urecovery_CheckTid(atid, index);
    if (!ubik_currentTrans[index]) {
	DBRELE(dbase);
	return USYNC;
    }

    code = udisk_abort(ubik_currentTrans[index]);
    /* If the thread is not waiting for lock - ok to end it */
#if !defined(UBIK_PAUSE)
    if (ubik_currentTrans[index]->locktype != LOCKWAIT) {
#endif /* UBIK_PAUSE */
	udisk_end(ubik_currentTrans[index]);
#if !defined(UBIK_PAUSE)
    }
#endif /* UBIK_PAUSE */
    ubik_currentTrans[index] = (struct ubik_trans *)0;
    DBRELE(dbase);
    return code;
}
Esempio n. 5
0
/*!
 * \brief this routine aborts the current remote transaction, if any, if the tid is wrong
 */
int
urecovery_CheckTid(register struct ubik_tid *atid)
{
    if (ubik_currentTrans) {
	/* there is remote write trans, see if we match, see if this
	 * is a new transaction */
	if (atid->epoch != ubik_currentTrans->tid.epoch
	    || atid->counter > ubik_currentTrans->tid.counter) {
	    /* don't match, abort it */
	    /* If the thread is not waiting for lock - ok to end it */
#if !defined(UBIK_PAUSE)
	    if (ubik_currentTrans->locktype != LOCKWAIT) {
#endif /* UBIK_PAUSE */
		udisk_end(ubik_currentTrans);
#if !defined(UBIK_PAUSE)
	    }
#endif /* UBIK_PAUSE */
	    ubik_currentTrans = (struct ubik_trans *)0;
	}
    }
    return 0;
}
Esempio n. 6
0
/* the rest of these guys handle remote execution of write
 * transactions: this is the code executed on the other servers when a
 * sync site is executing a write transaction.
 */
afs_int32
SDISK_Begin(struct rx_call *rxcall, struct ubik_tid *atid, afs_int32 index)
{
    afs_int32 code;

    if ((code = ubik_CheckAuth(rxcall))) {
	return code;
    }
    if (!ubik_dbase[index]) {
	return ENOENT;
    }
    DBHOLD(ubik_dbase[index]);
    if (urecovery_AllBetter(ubik_dbase[index], 0) == 0) {
	code = UNOQUORUM;
	goto out;
    }
    urecovery_CheckTid(atid, index);
    if (ubik_currentTrans[index]) {
	/* If the thread is not waiting for lock - ok to end it */
#if !defined(UBIK_PAUSE)
	if (ubik_currentTrans[index]->locktype != LOCKWAIT) {
#endif /* UBIK_PAUSE */
	    udisk_end(ubik_currentTrans[index]);
#if !defined(UBIK_PAUSE)
	}
#endif /* UBIK_PAUSE */
	ubik_currentTrans[index] = (struct ubik_trans *)0;
    }
    code = udisk_begin(ubik_dbase[index], UBIK_WRITETRANS, &ubik_currentTrans[index]);
    if (!code && ubik_currentTrans[index]) {
	/* label this trans with the right trans id */
	ubik_currentTrans[index]->tid.epoch = atid->epoch;
	ubik_currentTrans[index]->tid.counter = atid->counter;
    }
out:
    DBRELE(ubik_dbase[index]);
    return code;
}
Esempio n. 7
0
/*!
 * \brief Set a transaction lock.
 * \param atype is #LOCKREAD or #LOCKWRITE.
 * \param await is TRUE if you want to wait for the lock instead of returning
 * #EWOULDBLOCK.
 *
 * \note The #DBHOLD lock must be held.
 */
extern int
ulock_getLock(struct ubik_trans *atrans, int atype, int await)
{
    struct ubik_dbase *dbase = atrans->dbase;

    /* On first pass, initialize the lock */
    if (rwlockinit) {
	Lock_Init(&rwlock);
	rwlockinit = 0;
    }

    if ((atype != LOCKREAD) && (atype != LOCKWRITE))
	return EINVAL;

    if (atrans->flags & TRDONE)
	return UDONE;

    if (atype != LOCKREAD && (atrans->flags & TRREADWRITE)) {
	return EINVAL;
    }

    if (atrans->locktype != 0) {
	ubik_print("Ubik: Internal Error: attempted to take lock twice\n");
	abort();
    }

/*
 *ubik_print("Ubik: DEBUG: Thread 0x%x request %s lock\n", lwp_cpptr,
 *	     ((atype == LOCKREAD) ? "READ" : "WRITE"));
 */

    /* Check if the lock would would block */
    if (!await && !(atrans->flags & TRREADWRITE)) {
	if (atype == LOCKREAD) {
	    if (WouldReadBlock(&rwlock))
		return EAGAIN;
	} else {
	    if (WouldWriteBlock(&rwlock))
		return EAGAIN;
	}
    }

    /* Create new lock record and add to spec'd transaction:
     * #if defined(UBIK_PAUSE)
     * * locktype.  Before doing that, set TRSETLOCK,
     * * to tell udisk_end that another thread (us) is waiting.
     * #else
     * * locktype. This field also tells us if the thread is
     * * waiting for a lock: It will be equal to LOCKWAIT.
     * #endif
     */
#if defined(UBIK_PAUSE)
    if (atrans->flags & TRSETLOCK) {
	printf("Ubik: Internal Error: TRSETLOCK already set?\n");
	return EBUSY;
    }
    atrans->flags |= TRSETLOCK;
#else
    atrans->locktype = LOCKWAIT;
#endif /* UBIK_PAUSE */
    DBRELE(dbase);
    if (atrans->flags & TRREADWRITE) {
	/* noop; don't actually lock anything for TRREADWRITE */
    } else if (atype == LOCKREAD) {
	ObtainReadLock(&rwlock);
    } else {
	ObtainWriteLock(&rwlock);
    }
    DBHOLD(dbase);
    atrans->locktype = atype;
#if defined(UBIK_PAUSE)
    atrans->flags &= ~TRSETLOCK;
#if 0
    /* We don't do this here, because this can only happen in SDISK_Lock,
     *  and there's already code there to catch this condition.
     */
    if (atrans->flags & TRSTALE) {
	udisk_end(atrans);
	return UINTERNAL;
    }
#endif
#endif /* UBIK_PAUSE */

/*
 *ubik_print("Ubik: DEBUG: Thread 0x%x took %s lock\n", lwp_cpptr,
 *	     ((atype == LOCKREAD) ? "READ" : "WRITE"));
 */
    return 0;
}