tdb2: add TDB_COALESCING_MAGIC to solve coalescing race.
authorRusty Russell <rusty@rustcorp.com.au>
Mon, 15 Nov 2010 07:25:34 +0000 (17:55 +1030)
committerRusty Russell <rusty@rustcorp.com.au>
Mon, 15 Nov 2010 07:25:34 +0000 (17:55 +1030)
A new special record marker to indicate coalescing is in progress.

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

index eb8ddcae79baba5ba8f0fa8a5b4e908b4332f105..f3fff5f6b8e25a99b0d34682b92788a28ea48c6a 100644 (file)
@@ -407,7 +407,8 @@ static tdb_off_t check_zone(struct tdb_context *tdb, tdb_off_t zone_off,
                p = tdb_get(tdb, off, &pad, sizeof(pad));
                if (!p)
                        return TDB_OFF_ERR;
-               if (frec_magic(&p->f) == TDB_FREE_MAGIC) {
+               if (frec_magic(&p->f) == TDB_FREE_MAGIC
+                   || frec_magic(&p->f) == TDB_COALESCING_MAGIC) {
                        if (frec_zone_bits(&p->f) != zhdr.zone_bits) {
                                tdb->log(tdb, TDB_DEBUG_ERROR, tdb->log_priv,
                                         "tdb_check: Bad free zone bits %u"
@@ -416,9 +417,6 @@ static tdb_off_t check_zone(struct tdb_context *tdb, tdb_off_t zone_off,
                                         (long long)off);
                                return TDB_OFF_ERR;
                        }
-                       /* This record is free! */
-                       if (!append(free, num_free, off))
-                               return TDB_OFF_ERR;
                        len = sizeof(p->u) + p->f.data_len;
                        if (off + len > zone_off + (1ULL << zhdr.zone_bits)) {
                                tdb->log(tdb, TDB_DEBUG_ERROR, tdb->log_priv,
@@ -427,6 +425,10 @@ static tdb_off_t check_zone(struct tdb_context *tdb, tdb_off_t zone_off,
                                         (long long)len, (long long)off);
                                return TDB_OFF_ERR;
                        }
+                       /* This record is free! */
+                       if (frec_magic(&p->f) == TDB_FREE_MAGIC
+                           && !append(free, num_free, off))
+                               return TDB_OFF_ERR;
                } else {
                        uint64_t klen, dlen, extra;
 
index 6780fdadd421303ee9aec389cae999b8b96d755c..4b61d13fba3f4f98d82cd902bd264c90838b1dcf 100644 (file)
@@ -65,6 +65,7 @@ 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)TDB_MAGIC) << 6)
+#define TDB_COALESCING_MAGIC (0xBAD1DEA2FEEDULL << 6)
 #define TDB_HASH_MAGIC (0xA1ABE11A01092008ULL)
 #define TDB_RECOVERY_MAGIC (0xf53bc0e7U)
 #define TDB_RECOVERY_INVALID_MAGIC (0x0)
index e9f986e7727a4775928617256ed65e11e0dbaa5c..52103ea6b5247672ef24f808a97a1a99f4153466 100644 (file)
@@ -89,7 +89,7 @@ static tdb_len_t summarize_zone(struct tdb_context *tdb, tdb_off_t zone_off,
                p = tdb_get(tdb, off, &pad, sizeof(pad));
                if (!p)
                        return TDB_OFF_ERR;
-               if (frec_magic(&p->f) == TDB_FREE_MAGIC) {
+               if (rec_magic(&p->u) != TDB_MAGIC) {
                        len = p->f.data_len;
                        tally_add(free, len);
                        bucketlen[size_to_bucket(frec_zone_bits(&p->f), len)]++;