summaryrefslogtreecommitdiff
path: root/lib/tdb
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2018-10-22 08:57:00 +0200
committerJeremy Allison <jra@samba.org>2018-11-06 18:57:26 +0100
commit72ec893d0aaa518a2cf22aa68b16c3907a17dfc8 (patch)
tree2af45b44336cfeb3e7615646c638ade95ac8c6d9 /lib/tdb
parente814fb6bcba8687dafb7d0d1654df8225b2e6229 (diff)
downloadsamba-72ec893d0aaa518a2cf22aa68b16c3907a17dfc8.tar.gz
tdb: Allow !CLEAR_IF_FIRST & MUTEX_LOCKING
This is a prerequisite to allow gencache to run on a non-transactioned database with mutexes. Signed-off-by: Volker Lendecke <vl@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org>
Diffstat (limited to 'lib/tdb')
-rw-r--r--lib/tdb/common/open.c91
-rw-r--r--lib/tdb/test/run-mutex-openflags2.c7
2 files changed, 42 insertions, 56 deletions
diff --git a/lib/tdb/common/open.c b/lib/tdb/common/open.c
index 899a2fcaffb..be5f8075557 100644
--- a/lib/tdb/common/open.c
+++ b/lib/tdb/common/open.c
@@ -230,8 +230,6 @@ static bool check_header_hash(struct tdb_context *tdb,
static bool tdb_mutex_open_ok(struct tdb_context *tdb,
const struct tdb_header *header)
{
- int locked;
-
if (tdb->flags & TDB_NOLOCK) {
/*
* We don't look at locks, so it does not matter to have a
@@ -240,37 +238,6 @@ static bool tdb_mutex_open_ok(struct tdb_context *tdb,
return true;
}
- 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;
- }
-
-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 "
@@ -416,14 +383,6 @@ _PUBLIC_ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int td
* the runtime check for existing tdb's comes later.
*/
- if (!(tdb->flags & TDB_CLEAR_IF_FIRST)) {
- TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: "
- "invalid flags for %s - TDB_MUTEX_LOCKING "
- "requires TDB_CLEAR_IF_FIRST\n", name));
- errno = EINVAL;
- goto fail;
- }
-
if (tdb->flags & TDB_INTERNAL) {
TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: "
"invalid flags for %s - TDB_MUTEX_LOCKING and "
@@ -632,6 +591,30 @@ _PUBLIC_ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int td
* mutex locking.
*/
tdb->hdr_ofs = header.mutex_size;
+
+ if ((!(tdb_flags & TDB_CLEAR_IF_FIRST)) && (!tdb->read_only)) {
+ /*
+ * Open an existing mutexed tdb, but without
+ * CLEAR_IF_FIRST. We need to initialize the
+ * mutex array and keep the CLEAR_IF_FIRST
+ * lock locked.
+ */
+ ret = tdb_nest_lock(tdb, ACTIVE_LOCK, F_WRLCK,
+ TDB_LOCK_NOWAIT|TDB_LOCK_PROBE);
+ locked = (ret == 0);
+
+ if (locked) {
+ ret = tdb_mutex_init(tdb);
+ if (ret == -1) {
+ TDB_LOG((tdb,
+ TDB_DEBUG_FATAL,
+ "tdb_open_ex: tdb_mutex_init "
+ "failed for ""%s: %s\n",
+ name, strerror(errno)));
+ goto fail;
+ }
+ }
+ }
}
if ((header.magic1_hash == 0) && (header.magic2_hash == 0)) {
@@ -708,15 +691,19 @@ _PUBLIC_ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int td
goto fail;
}
+
}
- /* We always need to do this if the CLEAR_IF_FIRST flag is set, even if
- we didn't get the initial exclusive lock as we need to let all other
- users know we're using it. */
+ if (locked || (tdb_flags & TDB_CLEAR_IF_FIRST)) {
+ /*
+ * We always need to do this if the CLEAR_IF_FIRST
+ * flag is set, even if we didn't get the initial
+ * exclusive lock as we need to let all other users
+ * know we're using it.
+ */
- if (tdb_flags & TDB_CLEAR_IF_FIRST) {
- /* leave this lock in place to indicate it's in use */
- if (tdb_nest_lock(tdb, ACTIVE_LOCK, F_RDLCK, TDB_LOCK_WAIT) == -1) {
+ ret = tdb_nest_lock(tdb, ACTIVE_LOCK, F_RDLCK, TDB_LOCK_WAIT);
+ if (ret == -1) {
goto fail;
}
}
@@ -932,7 +919,10 @@ fail:
seek pointer from our parent and to re-establish locks */
_PUBLIC_ int tdb_reopen(struct tdb_context *tdb)
{
- return tdb_reopen_internal(tdb, tdb->flags & TDB_CLEAR_IF_FIRST);
+ bool active_lock;
+ active_lock = (tdb->flags & (TDB_CLEAR_IF_FIRST|TDB_MUTEX_LOCKING));
+
+ return tdb_reopen_internal(tdb, active_lock);
}
/* reopen all tdb's */
@@ -941,7 +931,10 @@ _PUBLIC_ int tdb_reopen_all(int parent_longlived)
struct tdb_context *tdb;
for (tdb=tdbs; tdb; tdb = tdb->next) {
- bool active_lock = (tdb->flags & TDB_CLEAR_IF_FIRST);
+ bool active_lock;
+
+ active_lock =
+ (tdb->flags & (TDB_CLEAR_IF_FIRST|TDB_MUTEX_LOCKING));
/*
* If the parent is longlived (ie. a
diff --git a/lib/tdb/test/run-mutex-openflags2.c b/lib/tdb/test/run-mutex-openflags2.c
index 6522ae42faa..89603e638c2 100644
--- a/lib/tdb/test/run-mutex-openflags2.c
+++ b/lib/tdb/test/run-mutex-openflags2.c
@@ -112,13 +112,6 @@ int main(int argc, char *argv[])
data.dsize = strlen("world");
data.dptr = discard_const_p(uint8_t, "world");
- tdb = tdb_open_ex("mutex-openflags2.tdb", 0,
- TDB_INCOMPATIBLE_HASH|
- TDB_MUTEX_LOCKING,
- O_RDWR|O_CREAT, 0755, &nolog_ctx, NULL);
- ok((tdb == NULL) && (errno == EINVAL), "TDB_MUTEX_LOCKING without "
- "TDB_CLEAR_IF_FIRST should fail with EINVAL - %d", errno);
-
if (!runtime_support) {
tdb = tdb_open_ex("mutex-openflags2.tdb", 0,
TDB_CLEAR_IF_FIRST|