예제 #1
0
파일: mutex.c 프로젝트: hef/samba
int tdb_mutex_munmap(struct tdb_context *tdb)
{
	size_t len;

	len = tdb_mutex_size(tdb);
	if (len == 0) {
		return 0;
	}

	return munmap(tdb->mutexes, len);
}
예제 #2
0
파일: mutex.c 프로젝트: Alexander--/samba
int tdb_mutex_munmap(struct tdb_context *tdb)
{
	size_t len;
	int ret;

	len = tdb_mutex_size(tdb);
	if (len == 0) {
		return 0;
	}

	ret = munmap(tdb->mutexes, len);
	if (ret == -1) {
		return -1;
	}
	tdb->mutexes = NULL;

	return 0;
}
예제 #3
0
파일: mutex.c 프로젝트: hef/samba
int tdb_mutex_mmap(struct tdb_context *tdb)
{
	size_t len;
	void *ptr;

	len = tdb_mutex_size(tdb);
	if (len == 0) {
		return 0;
	}

	ptr = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FILE,
		   tdb->fd, 0);
	if (ptr == MAP_FAILED) {
		return -1;
	}
	tdb->mutexes = (struct tdb_mutexes *)ptr;

	return 0;
}
예제 #4
0
파일: open.c 프로젝트: hef/samba
/* initialise a new database with a specified hash size */
static int tdb_new_database(struct tdb_context *tdb, struct tdb_header *header,
			    int hash_size)
{
	struct tdb_header *newdb;
	size_t size;
	int ret = -1;

	/* We make it up in memory, then write it out if not internal */
	size = sizeof(struct tdb_header) + (hash_size+1)*sizeof(tdb_off_t);
	if (!(newdb = (struct tdb_header *)calloc(size, 1))) {
		tdb->ecode = TDB_ERR_OOM;
		return -1;
	}

	/* Fill in the header */
	newdb->version = TDB_VERSION;
	newdb->hash_size = hash_size;

	tdb_header_hash(tdb, &newdb->magic1_hash, &newdb->magic2_hash);

	/* Make sure older tdbs (which don't check the magic hash fields)
	 * will refuse to open this TDB. */
	if (tdb->flags & TDB_INCOMPATIBLE_HASH)
		newdb->rwlocks = TDB_HASH_RWLOCK_MAGIC;

	/*
	 * We create a tdb with TDB_FEATURE_FLAG_MUTEX support,
	 * the flag combination and runtime feature checks
	 * are done by the caller already.
	 */
	if (tdb->flags & TDB_MUTEX_LOCKING) {
		newdb->feature_flags |= TDB_FEATURE_FLAG_MUTEX;
	}

	/*
	 * If we have any features we add the FEATURE_FLAG_MAGIC, overwriting the
	 * TDB_HASH_RWLOCK_MAGIC above.
	 */
	if (newdb->feature_flags != 0) {
		newdb->rwlocks = TDB_FEATURE_FLAG_MAGIC;
	}

	/*
	 * It's required for some following code pathes
	 * to have the fields on 'tdb' up-to-date.
	 *
	 * E.g. tdb_mutex_size() requires it
	 */
	tdb->feature_flags = newdb->feature_flags;
	tdb->hash_size = newdb->hash_size;

	if (tdb->flags & TDB_INTERNAL) {
		tdb->map_size = size;
		tdb->map_ptr = (char *)newdb;
		memcpy(header, newdb, sizeof(*header));
		/* Convert the `ondisk' version if asked. */
		CONVERT(*newdb);
		return 0;
	}
	if (lseek(tdb->fd, 0, SEEK_SET) == -1)
		goto fail;

	if (ftruncate(tdb->fd, 0) == -1)
		goto fail;

	if (newdb->feature_flags & TDB_FEATURE_FLAG_MUTEX) {
		newdb->mutex_size = tdb_mutex_size(tdb);
		tdb->hdr_ofs = newdb->mutex_size;
	}

	/* This creates an endian-converted header, as if read from disk */
	CONVERT(*newdb);
	memcpy(header, newdb, sizeof(*header));
	/* Don't endian-convert the magic food! */
	memcpy(newdb->magic_food, TDB_MAGIC_FOOD, strlen(TDB_MAGIC_FOOD)+1);

	if (!tdb_write_all(tdb->fd, newdb, size))
		goto fail;

	if (newdb->feature_flags & TDB_FEATURE_FLAG_MUTEX) {

		/*
		 * Now we init the mutex area
		 * followed by a second header.
		 */

		ret = ftruncate(
			tdb->fd,
			newdb->mutex_size + sizeof(struct tdb_header));
		if (ret == -1) {
			goto fail;
		}
		ret = tdb_mutex_init(tdb);
		if (ret == -1) {
			goto fail;
		}

		/*
		 * Write a second header behind the mutexes. That's the area
		 * that will be mmapp'ed.
		 */
		ret = lseek(tdb->fd, newdb->mutex_size, SEEK_SET);
		if (ret == -1) {
			goto fail;
		}
		if (!tdb_write_all(tdb->fd, newdb, size)) {
			goto fail;
		}
	}

	ret = 0;
  fail:
	SAFE_FREE(newdb);
	return ret;
}
예제 #5
0
파일: open.c 프로젝트: hef/samba
static bool tdb_mutex_open_ok(struct tdb_context *tdb,
			      const struct tdb_header *header)
{
	int locked;

	locked = tdb_nest_lock(tdb, ACTIVE_LOCK, F_WRLCK,
			       TDB_LOCK_NOWAIT|TDB_LOCK_PROBE);

	if ((locked == -1) && (tdb->ecode == TDB_ERR_LOCK)) {
		/*
		 * CLEAR_IF_FIRST still active. The tdb was created on this
		 * host, so we can assume the mutex implementation is
		 * compatible. Important for tools like tdbdump on a still
		 * open locking.tdb.
		 */
		goto check_local_settings;
	}

	/*
	 * We got the CLEAR_IF_FIRST lock. That means the database was
	 * potentially copied from somewhere else. The mutex implementation
	 * might be incompatible.
	 */

	if (tdb_nest_unlock(tdb, ACTIVE_LOCK, F_WRLCK, false) == -1) {
		/*
		 * Should not happen
		 */
		TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_mutex_open_ok: "
			 "failed to release ACTIVE_LOCK on %s: %s\n",
			 tdb->name, strerror(errno)));
		return false;
	}

	if (tdb->flags & TDB_NOLOCK) {
		/*
		 * We don't look at locks, so it does not matter to have a
		 * compatible mutex implementation. Allow the open.
		 */
		return true;
	}

check_local_settings:

	if (!(tdb->flags & TDB_MUTEX_LOCKING)) {
		TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_mutex_open_ok[%s]: "
			 "Can use mutexes only with "
			 "MUTEX_LOCKING or NOLOCK\n",
			 tdb->name));
		return false;
	}

	if (tdb_mutex_size(tdb) != header->mutex_size) {
		TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_mutex_open_ok[%s]: "
			 "Mutex size changed from %u to %u\n.",
			 tdb->name,
			 (unsigned int)header->mutex_size,
			 (unsigned int)tdb_mutex_size(tdb)));
		return false;
	}

	return true;
}