From 2b5cb9bd6be4e61870ba7a400d1a9d91c5933371 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 17 Mar 2011 22:12:21 +1030 Subject: [PATCH 1/1] tdb2: feature support. As detailed in doc/design.lyx section 2.15 "Extending The Header Is Difficult"; we add features_used and features_offered fields to the header, so we can identify if we add new features, and then if someone opens it who doesn't understand that feature. --- ccan/tdb2/doc/design.lyx | 6 +++ ccan/tdb2/private.h | 8 +++- ccan/tdb2/tdb.c | 11 +++++ ccan/tdb2/test/failtest_helper.h | 2 +- ccan/tdb2/test/run-features.c | 71 ++++++++++++++++++++++++++++++++ 5 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 ccan/tdb2/test/run-features.c diff --git a/ccan/tdb2/doc/design.lyx b/ccan/tdb2/doc/design.lyx index 3487a7da..af94f6b9 100644 --- a/ccan/tdb2/doc/design.lyx +++ b/ccan/tdb2/doc/design.lyx @@ -1398,7 +1398,13 @@ Status \end_layout \begin_layout Standard + +\change_deleted 0 1300360753 Incomplete. +\change_inserted 0 1300360754 +Complete. +\change_unchanged + \end_layout \begin_layout Subsection diff --git a/ccan/tdb2/private.h b/ccan/tdb2/private.h index e15d1ad8..8e7df501 100644 --- a/ccan/tdb2/private.h +++ b/ccan/tdb2/private.h @@ -116,6 +116,9 @@ typedef int tdb_bool_err; #define TDB_OFF_HASH_EXTRA_BIT 57 #define TDB_OFF_UPPER_STEAL_SUBHASH_BIT 56 +/* Additional features we understand. Currently: none. */ +#define TDB_FEATURE_MASK ((uint64_t)0) + /* The bit number where we store the extra hash bits. */ /* Convenience mask to get actual offset. */ #define TDB_OFF_MASK \ @@ -240,7 +243,10 @@ struct tdb_header { tdb_off_t free_table; /* (First) free table. */ tdb_off_t recovery; /* Transaction recovery area. */ - tdb_off_t reserved[26]; + uint64_t features_used; /* Features all writers understand */ + uint64_t features_offered; /* Features offered */ + + tdb_off_t reserved[24]; /* Top level hash table. */ tdb_off_t hashtable[1ULL << TDB_TOPLEVEL_HASH_BITS]; diff --git a/ccan/tdb2/tdb.c b/ccan/tdb2/tdb.c index ce431208..4ffcebf5 100644 --- a/ccan/tdb2/tdb.c +++ b/ccan/tdb2/tdb.c @@ -112,6 +112,7 @@ static enum TDB_ERROR tdb_new_database(struct tdb_context *tdb, newdb.hdr.hash_seed, tdb->hash_priv); newdb.hdr.recovery = 0; + newdb.hdr.features_used = newdb.hdr.features_offered = TDB_FEATURE_MASK; memset(newdb.hdr.reserved, 0, sizeof(newdb.hdr.reserved)); /* Initial hashes are empty. */ memset(newdb.hdr.hashtable, 0, sizeof(newdb.hdr.hashtable)); @@ -361,6 +362,16 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags, goto fail; } + /* Clear any features we don't understand. */ + if ((open_flags & O_ACCMODE) != O_RDONLY) { + hdr.features_used &= TDB_FEATURE_MASK; + if (tdb_write_convert(tdb, offsetof(struct tdb_header, + features_used), + &hdr.features_used, + sizeof(hdr.features_used)) == -1) + goto fail; + } + tdb->device = st.st_dev; tdb->inode = st.st_ino; tdb_unlock_open(tdb); diff --git a/ccan/tdb2/test/failtest_helper.h b/ccan/tdb2/test/failtest_helper.h index 25bf21d0..418c1968 100644 --- a/ccan/tdb2/test/failtest_helper.h +++ b/ccan/tdb2/test/failtest_helper.h @@ -4,7 +4,7 @@ #include /* FIXME: Check these! */ -#define INITIAL_TDB_MALLOC "tdb.c", 190, FAILTEST_MALLOC +#define INITIAL_TDB_MALLOC "tdb.c", 191, FAILTEST_MALLOC #define URANDOM_OPEN "tdb.c", 49, FAILTEST_OPEN #define URANDOM_READ "tdb.c", 29, FAILTEST_READ diff --git a/ccan/tdb2/test/run-features.c b/ccan/tdb2/test/run-features.c new file mode 100644 index 00000000..a09ddb96 --- /dev/null +++ b/ccan/tdb2/test/run-features.c @@ -0,0 +1,71 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "logging.h" + +int main(int argc, char *argv[]) +{ + unsigned int i, j; + struct tdb_context *tdb; + int flags[] = { TDB_DEFAULT, TDB_NOMMAP, + TDB_CONVERT, TDB_NOMMAP|TDB_CONVERT }; + struct tdb_data key = { (unsigned char *)&j, sizeof(j) }; + struct tdb_data data = { (unsigned char *)&j, sizeof(j) }; + + plan_tests(sizeof(flags) / sizeof(flags[0]) * 8 + 1); + for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) { + uint64_t features; + tdb = tdb_open("run-features.tdb", flags[i], + O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr); + ok1(tdb); + if (!tdb) + continue; + + /* Put some stuff in there. */ + for (j = 0; j < 100; j++) { + if (tdb_store(tdb, key, data, TDB_REPLACE) != 0) + fail("Storing in tdb"); + } + + /* Mess with features fields in hdr. */ + features = (~TDB_FEATURE_MASK ^ 1); + ok1(tdb_write_convert(tdb, offsetof(struct tdb_header, + features_used), + &features, sizeof(features)) == 0); + ok1(tdb_write_convert(tdb, offsetof(struct tdb_header, + features_offered), + &features, sizeof(features)) == 0); + tdb_close(tdb); + + tdb = tdb_open("run-features.tdb", flags[i], O_RDWR, 0, + &tap_log_attr); + ok1(tdb); + if (!tdb) + continue; + + /* Should not have changed features offered. */ + ok1(tdb_read_convert(tdb, offsetof(struct tdb_header, + features_offered), + &features, sizeof(features)) == 0); + ok1(features == (~TDB_FEATURE_MASK ^ 1)); + + /* Should have cleared unknown bits in features_used. */ + ok1(tdb_read_convert(tdb, offsetof(struct tdb_header, + features_used), + &features, sizeof(features)) == 0); + ok1(features == (1 & TDB_FEATURE_MASK)); + + tdb_close(tdb); + } + + ok1(tap_log_messages == 0); + return exit_status(); +} + + -- 2.39.2