From: Rusty Russell Date: Wed, 1 Dec 2010 13:11:26 +0000 (+1030) Subject: tdb2: use magic freetable value rather than different magic for coalescing X-Git-Url: https://git.ozlabs.org/?p=ccan;a=commitdiff_plain;h=539f1af037858b905c50c560f2a608555d8457ff tdb2: use magic freetable value rather than different magic for coalescing We have to unlock during coalescing, so we mark records specially to indicate to tdb_check that they're not on any list, and to prevent other coalescers from grabbing them. Use a special free list number, rather than a new magic. --- diff --git a/ccan/tdb2/check.c b/ccan/tdb2/check.c index dc18e64a..0766f9e9 100644 --- a/ccan/tdb2/check.c +++ b/ccan/tdb2/check.c @@ -497,8 +497,7 @@ static bool check_linear(struct tdb_context *tdb, } found_recovery = true; len = sizeof(rec.r) + rec.r.max_len; - } else if (frec_magic(&rec.f) == TDB_FREE_MAGIC - || frec_magic(&rec.f) == TDB_COALESCING_MAGIC) { + } else if (frec_magic(&rec.f) == TDB_FREE_MAGIC) { len = sizeof(rec.u) + frec_len(&rec.f); if (off + len > tdb->map_size) { tdb_logerr(tdb, TDB_ERR_CORRUPT, @@ -508,8 +507,8 @@ static bool check_linear(struct tdb_context *tdb, (long long)len, (long long)off); return false; } - /* This record is free! */ - if (frec_magic(&rec.f) == TDB_FREE_MAGIC + /* This record should be in free lists. */ + if (frec_flist(&rec.f) != TDB_FLIST_NONE && !append(free, num_free, off)) return false; } else { diff --git a/ccan/tdb2/free.c b/ccan/tdb2/free.c index 49880f18..b41e1d58 100644 --- a/ccan/tdb2/free.c +++ b/ccan/tdb2/free.c @@ -278,7 +278,8 @@ static int coalesce(struct tdb_context *tdb, if (!r) goto err; - if (frec_magic(r) != TDB_FREE_MAGIC) { + if (frec_magic(r) != TDB_FREE_MAGIC + || frec_flist(r) == TDB_FLIST_NONE) { tdb_access_release(tdb, r); break; } @@ -343,11 +344,11 @@ static int coalesce(struct tdb_context *tdb, /* We have to drop this to avoid deadlocks, so make sure record * doesn't get coalesced by someone else! */ - rec.magic_and_prev = TDB_COALESCING_MAGIC - << (64 - TDB_OFF_UPPER_STEAL); - /* FIXME: Use 255 as invalid free list? */ - rec.flist_and_len = end - off - sizeof(struct tdb_used_record); - if (tdb_write_convert(tdb, off, &rec, sizeof(rec)) != 0) + rec.flist_and_len = (TDB_FLIST_NONE << (64 - TDB_OFF_UPPER_STEAL)) + | (end - off - sizeof(struct tdb_used_record)); + if (tdb_write_off(tdb, off + offsetof(struct tdb_free_record, + flist_and_len), + rec.flist_and_len) != 0) goto err; add_stat(tdb, alloc_coalesce_succeeded, 1); diff --git a/ccan/tdb2/private.h b/ccan/tdb2/private.h index 8601a9a4..b77d70c3 100644 --- a/ccan/tdb2/private.h +++ b/ccan/tdb2/private.h @@ -66,7 +66,6 @@ typedef uint64_t tdb_off_t; #define TDB_VERSION ((uint64_t)(0x26011967 + 7)) #define TDB_MAGIC ((uint64_t)0x1999) #define TDB_FREE_MAGIC ((uint64_t)0xFE) -#define TDB_COALESCING_MAGIC ((uint64_t)0xFD) #define TDB_HASH_MAGIC (0xA1ABE11A01092008ULL) #define TDB_RECOVERY_MAGIC (0xf53bc0e7ad124589ULL) #define TDB_RECOVERY_INVALID_MAGIC (0x0ULL) @@ -117,6 +116,9 @@ typedef uint64_t tdb_off_t; #define TDB_MIN_DATA_LEN \ (sizeof(struct tdb_free_record) - sizeof(struct tdb_used_record)) +/* Indicates this entry is not on an flist (can happen during coalescing) */ +#define TDB_FLIST_NONE ((1ULL << TDB_OFF_UPPER_STEAL) - 1) + #if !HAVE_BSWAP_64 static inline uint64_t bswap_64(uint64_t x) {