Browse Source

tdb2: add error conversion functions.

This clarifies the code a little, but also provides a more explicit
mechanism which can be used to debug error handling (by introducing
tdb_err_t and making it a pointer type).
Rusty Russell 14 years ago
parent
commit
afa6d57b7d

+ 5 - 5
ccan/tdb2/check.c

@@ -148,7 +148,7 @@ static enum TDB_ERROR check_hash_chain(struct tdb_context *tdb,
 
 
 	off = tdb_read_off(tdb, off + offsetof(struct tdb_chain, next));
 	off = tdb_read_off(tdb, off + offsetof(struct tdb_chain, next));
 	if (TDB_OFF_IS_ERR(off)) {
 	if (TDB_OFF_IS_ERR(off)) {
-		return off;
+		return TDB_OFF_TO_ERR(off);
 	}
 	}
 	if (off == 0)
 	if (off == 0)
 		return TDB_SUCCESS;
 		return TDB_SUCCESS;
@@ -534,7 +534,7 @@ static enum TDB_ERROR check_free_table(struct tdb_context *tdb,
 		h = bucket_off(ftable_off, i);
 		h = bucket_off(ftable_off, i);
 		for (off = tdb_read_off(tdb, h); off; off = f.next) {
 		for (off = tdb_read_off(tdb, h); off; off = f.next) {
 			if (TDB_OFF_IS_ERR(off)) {
 			if (TDB_OFF_IS_ERR(off)) {
-				return off;
+				return TDB_OFF_TO_ERR(off);
 			}
 			}
 			if (!first) {
 			if (!first) {
 				off &= TDB_OFF_MASK;
 				off &= TDB_OFF_MASK;
@@ -589,7 +589,7 @@ tdb_off_t dead_space(struct tdb_context *tdb, tdb_off_t off)
 		char c;
 		char c;
 		ecode = tdb->tdb2.io->tread(tdb, off, &c, 1);
 		ecode = tdb->tdb2.io->tread(tdb, off, &c, 1);
 		if (ecode != TDB_SUCCESS) {
 		if (ecode != TDB_SUCCESS) {
-			return ecode;
+			return TDB_ERR_TO_OFF(ecode);
 		}
 		}
 		if (c != 0 && c != 0x43)
 		if (c != 0 && c != 0x43)
 			break;
 			break;
@@ -634,7 +634,7 @@ static enum TDB_ERROR check_linear(struct tdb_context *tdb,
 			} else {
 			} else {
 				len = dead_space(tdb, off);
 				len = dead_space(tdb, off);
 				if (TDB_OFF_IS_ERR(len)) {
 				if (TDB_OFF_IS_ERR(len)) {
-					return len;
+					return TDB_OFF_TO_ERR(len);
 				}
 				}
 				if (len < sizeof(rec.r)) {
 				if (len < sizeof(rec.r)) {
 					return tdb_logerr(tdb, TDB_ERR_CORRUPT,
 					return tdb_logerr(tdb, TDB_ERR_CORRUPT,
@@ -811,7 +811,7 @@ enum TDB_ERROR tdb_check_(struct tdb_context *tdb,
 
 
 	for (ft = first_ftable(tdb); ft; ft = next_ftable(tdb, ft)) {
 	for (ft = first_ftable(tdb); ft; ft = next_ftable(tdb, ft)) {
 		if (TDB_OFF_IS_ERR(ft)) {
 		if (TDB_OFF_IS_ERR(ft)) {
-			ecode = ft;
+			ecode = TDB_OFF_TO_ERR(ft);
 			goto out;
 			goto out;
 		}
 		}
 		ecode = check_free_table(tdb, ft, num_ftables, fr, num_free,
 		ecode = check_free_table(tdb, ft, num_ftables, fr, num_free,

+ 19 - 19
ccan/tdb2/free.c

@@ -70,7 +70,7 @@ enum TDB_ERROR tdb_ftable_init(struct tdb_context *tdb)
 
 
 	while (off) {
 	while (off) {
 		if (TDB_OFF_IS_ERR(off)) {
 		if (TDB_OFF_IS_ERR(off)) {
-			return off;
+			return TDB_OFF_TO_ERR(off);
 		}
 		}
 
 
 		rnd = random();
 		rnd = random();
@@ -146,14 +146,14 @@ static enum TDB_ERROR remove_from_list(struct tdb_context *tdb,
 	/* Get prev->next */
 	/* Get prev->next */
 	prev_next = tdb_read_off(tdb, off);
 	prev_next = tdb_read_off(tdb, off);
 	if (TDB_OFF_IS_ERR(prev_next))
 	if (TDB_OFF_IS_ERR(prev_next))
-		return prev_next;
+		return TDB_OFF_TO_ERR(prev_next);
 
 
 	/* If prev->next == 0, we were head: update bucket to point to next. */
 	/* If prev->next == 0, we were head: update bucket to point to next. */
 	if (prev_next == 0) {
 	if (prev_next == 0) {
 		/* We must preserve upper bits. */
 		/* We must preserve upper bits. */
 		head = tdb_read_off(tdb, b_off);
 		head = tdb_read_off(tdb, b_off);
 		if (TDB_OFF_IS_ERR(head))
 		if (TDB_OFF_IS_ERR(head))
-			return head;
+			return TDB_OFF_TO_ERR(head);
 
 
 		if ((head & TDB_OFF_MASK) != r_off) {
 		if ((head & TDB_OFF_MASK) != r_off) {
 			return tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
 			return tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
@@ -178,7 +178,7 @@ static enum TDB_ERROR remove_from_list(struct tdb_context *tdb,
 	if (r->next == 0) {
 	if (r->next == 0) {
 		head = tdb_read_off(tdb, b_off);
 		head = tdb_read_off(tdb, b_off);
 		if (TDB_OFF_IS_ERR(head))
 		if (TDB_OFF_IS_ERR(head))
-			return head;
+			return TDB_OFF_TO_ERR(head);
 		head &= TDB_OFF_MASK;
 		head &= TDB_OFF_MASK;
 		off = head + offsetof(struct tdb_free_record, magic_and_prev);
 		off = head + offsetof(struct tdb_free_record, magic_and_prev);
 	} else {
 	} else {
@@ -215,7 +215,7 @@ static enum TDB_ERROR enqueue_in_free(struct tdb_context *tdb,
 
 
 	head = tdb_read_off(tdb, b_off);
 	head = tdb_read_off(tdb, b_off);
 	if (TDB_OFF_IS_ERR(head))
 	if (TDB_OFF_IS_ERR(head))
-		return head;
+		return TDB_OFF_TO_ERR(head);
 
 
 	/* We only need to set ftable_and_len; rest is set in enqueue_in_free */
 	/* We only need to set ftable_and_len; rest is set in enqueue_in_free */
 	new.ftable_and_len = ((uint64_t)tdb->tdb2.ftable << (64 - TDB_OFF_UPPER_STEAL))
 	new.ftable_and_len = ((uint64_t)tdb->tdb2.ftable << (64 - TDB_OFF_UPPER_STEAL))
@@ -336,7 +336,7 @@ static tdb_len_t coalesce(struct tdb_context *tdb,
 		nb_off = ftable_offset(tdb, ftable);
 		nb_off = ftable_offset(tdb, ftable);
 		if (TDB_OFF_IS_ERR(nb_off)) {
 		if (TDB_OFF_IS_ERR(nb_off)) {
 			tdb_access_release(tdb, r);
 			tdb_access_release(tdb, r);
-			ecode = nb_off;
+			ecode = TDB_OFF_TO_ERR(nb_off);
 			goto err;
 			goto err;
 		}
 		}
 		nb_off = bucket_off(nb_off, bucket);
 		nb_off = bucket_off(nb_off, bucket);
@@ -372,7 +372,7 @@ static tdb_len_t coalesce(struct tdb_context *tdb,
 		/* Did we just mess up a record you were hoping to use? */
 		/* Did we just mess up a record you were hoping to use? */
 		if (end == *protect) {
 		if (end == *protect) {
 			tdb->stats.alloc_coalesce_iterate_clash++;
 			tdb->stats.alloc_coalesce_iterate_clash++;
-			*protect = TDB_ERR_NOEXIST;
+			*protect = TDB_ERR_TO_OFF(TDB_ERR_NOEXIST);
 		}
 		}
 
 
 		ecode = remove_from_list(tdb, nb_off, end, &rec);
 		ecode = remove_from_list(tdb, nb_off, end, &rec);
@@ -393,7 +393,7 @@ static tdb_len_t coalesce(struct tdb_context *tdb,
 
 
 	/* Before we expand, check this isn't one you wanted protected? */
 	/* Before we expand, check this isn't one you wanted protected? */
 	if (off == *protect) {
 	if (off == *protect) {
-		*protect = TDB_ERR_EXISTS;
+		*protect = TDB_ERR_TO_OFF(TDB_ERR_EXISTS);
 		tdb->stats.alloc_coalesce_iterate_clash++;
 		tdb->stats.alloc_coalesce_iterate_clash++;
 	}
 	}
 
 
@@ -421,7 +421,7 @@ static tdb_len_t coalesce(struct tdb_context *tdb,
 	if (ecode != TDB_SUCCESS) {
 	if (ecode != TDB_SUCCESS) {
 		/* Need to drop lock.  Can't rely on anything stable. */
 		/* Need to drop lock.  Can't rely on anything stable. */
 		tdb->stats.alloc_coalesce_lockfail++;
 		tdb->stats.alloc_coalesce_lockfail++;
-		*protect = TDB_ERR_CORRUPT;
+		*protect = TDB_ERR_TO_OFF(TDB_ERR_CORRUPT);
 
 
 		/* 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! */
@@ -441,7 +441,7 @@ static tdb_len_t coalesce(struct tdb_context *tdb,
 		ecode = add_free_record(tdb, off, end - off, TDB_LOCK_WAIT,
 		ecode = add_free_record(tdb, off, end - off, TDB_LOCK_WAIT,
 					false);
 					false);
 		if (ecode != TDB_SUCCESS) {
 		if (ecode != TDB_SUCCESS) {
-			return ecode;
+			return TDB_ERR_TO_OFF(ecode);
 		}
 		}
 	} else if (TDB_OFF_IS_ERR(*protect)) {
 	} else if (TDB_OFF_IS_ERR(*protect)) {
 		/* For simplicity, we always drop lock if they can't continue */
 		/* For simplicity, we always drop lock if they can't continue */
@@ -455,7 +455,7 @@ static tdb_len_t coalesce(struct tdb_context *tdb,
 err:
 err:
 	/* To unify error paths, we *always* unlock bucket on error. */
 	/* To unify error paths, we *always* unlock bucket on error. */
 	tdb_unlock_free_bucket(tdb, b_off);
 	tdb_unlock_free_bucket(tdb, b_off);
-	return ecode;
+	return TDB_ERR_TO_OFF(ecode);
 }
 }
 
 
 /* List is locked: we unlock it. */
 /* List is locked: we unlock it. */
@@ -469,7 +469,7 @@ static enum TDB_ERROR coalesce_list(struct tdb_context *tdb,
 
 
 	off = tdb_read_off(tdb, b_off);
 	off = tdb_read_off(tdb, b_off);
 	if (TDB_OFF_IS_ERR(off)) {
 	if (TDB_OFF_IS_ERR(off)) {
-		ecode = off;
+		ecode = TDB_OFF_TO_ERR(off);
 		goto unlock_err;
 		goto unlock_err;
 	}
 	}
 	/* A little bit of paranoia: counter should be 0. */
 	/* A little bit of paranoia: counter should be 0. */
@@ -488,7 +488,7 @@ static enum TDB_ERROR coalesce_list(struct tdb_context *tdb,
 		coal = coalesce(tdb, off, b_off, frec_len(&rec), &next);
 		coal = coalesce(tdb, off, b_off, frec_len(&rec), &next);
 		if (TDB_OFF_IS_ERR(coal)) {
 		if (TDB_OFF_IS_ERR(coal)) {
 			/* This has already unlocked on error. */
 			/* This has already unlocked on error. */
-			return coal;
+			return TDB_OFF_TO_ERR(coal);
 		}
 		}
 		if (TDB_OFF_IS_ERR(next)) {
 		if (TDB_OFF_IS_ERR(next)) {
 			/* Coalescing had to unlock, so stop. */
 			/* Coalescing had to unlock, so stop. */
@@ -520,7 +520,7 @@ static enum TDB_ERROR coalesce_list(struct tdb_context *tdb,
 		/* Get the old head. */
 		/* Get the old head. */
 		oldhoff = tdb_read_off(tdb, b_off);
 		oldhoff = tdb_read_off(tdb, b_off);
 		if (TDB_OFF_IS_ERR(oldhoff)) {
 		if (TDB_OFF_IS_ERR(oldhoff)) {
-			ecode = oldhoff;
+			ecode = TDB_OFF_TO_ERR(oldhoff);
 			goto unlock_err;
 			goto unlock_err;
 		}
 		}
 
 
@@ -661,7 +661,7 @@ static tdb_off_t lock_and_alloc(struct tdb_context *tdb,
 	/* Lock this bucket. */
 	/* Lock this bucket. */
 	ecode = tdb_lock_free_bucket(tdb, b_off, TDB_LOCK_WAIT);
 	ecode = tdb_lock_free_bucket(tdb, b_off, TDB_LOCK_WAIT);
 	if (ecode != TDB_SUCCESS) {
 	if (ecode != TDB_SUCCESS) {
-		return ecode;
+		return TDB_ERR_TO_OFF(ecode);
 	}
 	}
 
 
 	best.ftable_and_len = -1ULL;
 	best.ftable_and_len = -1ULL;
@@ -677,7 +677,7 @@ static tdb_off_t lock_and_alloc(struct tdb_context *tdb,
 	 * as we go. */
 	 * as we go. */
 	off = tdb_read_off(tdb, b_off);
 	off = tdb_read_off(tdb, b_off);
 	if (TDB_OFF_IS_ERR(off)) {
 	if (TDB_OFF_IS_ERR(off)) {
-		ecode = off;
+		ecode = TDB_OFF_TO_ERR(off);
 		goto unlock_err;
 		goto unlock_err;
 	}
 	}
 	off &= TDB_OFF_MASK;
 	off &= TDB_OFF_MASK;
@@ -768,7 +768,7 @@ static tdb_off_t lock_and_alloc(struct tdb_context *tdb,
 						+ frec_len(&best) - leftover,
 						+ frec_len(&best) - leftover,
 						leftover, TDB_LOCK_WAIT, false);
 						leftover, TDB_LOCK_WAIT, false);
 			if (ecode != TDB_SUCCESS) {
 			if (ecode != TDB_SUCCESS) {
-				best_off = ecode;
+				best_off = TDB_ERR_TO_OFF(ecode);
 			}
 			}
 		}
 		}
 		tdb_unlock_free_bucket(tdb, b_off);
 		tdb_unlock_free_bucket(tdb, b_off);
@@ -781,7 +781,7 @@ static tdb_off_t lock_and_alloc(struct tdb_context *tdb,
 
 
 unlock_err:
 unlock_err:
 	tdb_unlock_free_bucket(tdb, b_off);
 	tdb_unlock_free_bucket(tdb, b_off);
-	return ecode;
+	return TDB_ERR_TO_OFF(ecode);
 }
 }
 
 
 /* Get a free block from current free list, or 0 if none, -ve on error. */
 /* Get a free block from current free list, or 0 if none, -ve on error. */
@@ -960,7 +960,7 @@ tdb_off_t alloc(struct tdb_context *tdb, size_t keylen, size_t datalen,
 
 
 		ecode = tdb_expand(tdb, adjust_size(keylen, datalen));
 		ecode = tdb_expand(tdb, adjust_size(keylen, datalen));
 		if (ecode != TDB_SUCCESS) {
 		if (ecode != TDB_SUCCESS) {
-			return ecode;
+			return TDB_ERR_TO_OFF(ecode);
 		}
 		}
 	}
 	}
 
 

+ 16 - 15
ccan/tdb2/hash.c

@@ -90,7 +90,7 @@ static tdb_bool_err key_matches(struct tdb_context *tdb,
 
 
 	rkey = tdb_access_read(tdb, off + sizeof(*rec), key->dsize, false);
 	rkey = tdb_access_read(tdb, off + sizeof(*rec), key->dsize, false);
 	if (TDB_PTR_IS_ERR(rkey)) {
 	if (TDB_PTR_IS_ERR(rkey)) {
-		return TDB_PTR_ERR(rkey);
+		return (tdb_bool_err)TDB_PTR_ERR(rkey);
 	}
 	}
 	if (memcmp(rkey, key->dptr, key->dsize) == 0)
 	if (memcmp(rkey, key->dptr, key->dsize) == 0)
 		ret = true;
 		ret = true;
@@ -128,7 +128,7 @@ static tdb_bool_err match(struct tdb_context *tdb,
 	off = val & TDB_OFF_MASK;
 	off = val & TDB_OFF_MASK;
 	ecode = tdb_read_convert(tdb, off, rec, sizeof(*rec));
 	ecode = tdb_read_convert(tdb, off, rec, sizeof(*rec));
 	if (ecode != TDB_SUCCESS) {
 	if (ecode != TDB_SUCCESS) {
-		return ecode;
+		return (tdb_bool_err)ecode;
 	}
 	}
 
 
 	if ((h->h & ((1 << 11)-1)) != rec_hash(rec)) {
 	if ((h->h & ((1 << 11)-1)) != rec_hash(rec)) {
@@ -176,7 +176,7 @@ static tdb_off_t COLD find_in_chain(struct tdb_context *tdb,
 		h->group_start = off;
 		h->group_start = off;
 		ecode = tdb_read_convert(tdb, off, h->group, sizeof(h->group));
 		ecode = tdb_read_convert(tdb, off, h->group, sizeof(h->group));
 		if (ecode != TDB_SUCCESS) {
 		if (ecode != TDB_SUCCESS) {
-			return ecode;
+			return TDB_ERR_TO_OFF(ecode);
 		}
 		}
 
 
 		for (i = 0; i < (1 << TDB_HASH_GROUP_BITS); i++) {
 		for (i = 0; i < (1 << TDB_HASH_GROUP_BITS); i++) {
@@ -193,14 +193,15 @@ static tdb_off_t COLD find_in_chain(struct tdb_context *tdb,
 			ecode = tdb_read_convert(tdb, recoff, rec,
 			ecode = tdb_read_convert(tdb, recoff, rec,
 						 sizeof(*rec));
 						 sizeof(*rec));
 			if (ecode != TDB_SUCCESS) {
 			if (ecode != TDB_SUCCESS) {
-				return ecode;
+				return TDB_ERR_TO_OFF(ecode);
 			}
 			}
 
 
-			ecode = key_matches(tdb, rec, recoff, &key);
+			ecode = TDB_OFF_TO_ERR(key_matches(tdb, rec, recoff,
+							   &key));
 			if (ecode < 0) {
 			if (ecode < 0) {
-				return ecode;
+				return TDB_ERR_TO_OFF(ecode);
 			}
 			}
-			if (ecode == 1) {
+			if (ecode == (enum TDB_ERROR)1) {
 				h->home_bucket = h->found_bucket = i;
 				h->home_bucket = h->found_bucket = i;
 
 
 				if (tinfo) {
 				if (tinfo) {
@@ -252,7 +253,7 @@ tdb_off_t find_and_lock(struct tdb_context *tdb,
 	ecode = tdb_lock_hashes(tdb, h->hlock_start, h->hlock_range, ltype,
 	ecode = tdb_lock_hashes(tdb, h->hlock_start, h->hlock_range, ltype,
 				TDB_LOCK_WAIT);
 				TDB_LOCK_WAIT);
 	if (ecode != TDB_SUCCESS) {
 	if (ecode != TDB_SUCCESS) {
-		return ecode;
+		return TDB_ERR_TO_OFF(ecode);
 	}
 	}
 
 
 	hashtable = offsetof(struct tdb_header, hashtable);
 	hashtable = offsetof(struct tdb_header, hashtable);
@@ -315,7 +316,7 @@ tdb_off_t find_and_lock(struct tdb_context *tdb,
 			berr = match(tdb, h, &key, h->group[h->found_bucket],
 			berr = match(tdb, h, &key, h->group[h->found_bucket],
 				     rec);
 				     rec);
 			if (berr < 0) {
 			if (berr < 0) {
-				ecode = berr;
+				ecode = TDB_OFF_TO_ERR(berr);
 				goto fail;
 				goto fail;
 			}
 			}
 			if (berr) {
 			if (berr) {
@@ -334,7 +335,7 @@ tdb_off_t find_and_lock(struct tdb_context *tdb,
 
 
 fail:
 fail:
 	tdb_unlock_hashes(tdb, h->hlock_start, h->hlock_range, ltype);
 	tdb_unlock_hashes(tdb, h->hlock_start, h->hlock_range, ltype);
-	return ecode;
+	return TDB_ERR_TO_OFF(ecode);
 }
 }
 
 
 /* I wrote a simple test, expanding a hash to 2GB, for the following
 /* I wrote a simple test, expanding a hash to 2GB, for the following
@@ -426,7 +427,7 @@ static enum TDB_ERROR COLD add_to_chain(struct tdb_context *tdb,
 
 
 	entry = tdb_find_zero_off(tdb, subhash, 1<<TDB_HASH_GROUP_BITS);
 	entry = tdb_find_zero_off(tdb, subhash, 1<<TDB_HASH_GROUP_BITS);
 	if (TDB_OFF_IS_ERR(entry)) {
 	if (TDB_OFF_IS_ERR(entry)) {
-		return entry;
+		return TDB_OFF_TO_ERR(entry);
 	}
 	}
 
 
 	if (entry == 1 << TDB_HASH_GROUP_BITS) {
 	if (entry == 1 << TDB_HASH_GROUP_BITS) {
@@ -435,14 +436,14 @@ static enum TDB_ERROR COLD add_to_chain(struct tdb_context *tdb,
 		next = tdb_read_off(tdb, subhash
 		next = tdb_read_off(tdb, subhash
 				    + offsetof(struct tdb_chain, next));
 				    + offsetof(struct tdb_chain, next));
 		if (TDB_OFF_IS_ERR(next)) {
 		if (TDB_OFF_IS_ERR(next)) {
-			return next;
+			return TDB_OFF_TO_ERR(next);
 		}
 		}
 
 
 		if (!next) {
 		if (!next) {
 			next = alloc(tdb, 0, sizeof(struct tdb_chain), 0,
 			next = alloc(tdb, 0, sizeof(struct tdb_chain), 0,
 				     TDB_CHAIN_MAGIC, false);
 				     TDB_CHAIN_MAGIC, false);
 			if (TDB_OFF_IS_ERR(next))
 			if (TDB_OFF_IS_ERR(next))
-				return next;
+				return TDB_OFF_TO_ERR(next);
 			ecode = zero_out(tdb,
 			ecode = zero_out(tdb,
 					 next+sizeof(struct tdb_used_record),
 					 next+sizeof(struct tdb_used_record),
 					 sizeof(struct tdb_chain));
 					 sizeof(struct tdb_chain));
@@ -515,7 +516,7 @@ static enum TDB_ERROR expand_group(struct tdb_context *tdb, struct hash_info *h)
 
 
 	subhash = alloc(tdb, 0, subsize, 0, magic, false);
 	subhash = alloc(tdb, 0, subsize, 0, magic, false);
 	if (TDB_OFF_IS_ERR(subhash)) {
 	if (TDB_OFF_IS_ERR(subhash)) {
-		return subhash;
+		return TDB_OFF_TO_ERR(subhash);
 	}
 	}
 
 
 	ecode = zero_out(tdb, subhash + sizeof(struct tdb_used_record),
 	ecode = zero_out(tdb, subhash + sizeof(struct tdb_used_record),
@@ -760,7 +761,7 @@ enum TDB_ERROR next_in_hash(struct tdb_context *tdb,
 			struct tdb_used_record rec;
 			struct tdb_used_record rec;
 
 
 			if (TDB_OFF_IS_ERR(off)) {
 			if (TDB_OFF_IS_ERR(off)) {
-				ecode = off;
+				ecode = TDB_OFF_TO_ERR(off);
 				goto fail;
 				goto fail;
 			}
 			}
 
 

+ 4 - 4
ccan/tdb2/io.c

@@ -162,7 +162,7 @@ uint64_t tdb_find_nonzero_off(struct tdb_context *tdb,
 	val = tdb_access_read(tdb, base + start * sizeof(tdb_off_t),
 	val = tdb_access_read(tdb, base + start * sizeof(tdb_off_t),
 			      (end - start) * sizeof(tdb_off_t), false);
 			      (end - start) * sizeof(tdb_off_t), false);
 	if (TDB_PTR_IS_ERR(val)) {
 	if (TDB_PTR_IS_ERR(val)) {
-		return TDB_PTR_ERR(val);
+		return TDB_ERR_TO_OFF(TDB_PTR_ERR(val));
 	}
 	}
 
 
 	for (i = 0; i < (end - start); i++) {
 	for (i = 0; i < (end - start); i++) {
@@ -183,7 +183,7 @@ uint64_t tdb_find_zero_off(struct tdb_context *tdb, tdb_off_t off,
 	/* Zero vs non-zero is the same unconverted: minor optimization. */
 	/* Zero vs non-zero is the same unconverted: minor optimization. */
 	val = tdb_access_read(tdb, off, num * sizeof(tdb_off_t), false);
 	val = tdb_access_read(tdb, off, num * sizeof(tdb_off_t), false);
 	if (TDB_PTR_IS_ERR(val)) {
 	if (TDB_PTR_IS_ERR(val)) {
-		return TDB_PTR_ERR(val);
+		return TDB_ERR_TO_OFF(TDB_PTR_ERR(val));
 	}
 	}
 
 
 	for (i = 0; i < num; i++) {
 	for (i = 0; i < num; i++) {
@@ -229,7 +229,7 @@ tdb_off_t tdb_read_off(struct tdb_context *tdb, tdb_off_t off)
 		tdb_off_t *p = tdb->tdb2.io->direct(tdb, off, sizeof(*p),
 		tdb_off_t *p = tdb->tdb2.io->direct(tdb, off, sizeof(*p),
 						    false);
 						    false);
 		if (TDB_PTR_IS_ERR(p)) {
 		if (TDB_PTR_IS_ERR(p)) {
-			return TDB_PTR_ERR(p);
+			return TDB_ERR_TO_OFF(TDB_PTR_ERR(p));
 		}
 		}
 		if (p)
 		if (p)
 			return *p;
 			return *p;
@@ -237,7 +237,7 @@ tdb_off_t tdb_read_off(struct tdb_context *tdb, tdb_off_t off)
 
 
 	ecode = tdb_read_convert(tdb, off, &ret, sizeof(ret));
 	ecode = tdb_read_convert(tdb, off, &ret, sizeof(ret));
 	if (ecode != TDB_SUCCESS) {
 	if (ecode != TDB_SUCCESS) {
-		return ecode;
+		return TDB_ERR_TO_OFF(ecode);
 	}
 	}
 	return ret;
 	return ret;
 }
 }

+ 2 - 2
ccan/tdb2/lock.c

@@ -415,7 +415,7 @@ enum TDB_ERROR tdb_nest_lock(struct tdb_context *tdb,
 			tdb_brunlock(tdb, ltype, offset, 1);
 			tdb_brunlock(tdb, ltype, offset, 1);
 
 
 			if (berr < 0)
 			if (berr < 0)
-				return berr;
+				return TDB_OFF_TO_ERR(berr);
 			ecode = tdb_lock_and_recover(tdb);
 			ecode = tdb_lock_and_recover(tdb);
 			if (ecode == TDB_SUCCESS) {
 			if (ecode == TDB_SUCCESS) {
 				ecode = tdb_brlock(tdb, ltype, offset, 1,
 				ecode = tdb_brlock(tdb, ltype, offset, 1,
@@ -613,7 +613,7 @@ again:
 
 
 	tdb_allrecord_unlock(tdb, ltype);
 	tdb_allrecord_unlock(tdb, ltype);
 	if (berr < 0)
 	if (berr < 0)
-		return berr;
+		return TDB_OFF_TO_ERR(berr);
 	ecode = tdb_lock_and_recover(tdb);
 	ecode = tdb_lock_and_recover(tdb);
 	if (ecode != TDB_SUCCESS) {
 	if (ecode != TDB_SUCCESS) {
 		return ecode;
 		return ecode;

+ 7 - 7
ccan/tdb2/open.c

@@ -706,7 +706,7 @@ finished:
 		berr = tdb_needs_recovery(tdb);
 		berr = tdb_needs_recovery(tdb);
 		if (unlikely(berr != false)) {
 		if (unlikely(berr != false)) {
 			if (berr < 0) {
 			if (berr < 0) {
-				ecode = berr;
+				ecode = TDB_OFF_TO_ERR(berr);
 				goto fail;
 				goto fail;
 			}
 			}
 			ecode = tdb_lock_and_recover(tdb);
 			ecode = tdb_lock_and_recover(tdb);
@@ -727,18 +727,18 @@ finished:
 
 
  fail:
  fail:
 	/* Map ecode to some logical errno. */
 	/* Map ecode to some logical errno. */
-	switch (ecode) {
-	case TDB_ERR_CORRUPT:
-	case TDB_ERR_IO:
+	switch (TDB_ERR_TO_OFF(ecode)) {
+	case TDB_ERR_TO_OFF(TDB_ERR_CORRUPT):
+	case TDB_ERR_TO_OFF(TDB_ERR_IO):
 		saved_errno = EIO;
 		saved_errno = EIO;
 		break;
 		break;
-	case TDB_ERR_LOCK:
+	case TDB_ERR_TO_OFF(TDB_ERR_LOCK):
 		saved_errno = EWOULDBLOCK;
 		saved_errno = EWOULDBLOCK;
 		break;
 		break;
-	case TDB_ERR_OOM:
+	case TDB_ERR_TO_OFF(TDB_ERR_OOM):
 		saved_errno = ENOMEM;
 		saved_errno = ENOMEM;
 		break;
 		break;
-	case TDB_ERR_EINVAL:
+	case TDB_ERR_TO_OFF(TDB_ERR_EINVAL):
 		saved_errno = EINVAL;
 		saved_errno = EINVAL;
 		break;
 		break;
 	default:
 	default:

+ 3 - 1
ccan/tdb2/private.h

@@ -65,7 +65,9 @@ typedef uint64_t tdb_off_t;
 #define TDB_RECOVERY_MAGIC (0xf53bc0e7ad124589ULL)
 #define TDB_RECOVERY_MAGIC (0xf53bc0e7ad124589ULL)
 #define TDB_RECOVERY_INVALID_MAGIC (0x0ULL)
 #define TDB_RECOVERY_INVALID_MAGIC (0x0ULL)
 
 
-#define TDB_OFF_IS_ERR(off) unlikely(off >= (tdb_off_t)TDB_ERR_LAST)
+#define TDB_OFF_IS_ERR(off) unlikely(off >= (tdb_off_t)(long)TDB_ERR_LAST)
+#define TDB_OFF_TO_ERR(off) ((enum TDB_ERROR)(long)(off))
+#define TDB_ERR_TO_OFF(ecode) ((tdb_off_t)(long)(ecode))
 
 
 /* Packing errors into pointers and v.v. */
 /* Packing errors into pointers and v.v. */
 #define TDB_PTR_IS_ERR(ptr) \
 #define TDB_PTR_IS_ERR(ptr) \

+ 3 - 3
ccan/tdb2/summary.c

@@ -28,7 +28,7 @@ static tdb_off_t count_hash(struct tdb_context *tdb,
 
 
 	h = tdb_access_read(tdb, hash_off, sizeof(*h) << bits, true);
 	h = tdb_access_read(tdb, hash_off, sizeof(*h) << bits, true);
 	if (TDB_PTR_IS_ERR(h)) {
 	if (TDB_PTR_IS_ERR(h)) {
-		return TDB_PTR_ERR(h);
+		return TDB_ERR_TO_OFF(TDB_PTR_ERR(h));
 	}
 	}
 	for (i = 0; i < (1 << bits); i++)
 	for (i = 0; i < (1 << bits); i++)
 		count += (h[i] != 0);
 		count += (h[i] != 0);
@@ -93,7 +93,7 @@ static enum TDB_ERROR summarize(struct tdb_context *tdb,
 						     off + sizeof(p->u),
 						     off + sizeof(p->u),
 						     TDB_SUBLEVEL_HASH_BITS);
 						     TDB_SUBLEVEL_HASH_BITS);
 			if (TDB_OFF_IS_ERR(count)) {
 			if (TDB_OFF_IS_ERR(count)) {
-				return count;
+				return TDB_OFF_TO_ERR(count);
 			}
 			}
 			tally_add(hashes, count);
 			tally_add(hashes, count);
 			tally_add(extra, rec_extra_padding(&p->u));
 			tally_add(extra, rec_extra_padding(&p->u));
@@ -115,7 +115,7 @@ static enum TDB_ERROR summarize(struct tdb_context *tdb,
 		} else {
 		} else {
 			len = dead_space(tdb, off);
 			len = dead_space(tdb, off);
 			if (TDB_OFF_IS_ERR(len)) {
 			if (TDB_OFF_IS_ERR(len)) {
-				return len;
+				return TDB_OFF_TO_ERR(len);
 			}
 			}
 		}
 		}
 		tdb_access_release(tdb, p);
 		tdb_access_release(tdb, p);

+ 19 - 19
ccan/tdb2/tdb.c

@@ -50,7 +50,7 @@ static enum TDB_ERROR replace_data(struct tdb_context *tdb,
 	new_off = alloc(tdb, key.dsize, dbuf.dsize, h->h, TDB_USED_MAGIC,
 	new_off = alloc(tdb, key.dsize, dbuf.dsize, h->h, TDB_USED_MAGIC,
 			growing);
 			growing);
 	if (TDB_OFF_IS_ERR(new_off)) {
 	if (TDB_OFF_IS_ERR(new_off)) {
-		return new_off;
+		return TDB_OFF_TO_ERR(new_off);
 	}
 	}
 
 
 	/* We didn't like the existing one: remove it. */
 	/* We didn't like the existing one: remove it. */
@@ -122,7 +122,7 @@ enum TDB_ERROR tdb_store(struct tdb_context *tdb,
 
 
 	off = find_and_lock(tdb, key, F_WRLCK, &h, &rec, NULL);
 	off = find_and_lock(tdb, key, F_WRLCK, &h, &rec, NULL);
 	if (TDB_OFF_IS_ERR(off)) {
 	if (TDB_OFF_IS_ERR(off)) {
-		return tdb->last_error = off;
+		return tdb->last_error = TDB_OFF_TO_ERR(off);
 	}
 	}
 
 
 	/* Now we have lock on this hash bucket. */
 	/* Now we have lock on this hash bucket. */
@@ -191,7 +191,7 @@ enum TDB_ERROR tdb_append(struct tdb_context *tdb,
 
 
 	off = find_and_lock(tdb, key, F_WRLCK, &h, &rec, NULL);
 	off = find_and_lock(tdb, key, F_WRLCK, &h, &rec, NULL);
 	if (TDB_OFF_IS_ERR(off)) {
 	if (TDB_OFF_IS_ERR(off)) {
-		return tdb->last_error = off;
+		return tdb->last_error = TDB_OFF_TO_ERR(off);
 	}
 	}
 
 
 	if (off) {
 	if (off) {
@@ -259,7 +259,7 @@ enum TDB_ERROR tdb_fetch(struct tdb_context *tdb, struct tdb_data key,
 
 
 	off = find_and_lock(tdb, key, F_RDLCK, &h, &rec, NULL);
 	off = find_and_lock(tdb, key, F_RDLCK, &h, &rec, NULL);
 	if (TDB_OFF_IS_ERR(off)) {
 	if (TDB_OFF_IS_ERR(off)) {
-		return tdb->last_error = off;
+		return tdb->last_error = TDB_OFF_TO_ERR(off);
 	}
 	}
 
 
 	if (!off) {
 	if (!off) {
@@ -290,7 +290,7 @@ bool tdb_exists(struct tdb_context *tdb, TDB_DATA key)
 
 
 	off = find_and_lock(tdb, key, F_RDLCK, &h, &rec, NULL);
 	off = find_and_lock(tdb, key, F_RDLCK, &h, &rec, NULL);
 	if (TDB_OFF_IS_ERR(off)) {
 	if (TDB_OFF_IS_ERR(off)) {
-		tdb->last_error = off;
+		tdb->last_error = TDB_OFF_TO_ERR(off);
 		return false;
 		return false;
 	}
 	}
 	tdb_unlock_hashes(tdb, h.hlock_start, h.hlock_range, F_RDLCK);
 	tdb_unlock_hashes(tdb, h.hlock_start, h.hlock_range, F_RDLCK);
@@ -314,7 +314,7 @@ enum TDB_ERROR tdb_delete(struct tdb_context *tdb, struct tdb_data key)
 
 
 	off = find_and_lock(tdb, key, F_WRLCK, &h, &rec, NULL);
 	off = find_and_lock(tdb, key, F_WRLCK, &h, &rec, NULL);
 	if (TDB_OFF_IS_ERR(off)) {
 	if (TDB_OFF_IS_ERR(off)) {
-		return tdb->last_error = off;
+		return tdb->last_error = TDB_OFF_TO_ERR(off);
 	}
 	}
 
 
 	if (!off) {
 	if (!off) {
@@ -465,16 +465,16 @@ void tdb_remove_flag(struct tdb_context *tdb, unsigned flag)
 const char *tdb_errorstr(enum TDB_ERROR ecode)
 const char *tdb_errorstr(enum TDB_ERROR ecode)
 {
 {
 	/* Gcc warns if you miss a case in the switch, so use that. */
 	/* Gcc warns if you miss a case in the switch, so use that. */
-	switch (ecode) {
-	case TDB_SUCCESS: return "Success";
-	case TDB_ERR_CORRUPT: return "Corrupt database";
-	case TDB_ERR_IO: return "IO Error";
-	case TDB_ERR_LOCK: return "Locking error";
-	case TDB_ERR_OOM: return "Out of memory";
-	case TDB_ERR_EXISTS: return "Record exists";
-	case TDB_ERR_EINVAL: return "Invalid parameter";
-	case TDB_ERR_NOEXIST: return "Record does not exist";
-	case TDB_ERR_RDONLY: return "write not permitted";
+	switch (TDB_ERR_TO_OFF(ecode)) {
+	case TDB_ERR_TO_OFF(TDB_SUCCESS): return "Success";
+	case TDB_ERR_TO_OFF(TDB_ERR_CORRUPT): return "Corrupt database";
+	case TDB_ERR_TO_OFF(TDB_ERR_IO): return "IO Error";
+	case TDB_ERR_TO_OFF(TDB_ERR_LOCK): return "Locking error";
+	case TDB_ERR_TO_OFF(TDB_ERR_OOM): return "Out of memory";
+	case TDB_ERR_TO_OFF(TDB_ERR_EXISTS): return "Record exists";
+	case TDB_ERR_TO_OFF(TDB_ERR_EINVAL): return "Invalid parameter";
+	case TDB_ERR_TO_OFF(TDB_ERR_NOEXIST): return "Record does not exist";
+	case TDB_ERR_TO_OFF(TDB_ERR_RDONLY): return "write not permitted";
 	}
 	}
 	return "Invalid error code";
 	return "Invalid error code";
 }
 }
@@ -533,7 +533,7 @@ enum TDB_ERROR tdb_parse_record_(struct tdb_context *tdb,
 
 
 	off = find_and_lock(tdb, key, F_RDLCK, &h, &rec, NULL);
 	off = find_and_lock(tdb, key, F_RDLCK, &h, &rec, NULL);
 	if (TDB_OFF_IS_ERR(off)) {
 	if (TDB_OFF_IS_ERR(off)) {
-		return tdb->last_error = off;
+		return tdb->last_error = TDB_OFF_TO_ERR(off);
 	}
 	}
 
 
 	if (!off) {
 	if (!off) {
@@ -571,14 +571,14 @@ int64_t tdb_get_seqnum(struct tdb_context *tdb)
 		val = tdb1_get_seqnum(tdb);
 		val = tdb1_get_seqnum(tdb);
 
 
 		if (tdb->last_error != TDB_SUCCESS)
 		if (tdb->last_error != TDB_SUCCESS)
-			return tdb->last_error;
+			return TDB_ERR_TO_OFF(tdb->last_error);
 		else
 		else
 			return val;
 			return val;
 	}
 	}
 
 
 	off = tdb_read_off(tdb, offsetof(struct tdb_header, seqnum));
 	off = tdb_read_off(tdb, offsetof(struct tdb_header, seqnum));
 	if (TDB_OFF_IS_ERR(off))
 	if (TDB_OFF_IS_ERR(off))
-		tdb->last_error = off;
+		tdb->last_error = TDB_OFF_TO_ERR(off);
 	else
 	else
 		tdb->last_error = TDB_SUCCESS;
 		tdb->last_error = TDB_SUCCESS;
 	return off;
 	return off;

+ 2 - 2
ccan/tdb2/tdb1_transaction.c

@@ -1318,7 +1318,7 @@ tdb_bool_err tdb1_needs_recovery(struct tdb_context *tdb)
 
 
 	/* find the recovery area */
 	/* find the recovery area */
 	if (tdb1_ofs_read(tdb, TDB1_RECOVERY_HEAD, &recovery_head) == -1) {
 	if (tdb1_ofs_read(tdb, TDB1_RECOVERY_HEAD, &recovery_head) == -1) {
-		return tdb->last_error;
+		return TDB_ERR_TO_OFF(tdb->last_error);
 	}
 	}
 
 
 	if (recovery_head == 0) {
 	if (recovery_head == 0) {
@@ -1329,7 +1329,7 @@ tdb_bool_err tdb1_needs_recovery(struct tdb_context *tdb)
 	/* read the recovery record */
 	/* read the recovery record */
 	if (tdb->tdb1.io->tdb1_read(tdb, recovery_head, &rec,
 	if (tdb->tdb1.io->tdb1_read(tdb, recovery_head, &rec,
 				   sizeof(rec), TDB1_DOCONV()) == -1) {
 				   sizeof(rec), TDB1_DOCONV()) == -1) {
-		return tdb->last_error;
+		return TDB_ERR_TO_OFF(tdb->last_error);
 	}
 	}
 
 
 	return (rec.magic == TDB1_RECOVERY_MAGIC);
 	return (rec.magic == TDB1_RECOVERY_MAGIC);

+ 13 - 10
ccan/tdb2/transaction.c

@@ -668,7 +668,7 @@ static enum TDB_ERROR tdb_recovery_area(struct tdb_context *tdb,
 	*recovery_offset = tdb_read_off(tdb,
 	*recovery_offset = tdb_read_off(tdb,
 					offsetof(struct tdb_header, recovery));
 					offsetof(struct tdb_header, recovery));
 	if (TDB_OFF_IS_ERR(*recovery_offset)) {
 	if (TDB_OFF_IS_ERR(*recovery_offset)) {
-		return *recovery_offset;
+		return TDB_OFF_TO_ERR(*recovery_offset);
 	}
 	}
 
 
 	if (*recovery_offset == 0) {
 	if (*recovery_offset == 0) {
@@ -852,9 +852,10 @@ static tdb_off_t create_recovery_area(struct tdb_context *tdb,
 	tdb->stats.transaction_expand_file++;
 	tdb->stats.transaction_expand_file++;
 	ecode = methods->expand_file(tdb, addition);
 	ecode = methods->expand_file(tdb, addition);
 	if (ecode != TDB_SUCCESS) {
 	if (ecode != TDB_SUCCESS) {
-		return tdb_logerr(tdb, ecode, TDB_LOG_ERROR,
-				  "tdb_recovery_allocate:"
-				  " failed to create recovery area");
+		tdb_logerr(tdb, ecode, TDB_LOG_ERROR,
+			   "tdb_recovery_allocate:"
+			   " failed to create recovery area");
+		return TDB_ERR_TO_OFF(ecode);
 	}
 	}
 
 
 	/* we have to reset the old map size so that we don't try to
 	/* we have to reset the old map size so that we don't try to
@@ -869,9 +870,10 @@ static tdb_off_t create_recovery_area(struct tdb_context *tdb,
 	ecode = methods->twrite(tdb, offsetof(struct tdb_header, recovery),
 	ecode = methods->twrite(tdb, offsetof(struct tdb_header, recovery),
 				&recovery_off, sizeof(tdb_off_t));
 				&recovery_off, sizeof(tdb_off_t));
 	if (ecode != TDB_SUCCESS) {
 	if (ecode != TDB_SUCCESS) {
-		return tdb_logerr(tdb, ecode, TDB_LOG_ERROR,
-				  "tdb_recovery_allocate:"
-				  " failed to write recovery head");
+		tdb_logerr(tdb, ecode, TDB_LOG_ERROR,
+			   "tdb_recovery_allocate:"
+			   " failed to write recovery head");
+		return TDB_ERR_TO_OFF(ecode);
 	}
 	}
 	transaction_write_existing(tdb, offsetof(struct tdb_header, recovery),
 	transaction_write_existing(tdb, offsetof(struct tdb_header, recovery),
 				   &recovery_off,
 				   &recovery_off,
@@ -928,7 +930,7 @@ static enum TDB_ERROR transaction_setup_recovery(struct tdb_context *tdb)
 						    recovery);
 						    recovery);
 		if (TDB_OFF_IS_ERR(recovery_off)) {
 		if (TDB_OFF_IS_ERR(recovery_off)) {
 			free(recovery);
 			free(recovery);
-			return recovery_off;
+			return TDB_OFF_TO_ERR(recovery_off);
 		}
 		}
 	}
 	}
 
 
@@ -1194,7 +1196,8 @@ enum TDB_ERROR tdb_transaction_recover(struct tdb_context *tdb)
 	/* find the recovery area */
 	/* find the recovery area */
 	recovery_head = tdb_read_off(tdb, offsetof(struct tdb_header,recovery));
 	recovery_head = tdb_read_off(tdb, offsetof(struct tdb_header,recovery));
 	if (TDB_OFF_IS_ERR(recovery_head)) {
 	if (TDB_OFF_IS_ERR(recovery_head)) {
-		return tdb_logerr(tdb, recovery_head, TDB_LOG_ERROR,
+		ecode = TDB_OFF_TO_ERR(recovery_head);
+		return tdb_logerr(tdb, ecode, TDB_LOG_ERROR,
 				  "tdb_transaction_recover:"
 				  "tdb_transaction_recover:"
 				  " failed to read recovery head");
 				  " failed to read recovery head");
 	}
 	}
@@ -1330,7 +1333,7 @@ tdb_bool_err tdb_needs_recovery(struct tdb_context *tdb)
 	/* read the recovery record */
 	/* read the recovery record */
 	ecode = tdb_read_convert(tdb, recovery_head, &rec, sizeof(rec));
 	ecode = tdb_read_convert(tdb, recovery_head, &rec, sizeof(rec));
 	if (ecode != TDB_SUCCESS) {
 	if (ecode != TDB_SUCCESS) {
-		return ecode;
+		return TDB_ERR_TO_OFF(ecode);
 	}
 	}
 
 
 	return (rec.magic == TDB_RECOVERY_MAGIC);
 	return (rec.magic == TDB_RECOVERY_MAGIC);

+ 4 - 4
ccan/tdb2/traverse.c

@@ -31,7 +31,7 @@ int64_t tdb_traverse_(struct tdb_context *tdb,
 	if (tdb->flags & TDB_VERSION1) {
 	if (tdb->flags & TDB_VERSION1) {
 		count = tdb1_traverse(tdb, fn, p);
 		count = tdb1_traverse(tdb, fn, p);
 		if (count == -1)
 		if (count == -1)
-			return tdb->last_error;
+			return TDB_ERR_TO_OFF(tdb->last_error);
 		return count;
 		return count;
 	}
 	}
 
 
@@ -51,7 +51,7 @@ int64_t tdb_traverse_(struct tdb_context *tdb,
 	}
 	}
 
 
 	if (ecode != TDB_ERR_NOEXIST) {
 	if (ecode != TDB_ERR_NOEXIST) {
-		return tdb->last_error = ecode;
+		return TDB_ERR_TO_OFF(tdb->last_error = ecode);
 	}
 	}
 	tdb->last_error = TDB_SUCCESS;
 	tdb->last_error = TDB_SUCCESS;
 	return count;
 	return count;
@@ -96,7 +96,7 @@ enum TDB_ERROR tdb_nextkey(struct tdb_context *tdb, struct tdb_data *key)
 	tinfo.prev = find_and_lock(tdb, *key, F_RDLCK, &h, &rec, &tinfo);
 	tinfo.prev = find_and_lock(tdb, *key, F_RDLCK, &h, &rec, &tinfo);
 	free(key->dptr);
 	free(key->dptr);
 	if (TDB_OFF_IS_ERR(tinfo.prev)) {
 	if (TDB_OFF_IS_ERR(tinfo.prev)) {
-		return tdb->last_error = tinfo.prev;
+		return tdb->last_error = TDB_OFF_TO_ERR(tinfo.prev);
 	}
 	}
 	tdb_unlock_hashes(tdb, h.hlock_start, h.hlock_range, F_RDLCK);
 	tdb_unlock_hashes(tdb, h.hlock_start, h.hlock_range, F_RDLCK);
 
 
@@ -128,7 +128,7 @@ enum TDB_ERROR tdb_wipe_all(struct tdb_context *tdb)
 	/* FIXME: Be smarter. */
 	/* FIXME: Be smarter. */
 	count = tdb_traverse(tdb, wipe_one, &ecode);
 	count = tdb_traverse(tdb, wipe_one, &ecode);
 	if (count < 0)
 	if (count < 0)
-		ecode = count;
+		ecode = TDB_OFF_TO_ERR(count);
 	tdb_allrecord_unlock(tdb, F_WRLCK);
 	tdb_allrecord_unlock(tdb, F_WRLCK);
 	return tdb->last_error = ecode;
 	return tdb->last_error = ecode;
 }
 }