Пример #1
0
Файл: lock.c Проект: hef/samba
/* The transaction code uses this to remove all locks. */
void tdb_release_transaction_locks(struct tdb_context *tdb)
{
	unsigned int i, active = 0;

	if (tdb->allrecord_lock.count != 0) {
		tdb_allrecord_unlock(tdb, tdb->allrecord_lock.ltype, false);
		tdb->allrecord_lock.count = 0;
	}

	for (i=0;i<tdb->num_lockrecs;i++) {
		struct tdb_lock_type *lck = &tdb->lockrecs[i];

		/* Don't release the active lock!  Copy it to first entry. */
		if (lck->off == ACTIVE_LOCK) {
			tdb->lockrecs[active++] = *lck;
		} else {
			tdb_brunlock(tdb, lck->ltype, lck->off, 1);
		}
	}
	tdb->num_lockrecs = active;
}
Пример #2
0
enum TDB_ERROR tdb_wipe_all(struct tdb_context *tdb)
{
	enum TDB_ERROR ecode;
	int64_t count;

	if (tdb->flags & TDB_VERSION1) {
		if (tdb1_wipe_all(tdb) == -1)
			return tdb->last_error;
		return TDB_SUCCESS;
	}

	ecode = tdb_allrecord_lock(tdb, F_WRLCK, TDB_LOCK_WAIT, false);
	if (ecode != TDB_SUCCESS)
		return tdb->last_error = ecode;

	/* FIXME: Be smarter. */
	count = tdb_traverse(tdb, wipe_one, &ecode);
	if (count < 0)
		ecode = TDB_OFF_TO_ERR(count);
	tdb_allrecord_unlock(tdb, F_WRLCK);
	return tdb->last_error = ecode;
}
Пример #3
0
Файл: lock.c Проект: hef/samba
/* unlock entire database with read lock */
_PUBLIC_ int tdb_unlockall_read(struct tdb_context *tdb)
{
	tdb_trace(tdb, "tdb_unlockall_read");
	return tdb_allrecord_unlock(tdb, F_RDLCK, false);
}
Пример #4
0
Файл: lock.c Проект: hef/samba
/* unlock entire database with write lock - unmark only */
_PUBLIC_ int tdb_lockall_unmark(struct tdb_context *tdb)
{
	tdb_trace(tdb, "tdb_lockall_unmark");
	return tdb_allrecord_unlock(tdb, F_WRLCK, true);
}
Пример #5
0
Файл: lock.c Проект: hef/samba
/* lock/unlock entire database.  It can only be upgradable if you have some
 * other way of guaranteeing exclusivity (ie. transaction write lock).
 * We do the locking gradually to avoid being starved by smaller locks. */
int tdb_allrecord_lock(struct tdb_context *tdb, int ltype,
		       enum tdb_lock_flags flags, bool upgradable)
{
	int ret;

	switch (tdb_allrecord_check(tdb, ltype, flags, upgradable)) {
	case -1:
		return -1;
	case 0:
		return 0;
	}

	/* We cover two kinds of locks:
	 * 1) Normal chain locks.  Taken for almost all operations.
	 * 2) Individual records locks.  Taken after normal or free
	 *    chain locks.
	 *
	 * It is (1) which cause the starvation problem, so we're only
	 * gradual for that. */

	if (tdb_have_mutexes(tdb)) {
		ret = tdb_mutex_allrecord_lock(tdb, ltype, flags);
	} else {
		ret = tdb_chainlock_gradual(tdb, ltype, flags, FREELIST_TOP,
					    tdb->hash_size * 4);
	}

	if (ret == -1) {
		return -1;
	}

	/* Grab individual record locks. */
	if (tdb_brlock(tdb, ltype, lock_offset(tdb->hash_size), 0,
		       flags) == -1) {
		if (tdb_have_mutexes(tdb)) {
			tdb_mutex_allrecord_unlock(tdb);
		} else {
			tdb_brunlock(tdb, ltype, FREELIST_TOP,
				     tdb->hash_size * 4);
		}
		return -1;
	}

	tdb->allrecord_lock.count = 1;
	/* If it's upgradable, it's actually exclusive so we can treat
	 * it as a write lock. */
	tdb->allrecord_lock.ltype = upgradable ? F_WRLCK : ltype;
	tdb->allrecord_lock.off = upgradable;

	if (tdb_needs_recovery(tdb)) {
		bool mark = flags & TDB_LOCK_MARK_ONLY;
		tdb_allrecord_unlock(tdb, ltype, mark);
		if (mark) {
			tdb->ecode = TDB_ERR_LOCK;
			TDB_LOG((tdb, TDB_DEBUG_ERROR,
				 "tdb_lockall_mark cannot do recovery\n"));
			return -1;
		}
		if (tdb_lock_and_recover(tdb) == -1) {
			return -1;
		}
		return tdb_allrecord_lock(tdb, ltype, flags, upgradable);
	}

	return 0;
}