}
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,
(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 {
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;
}
/* 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);
#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)
#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)
{