summaryrefslogtreecommitdiff
path: root/lib/tdb/common
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2010-09-24 15:45:11 +0930
committerRusty Russell <rusty@rustcorp.com.au>2010-09-27 10:48:28 +0930
commit2dcf76c9247ff02a1779000dbbecdc418473ca41 (patch)
treeabb39b50bd6c30c5a6dc42aa0414e68b16237dd8 /lib/tdb/common
parentccac258d14dda7d8a994a7b80474ce6d85478a6d (diff)
downloadsamba-2dcf76c9247ff02a1779000dbbecdc418473ca41.tar.gz
samba-2dcf76c9247ff02a1779000dbbecdc418473ca41.tar.bz2
samba-2dcf76c9247ff02a1779000dbbecdc418473ca41.zip
tdb: TDB_INCOMPATIBLE_HASH, to allow safe changing of default hash.
This flag to tdb_open/tdb_open_ex effects creation of a new database: 1) Uses the Jenkins lookup3 hash instead of the old gdbm hash if none is specified, 2) Places a non-zero field in header->rwlocks, so older versions of TDB will refuse to open it. This means that the caller (ie Samba) can set this flag to safely change the hash function. Versions of TDB from this one on will either use the correct hash or refuse to open (if a different hash is specified). Older TDB versions will see the nonzero rwlocks field and refuse to open it under any conditions. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'lib/tdb/common')
-rw-r--r--lib/tdb/common/check.c2
-rw-r--r--lib/tdb/common/open.c21
-rw-r--r--lib/tdb/common/tdb_private.h1
3 files changed, 20 insertions, 4 deletions
diff --git a/lib/tdb/common/check.c b/lib/tdb/common/check.c
index b1b98d4f1e..58c9c26540 100644
--- a/lib/tdb/common/check.c
+++ b/lib/tdb/common/check.c
@@ -39,7 +39,7 @@ static bool tdb_check_header(struct tdb_context *tdb, tdb_off_t *recovery)
if (hdr.version != TDB_VERSION)
goto corrupt;
- if (hdr.rwlocks != 0)
+ if (hdr.rwlocks != 0 && hdr.rwlocks != TDB_HASH_RWLOCK_MAGIC)
goto corrupt;
tdb_header_hash(tdb, &h1, &h2);
diff --git a/lib/tdb/common/open.c b/lib/tdb/common/open.c
index 9a82bc9bad..66539c3f6c 100644
--- a/lib/tdb/common/open.c
+++ b/lib/tdb/common/open.c
@@ -70,6 +70,11 @@ static int tdb_new_database(struct tdb_context *tdb, int 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;
+
if (tdb->flags & TDB_INTERNAL) {
tdb->map_size = size;
tdb->map_ptr = (char *)newdb;
@@ -150,7 +155,10 @@ static bool check_header_hash(struct tdb_context *tdb,
return false;
/* Otherwise, try the other inbuilt hash. */
- tdb->hash_fn = tdb_jenkins_hash;
+ if (tdb->hash_fn == tdb_old_hash)
+ tdb->hash_fn = tdb_jenkins_hash;
+ else
+ tdb->hash_fn = tdb_old_hash;
return check_header_hash(tdb, false, m1, m2);
}
@@ -193,7 +201,12 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
tdb->hash_fn = hash_fn;
hash_alg = "the user defined";
} else {
- tdb->hash_fn = tdb_old_hash;
+ /* This controls what we use when creating a tdb. */
+ if (tdb->flags & TDB_INCOMPATIBLE_HASH) {
+ tdb->hash_fn = tdb_jenkins_hash;
+ } else {
+ tdb->hash_fn = tdb_old_hash;
+ }
hash_alg = "either default";
}
@@ -312,13 +325,15 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
if (fstat(tdb->fd, &st) == -1)
goto fail;
- if (tdb->header.rwlocks != 0) {
+ if (tdb->header.rwlocks != 0 &&
+ tdb->header.rwlocks != TDB_HASH_RWLOCK_MAGIC) {
TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: spinlocks no longer supported\n"));
goto fail;
}
if ((tdb->header.magic1_hash == 0) && (tdb->header.magic2_hash == 0)) {
/* older TDB without magic hash references */
+ tdb->hash_fn = tdb_old_hash;
} else if (!check_header_hash(tdb, !hash_fn, &magic1, &magic2)) {
TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: "
"%s was not created with %s hash function we are using\n"
diff --git a/lib/tdb/common/tdb_private.h b/lib/tdb/common/tdb_private.h
index fe3603c104..0c621636fa 100644
--- a/lib/tdb/common/tdb_private.h
+++ b/lib/tdb/common/tdb_private.h
@@ -50,6 +50,7 @@ typedef uint32_t tdb_off_t;
#define TDB_DEAD_MAGIC (0xFEE1DEAD)
#define TDB_RECOVERY_MAGIC (0xf53bc0e7U)
#define TDB_RECOVERY_INVALID_MAGIC (0x0)
+#define TDB_HASH_RWLOCK_MAGIC (0xbad1a51U)
#define TDB_ALIGNMENT 4
#define DEFAULT_HASH_SIZE 131
#define FREELIST_TOP (sizeof(struct tdb_header))