Browse Source

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.
Rusty Russell 15 years ago
parent
commit
539f1af037
3 changed files with 13 additions and 11 deletions
  1. 3 4
      ccan/tdb2/check.c
  2. 7 6
      ccan/tdb2/free.c
  3. 3 1
      ccan/tdb2/private.h

+ 3 - 4
ccan/tdb2/check.c

@@ -497,8 +497,7 @@ static bool check_linear(struct tdb_context *tdb,
 			}
 			}
 			found_recovery = true;
 			found_recovery = true;
 			len = sizeof(rec.r) + rec.r.max_len;
 			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);
 			len = sizeof(rec.u) + frec_len(&rec.f);
 			if (off + len > tdb->map_size) {
 			if (off + len > tdb->map_size) {
 				tdb_logerr(tdb, TDB_ERR_CORRUPT,
 				tdb_logerr(tdb, TDB_ERR_CORRUPT,
@@ -508,8 +507,8 @@ static bool check_linear(struct tdb_context *tdb,
 					   (long long)len, (long long)off);
 					   (long long)len, (long long)off);
 				return false;
 				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))
 			    && !append(free, num_free, off))
 				return false;
 				return false;
 		} else {
 		} else {

+ 7 - 6
ccan/tdb2/free.c

@@ -278,7 +278,8 @@ static int coalesce(struct tdb_context *tdb,
 		if (!r)
 		if (!r)
 			goto err;
 			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);
 			tdb_access_release(tdb, r);
 			break;
 			break;
 		}
 		}
@@ -343,11 +344,11 @@ static int coalesce(struct tdb_context *tdb,
 
 
 	/* We have to drop this to avoid deadlocks, so make sure record
 	/* We have to drop this to avoid deadlocks, so make sure record
 	 * doesn't get coalesced by someone else! */
 	 * 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;
 		goto err;
 
 
 	add_stat(tdb, alloc_coalesce_succeeded, 1);
 	add_stat(tdb, alloc_coalesce_succeeded, 1);

+ 3 - 1
ccan/tdb2/private.h

@@ -66,7 +66,6 @@ typedef uint64_t tdb_off_t;
 #define TDB_VERSION ((uint64_t)(0x26011967 + 7))
 #define TDB_VERSION ((uint64_t)(0x26011967 + 7))
 #define TDB_MAGIC ((uint64_t)0x1999)
 #define TDB_MAGIC ((uint64_t)0x1999)
 #define TDB_FREE_MAGIC ((uint64_t)0xFE)
 #define TDB_FREE_MAGIC ((uint64_t)0xFE)
-#define TDB_COALESCING_MAGIC ((uint64_t)0xFD)
 #define TDB_HASH_MAGIC (0xA1ABE11A01092008ULL)
 #define TDB_HASH_MAGIC (0xA1ABE11A01092008ULL)
 #define TDB_RECOVERY_MAGIC (0xf53bc0e7ad124589ULL)
 #define TDB_RECOVERY_MAGIC (0xf53bc0e7ad124589ULL)
 #define TDB_RECOVERY_INVALID_MAGIC (0x0ULL)
 #define TDB_RECOVERY_INVALID_MAGIC (0x0ULL)
@@ -117,6 +116,9 @@ typedef uint64_t tdb_off_t;
 #define TDB_MIN_DATA_LEN	\
 #define TDB_MIN_DATA_LEN	\
 	(sizeof(struct tdb_free_record) - sizeof(struct tdb_used_record))
 	(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
 #if !HAVE_BSWAP_64
 static inline uint64_t bswap_64(uint64_t x)
 static inline uint64_t bswap_64(uint64_t x)
 {
 {