]> git.ozlabs.org Git - ccan/commitdiff
tdb2: use magic freetable value rather than different magic for coalescing
authorRusty Russell <rusty@rustcorp.com.au>
Wed, 1 Dec 2010 13:11:26 +0000 (23:41 +1030)
committerRusty Russell <rusty@rustcorp.com.au>
Wed, 1 Dec 2010 13:11:26 +0000 (23:41 +1030)
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.

ccan/tdb2/check.c
ccan/tdb2/free.c
ccan/tdb2/private.h

index dc18e64acc55e8d078a258a986200cd6e9daa89d..0766f9e9702122f011c5d4930072bd43e315ee3d 100644 (file)
@@ -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 {
index 49880f18dd51517601eca798d163e5e98b10b514..b41e1d58d2a699a76f74c98cb17f0e5e21ba5a97 100644 (file)
@@ -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);
index 8601a9a48e6497d0a93e3dfefe702ef897053a8e..b77d70c3ce6b0afa47eec11e2838a4cbbf4284ca 100644 (file)
@@ -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)
 {