From c29e64d97ee18e9d7946151052d1757084f861c6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 4 Feb 2014 23:35:53 +0100 Subject: [PATCH] tdb: introduce TDB_SUPPORTED_FEATURE_FLAGS This will allow to store a feature mask in the tdb header on disk, so that openers can check if they can handle the features other openers are using. Pair-Programmed-With: Volker Lendecke Pair-Programmed-With: Michael Adam Signed-off-by: Stefan Metzmacher Signed-off-by: Volker Lendecke Signed-off-by: Michael Adam Reviewed-by: Jeremy Allison --- lib/tdb/common/check.c | 4 +++- lib/tdb/common/open.c | 28 ++++++++++++++++++++++++++++ lib/tdb/common/summary.c | 2 ++ lib/tdb/common/tdb_private.h | 7 ++++++- 4 files changed, 39 insertions(+), 2 deletions(-) diff --git a/lib/tdb/common/check.c b/lib/tdb/common/check.c index 9f9d8708c1e..e632af51536 100644 --- a/lib/tdb/common/check.c +++ b/lib/tdb/common/check.c @@ -39,7 +39,9 @@ static bool tdb_check_header(struct tdb_context *tdb, tdb_off_t *recovery) if (hdr.version != TDB_VERSION) goto corrupt; - if (hdr.rwlocks != 0 && hdr.rwlocks != TDB_HASH_RWLOCK_MAGIC) + if (hdr.rwlocks != 0 && + hdr.rwlocks != TDB_FEATURE_FLAG_MAGIC && + 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 d5c04321111..17ab0b7c285 100644 --- a/lib/tdb/common/open.c +++ b/lib/tdb/common/open.c @@ -76,6 +76,20 @@ static int tdb_new_database(struct tdb_context *tdb, struct tdb_header *header, if (tdb->flags & TDB_INCOMPATIBLE_HASH) newdb->rwlocks = TDB_HASH_RWLOCK_MAGIC; + /* + * 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. + */ + tdb->feature_flags = newdb->feature_flags; + if (tdb->flags & TDB_INTERNAL) { tdb->map_size = size; tdb->map_ptr = (char *)newdb; @@ -390,6 +404,7 @@ _PUBLIC_ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int td goto fail; if (header.rwlocks != 0 && + header.rwlocks != TDB_FEATURE_FLAG_MAGIC && header.rwlocks != TDB_HASH_RWLOCK_MAGIC) { TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: spinlocks no longer supported\n")); errno = ENOSYS; @@ -397,6 +412,19 @@ _PUBLIC_ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int td } tdb->hash_size = header.hash_size; + if (header.rwlocks == TDB_FEATURE_FLAG_MAGIC) { + tdb->feature_flags = header.feature_flags; + } + + if (tdb->feature_flags & ~TDB_SUPPORTED_FEATURE_FLAGS) { + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: unsupported " + "features in tdb %s: 0x%08x (supported: 0x%08x)\n", + name, (unsigned)tdb->feature_flags, + (unsigned)TDB_SUPPORTED_FEATURE_FLAGS)); + errno = ENOSYS; + goto fail; + } + if ((header.magic1_hash == 0) && (header.magic2_hash == 0)) { /* older TDB without magic hash references */ tdb->hash_fn = tdb_old_hash; diff --git a/lib/tdb/common/summary.c b/lib/tdb/common/summary.c index 22404afa9b8..6f2e0a9e80a 100644 --- a/lib/tdb/common/summary.c +++ b/lib/tdb/common/summary.c @@ -21,6 +21,7 @@ "Size of file/data: %u/%zu\n" \ "Number of records: %zu\n" \ "Incompatible hash: %s\n" \ + "Active/supported feature flags: 0x%08x/0x%08x\n" \ "Smallest/average/largest keys: %zu/%zu/%zu\n" \ "Smallest/average/largest data: %zu/%zu/%zu\n" \ "Smallest/average/largest padding: %zu/%zu/%zu\n" \ @@ -169,6 +170,7 @@ _PUBLIC_ char *tdb_summary(struct tdb_context *tdb) tdb->map_size, keys.total+data.total, keys.num, (tdb->hash_fn == tdb_jenkins_hash)?"yes":"no", + (unsigned)tdb->feature_flags, TDB_SUPPORTED_FEATURE_FLAGS, keys.min, tally_mean(&keys), keys.max, data.min, tally_mean(&data), data.max, extra.min, tally_mean(&extra), extra.max, diff --git a/lib/tdb/common/tdb_private.h b/lib/tdb/common/tdb_private.h index a6721595782..aa9dd55ba47 100644 --- a/lib/tdb/common/tdb_private.h +++ b/lib/tdb/common/tdb_private.h @@ -53,6 +53,7 @@ typedef uint32_t tdb_off_t; #define TDB_RECOVERY_MAGIC (0xf53bc0e7U) #define TDB_RECOVERY_INVALID_MAGIC (0x0) #define TDB_HASH_RWLOCK_MAGIC (0xbad1a51U) +#define TDB_FEATURE_FLAG_MAGIC (0xbad1a52U) #define TDB_ALIGNMENT 4 #define DEFAULT_HASH_SIZE 131 #define FREELIST_TOP (sizeof(struct tdb_header)) @@ -68,6 +69,8 @@ typedef uint32_t tdb_off_t; #define TDB_PAD_BYTE 0x42 #define TDB_PAD_U32 0x42424242 +#define TDB_SUPPORTED_FEATURE_FLAGS 0 + /* NB assumes there is a local variable called "tdb" that is the * current context, also takes doubly-parenthesized print-style * argument. */ @@ -152,7 +155,8 @@ struct tdb_header { tdb_off_t sequence_number; /* used when TDB_SEQNUM is set */ uint32_t magic1_hash; /* hash of TDB_MAGIC_FOOD. */ uint32_t magic2_hash; /* hash of TDB_MAGIC. */ - tdb_off_t reserved[27]; + uint32_t feature_flags; + tdb_off_t reserved[26]; }; struct tdb_lock_type { @@ -200,6 +204,7 @@ struct tdb_context { int lockrecs_array_length; enum TDB_ERROR ecode; /* error code for last tdb error */ uint32_t hash_size; + uint32_t feature_flags; uint32_t flags; /* the flags passed to tdb_open */ struct tdb_traverse_lock travlocks; /* current traversal locks */ struct tdb_context *next; /* all tdbs to avoid multiple opens */ -- 2.11.4.GIT