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); }
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; }
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; }
/* 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; }
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; }