Browse Source

tdb2: rework remaining io.c functions to return enum TDB_ERROR.

In particular, we replace the TDB_OFF_ERR ((off_t)-1) with a range of
negative error values.
Rusty Russell 15 years ago
parent
commit
323a9473c0
5 changed files with 77 additions and 31 deletions
  1. 10 4
      ccan/tdb2/check.c
  2. 30 6
      ccan/tdb2/free.c
  3. 25 7
      ccan/tdb2/hash.c
  4. 6 9
      ccan/tdb2/io.c
  5. 6 5
      ccan/tdb2/transaction.c

+ 10 - 4
ccan/tdb2/check.c

@@ -136,8 +136,10 @@ static bool check_hash_chain(struct tdb_context *tdb,
 		return false;
 		return false;
 
 
 	off = tdb_read_off(tdb, off + offsetof(struct tdb_chain, next));
 	off = tdb_read_off(tdb, off + offsetof(struct tdb_chain, next));
-	if (off == TDB_OFF_ERR)
+	if (TDB_OFF_IS_ERR(off)) {
+		tdb->ecode = off;
 		return false;
 		return false;
+	}
 	if (off == 0)
 	if (off == 0)
 		return true;
 		return true;
 	(*num_found)++;
 	(*num_found)++;
@@ -512,8 +514,10 @@ static bool 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 (off == TDB_OFF_ERR)
+			if (TDB_OFF_IS_ERR(off)) {
+				tdb->ecode = off;
 				return false;
 				return false;
+			}
 			ecode = tdb_read_convert(tdb, off, &f, sizeof(f));
 			ecode = tdb_read_convert(tdb, off, &f, sizeof(f));
 			if (ecode != TDB_SUCCESS) {
 			if (ecode != TDB_SUCCESS) {
 				tdb->ecode = ecode;
 				tdb->ecode = ecode;
@@ -725,7 +729,7 @@ int tdb_check(struct tdb_context *tdb,
 	enum TDB_ERROR ecode;
 	enum TDB_ERROR ecode;
 
 
 	ecode = tdb_allrecord_lock(tdb, F_RDLCK, TDB_LOCK_WAIT, false);
 	ecode = tdb_allrecord_lock(tdb, F_RDLCK, TDB_LOCK_WAIT, false);
-	if (ecpde != TDB_SUCCESS) {
+	if (ecode != TDB_SUCCESS) {
 		tdb->ecode = ecode;
 		tdb->ecode = ecode;
 		return -1;
 		return -1;
 	}
 	}
@@ -745,8 +749,10 @@ int tdb_check(struct tdb_context *tdb,
 		goto fail;
 		goto fail;
 
 
 	for (ft = first_ftable(tdb); ft; ft = next_ftable(tdb, ft)) {
 	for (ft = first_ftable(tdb); ft; ft = next_ftable(tdb, ft)) {
-		if (ft == TDB_OFF_ERR)
+		if (TDB_OFF_IS_ERR(ft)) {
+			tdb->ecode = ft;
 			goto fail;
 			goto fail;
+		}
 		if (!check_free_table(tdb, ft, num_ftables, fr, num_free,
 		if (!check_free_table(tdb, ft, num_ftables, fr, num_free,
 				      &num_found))
 				      &num_found))
 			goto fail;
 			goto fail;

+ 30 - 6
ccan/tdb2/free.c

@@ -69,8 +69,10 @@ int tdb_ftable_init(struct tdb_context *tdb)
 	tdb->ftable = 0;
 	tdb->ftable = 0;
 
 
 	while (off) {
 	while (off) {
-		if (off == TDB_OFF_ERR)
+		if (TDB_OFF_IS_ERR(off)) {
+			tdb->ecode = off;
 			return -1;
 			return -1;
+		}
 
 
 		rnd = random();
 		rnd = random();
 		if (rnd >= max) {
 		if (rnd >= max) {
@@ -92,7 +94,7 @@ tdb_off_t bucket_off(tdb_off_t ftable_off, unsigned bucket)
 		+ bucket * sizeof(tdb_off_t);
 		+ bucket * sizeof(tdb_off_t);
 }
 }
 
 
-/* Returns free_buckets + 1, or list number to search. */
+/* Returns free_buckets + 1, or list number to search, or -ve error. */
 static tdb_off_t find_free_head(struct tdb_context *tdb,
 static tdb_off_t find_free_head(struct tdb_context *tdb,
 				tdb_off_t ftable_off,
 				tdb_off_t ftable_off,
 				tdb_off_t bucket)
 				tdb_off_t bucket)
@@ -173,8 +175,10 @@ static int enqueue_in_free(struct tdb_context *tdb,
 
 
 	/* new->next = head. */
 	/* new->next = head. */
 	new.next = tdb_read_off(tdb, b_off);
 	new.next = tdb_read_off(tdb, b_off);
-	if (new.next == TDB_OFF_ERR)
+	if (TDB_OFF_IS_ERR(new.next)) {
+		tdb->ecode = new.next;
 		return -1;
 		return -1;
+	}
 
 
 	if (new.next) {
 	if (new.next) {
 #ifdef CCAN_TDB2_DEBUG
 #ifdef CCAN_TDB2_DEBUG
@@ -275,8 +279,13 @@ static tdb_off_t ftable_offset(struct tdb_context *tdb, unsigned int ftable)
 		return tdb->ftable_off;
 		return tdb->ftable_off;
 
 
 	off = first_ftable(tdb);
 	off = first_ftable(tdb);
-	for (i = 0; i < ftable; i++)
+	for (i = 0; i < ftable; i++) {
+		if (TDB_OFF_IS_ERR(off)) {
+			tdb->ecode = off;
+			break;
+		}
 		off = next_ftable(tdb, off);
 		off = next_ftable(tdb, off);
+	}
 	return off;
 	return off;
 }
 }
 
 
@@ -436,8 +445,10 @@ again:
 	/* Walk the list to see if any are large enough, getting less fussy
 	/* Walk the list to see if any are large enough, getting less fussy
 	 * as we go. */
 	 * as we go. */
 	off = tdb_read_off(tdb, b_off);
 	off = tdb_read_off(tdb, b_off);
-	if (unlikely(off == TDB_OFF_ERR))
+	if (TDB_OFF_IS_ERR(off)) {
+		tdb->ecode = off;
 		goto unlock_err;
 		goto unlock_err;
+	}
 
 
 	while (off) {
 	while (off) {
 		const struct tdb_free_record *r;
 		const struct tdb_free_record *r;
@@ -540,7 +551,7 @@ static tdb_off_t get_free(struct tdb_context *tdb,
 			  unsigned magic, unsigned hashlow)
 			  unsigned magic, unsigned hashlow)
 {
 {
 	tdb_off_t off, ftable_off;
 	tdb_off_t off, ftable_off;
-	unsigned start_b, b, ftable;
+	tdb_off_t start_b, b, ftable;
 	bool wrapped = false;
 	bool wrapped = false;
 
 
 	/* If they are growing, add 50% to get to higher bucket. */
 	/* If they are growing, add 50% to get to higher bucket. */
@@ -576,13 +587,26 @@ static tdb_off_t get_free(struct tdb_context *tdb,
 			/* Didn't work.  Try next bucket. */
 			/* Didn't work.  Try next bucket. */
 		}
 		}
 
 
+		if (TDB_OFF_IS_ERR(b)) {
+			tdb->ecode = b;
+			return 0;
+		}
+
 		/* Hmm, try next table. */
 		/* Hmm, try next table. */
 		ftable_off = next_ftable(tdb, ftable_off);
 		ftable_off = next_ftable(tdb, ftable_off);
+		if (TDB_OFF_IS_ERR(ftable_off)) {
+			tdb->ecode = ftable_off;
+			return 0;
+		}
 		ftable++;
 		ftable++;
 
 
 		if (ftable_off == 0) {
 		if (ftable_off == 0) {
 			wrapped = true;
 			wrapped = true;
 			ftable_off = first_ftable(tdb);
 			ftable_off = first_ftable(tdb);
+			if (TDB_OFF_IS_ERR(ftable_off)) {
+				tdb->ecode = ftable_off;
+				return 0;
+			}
 			ftable = 0;
 			ftable = 0;
 		}
 		}
 	}
 	}

+ 25 - 7
ccan/tdb2/hash.c

@@ -225,8 +225,10 @@ static tdb_off_t COLD find_in_chain(struct tdb_context *tdb,
 		}
 		}
 		next = tdb_read_off(tdb, off
 		next = tdb_read_off(tdb, off
 				    + offsetof(struct tdb_chain, next));
 				    + offsetof(struct tdb_chain, next));
-		if (next == TDB_OFF_ERR)
+		if (TDB_OFF_IS_ERR(next)) {
+			tdb->ecode = next;
 			return TDB_OFF_ERR;
 			return TDB_OFF_ERR;
+		}
 		if (next)
 		if (next)
 			next += sizeof(struct tdb_used_record);
 			next += sizeof(struct tdb_used_record);
 	}
 	}
@@ -430,16 +432,24 @@ static int COLD add_to_chain(struct tdb_context *tdb,
 			     tdb_off_t subhash,
 			     tdb_off_t subhash,
 			     tdb_off_t new_off)
 			     tdb_off_t new_off)
 {
 {
-	size_t entry = tdb_find_zero_off(tdb, subhash, 1<<TDB_HASH_GROUP_BITS);
+	tdb_off_t entry;
 	enum TDB_ERROR ecode;
 	enum TDB_ERROR ecode;
 
 
+	entry = tdb_find_zero_off(tdb, subhash, 1<<TDB_HASH_GROUP_BITS);
+	if (TDB_OFF_IS_ERR(entry)) {
+		tdb->ecode = entry;
+		return -1;
+	}
+
 	if (entry == 1 << TDB_HASH_GROUP_BITS) {
 	if (entry == 1 << TDB_HASH_GROUP_BITS) {
 		tdb_off_t next;
 		tdb_off_t next;
 
 
 		next = tdb_read_off(tdb, subhash
 		next = tdb_read_off(tdb, subhash
 				    + offsetof(struct tdb_chain, next));
 				    + offsetof(struct tdb_chain, next));
-		if (next == TDB_OFF_ERR)
+		if (TDB_OFF_IS_ERR(next)) {
+			tdb->ecode = next;
 			return -1;
 			return -1;
+		}
 
 
 		if (!next) {
 		if (!next) {
 			next = alloc(tdb, 0, sizeof(struct tdb_chain), 0,
 			next = alloc(tdb, 0, sizeof(struct tdb_chain), 0,
@@ -692,8 +702,7 @@ int add_to_hash(struct tdb_context *tdb, struct hash_info *h, tdb_off_t new_off)
 static tdb_off_t iterate_hash(struct tdb_context *tdb,
 static tdb_off_t iterate_hash(struct tdb_context *tdb,
 			      struct traverse_info *tinfo)
 			      struct traverse_info *tinfo)
 {
 {
-	tdb_off_t off, val;
-	unsigned int i;
+	tdb_off_t off, val, i;
 	struct traverse_level *tlevel;
 	struct traverse_level *tlevel;
 
 
 	tlevel = &tinfo->levels[tinfo->num_levels-1];
 	tlevel = &tinfo->levels[tinfo->num_levels-1];
@@ -704,9 +713,16 @@ again:
 	     i != tlevel->total_buckets;
 	     i != tlevel->total_buckets;
 	     i = tdb_find_nonzero_off(tdb, tlevel->hashtable,
 	     i = tdb_find_nonzero_off(tdb, tlevel->hashtable,
 				      i+1, tlevel->total_buckets)) {
 				      i+1, tlevel->total_buckets)) {
+		if (TDB_OFF_IS_ERR(i)) {
+			tdb->ecode = i;
+			return TDB_OFF_ERR;
+		}
+
 		val = tdb_read_off(tdb, tlevel->hashtable+sizeof(tdb_off_t)*i);
 		val = tdb_read_off(tdb, tlevel->hashtable+sizeof(tdb_off_t)*i);
-		if (unlikely(val == TDB_OFF_ERR))
+		if (TDB_OFF_IS_ERR(val)) {
+			tdb->ecode = val;
 			return TDB_OFF_ERR;
 			return TDB_OFF_ERR;
+		}
 
 
 		off = val & TDB_OFF_MASK;
 		off = val & TDB_OFF_MASK;
 
 
@@ -746,8 +762,10 @@ again:
 		tlevel->hashtable = tdb_read_off(tdb, tlevel->hashtable
 		tlevel->hashtable = tdb_read_off(tdb, tlevel->hashtable
 						 + offsetof(struct tdb_chain,
 						 + offsetof(struct tdb_chain,
 							    next));
 							    next));
-		if (tlevel->hashtable == TDB_OFF_ERR)
+		if (TDB_OFF_IS_ERR(tlevel->hashtable)) {
+			tdb->ecode = tlevel->hashtable;
 			return TDB_OFF_ERR;
 			return TDB_OFF_ERR;
+		}
 		if (tlevel->hashtable) {
 		if (tlevel->hashtable) {
 			tlevel->hashtable += sizeof(struct tdb_used_record);
 			tlevel->hashtable += sizeof(struct tdb_used_record);
 			tlevel->entry = 0;
 			tlevel->entry = 0;

+ 6 - 9
ccan/tdb2/io.c

@@ -133,6 +133,7 @@ void *tdb_convert(const struct tdb_context *tdb, void *buf, tdb_len_t size)
 	return buf;
 	return buf;
 }
 }
 
 
+/* Return first non-zero offset in offset array, or end, or -ve error. */
 /* FIXME: Return the off? */
 /* FIXME: Return the off? */
 uint64_t tdb_find_nonzero_off(struct tdb_context *tdb,
 uint64_t tdb_find_nonzero_off(struct tdb_context *tdb,
 			      tdb_off_t base, uint64_t start, uint64_t end)
 			      tdb_off_t base, uint64_t start, uint64_t end)
@@ -144,8 +145,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)) {
-		tdb->ecode = TDB_PTR_ERR(val);
-		return end;
+		return TDB_PTR_ERR(val);
 	}
 	}
 
 
 	for (i = 0; i < (end - start); i++) {
 	for (i = 0; i < (end - start); i++) {
@@ -156,7 +156,7 @@ uint64_t tdb_find_nonzero_off(struct tdb_context *tdb,
 	return start + i;
 	return start + i;
 }
 }
 
 
-/* Return first zero offset in num offset array, or num. */
+/* Return first zero offset in num offset array, or num, or -ve error. */
 uint64_t tdb_find_zero_off(struct tdb_context *tdb, tdb_off_t off,
 uint64_t tdb_find_zero_off(struct tdb_context *tdb, tdb_off_t off,
 			   uint64_t num)
 			   uint64_t num)
 {
 {
@@ -166,8 +166,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)) {
-		tdb->ecode = TDB_PTR_ERR(val);
-		return num;
+		return TDB_PTR_ERR(val);
 	}
 	}
 
 
 	for (i = 0; i < num; i++) {
 	for (i = 0; i < num; i++) {
@@ -213,8 +212,7 @@ tdb_off_t tdb_read_off(struct tdb_context *tdb, tdb_off_t off)
 		tdb_off_t *p = tdb->methods->direct(tdb, off, sizeof(*p),
 		tdb_off_t *p = tdb->methods->direct(tdb, off, sizeof(*p),
 						    false);
 						    false);
 		if (TDB_PTR_IS_ERR(p)) {
 		if (TDB_PTR_IS_ERR(p)) {
-			tdb->ecode = TDB_PTR_ERR(p);
-			return TDB_OFF_ERR;
+			return TDB_PTR_ERR(p);
 		}
 		}
 		if (p)
 		if (p)
 			return *p;
 			return *p;
@@ -222,8 +220,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) {
-		tdb->ecode = ecode;
-		return TDB_OFF_ERR;
+		return ecode;
 	}
 	}
 	return ret;
 	return ret;
 }
 }

+ 6 - 5
ccan/tdb2/transaction.c

@@ -642,8 +642,8 @@ static int tdb_recovery_allocate(struct tdb_context *tdb,
 	enum TDB_ERROR ecode;
 	enum TDB_ERROR ecode;
 
 
 	recovery_head = tdb_read_off(tdb, offsetof(struct tdb_header,recovery));
 	recovery_head = tdb_read_off(tdb, offsetof(struct tdb_header,recovery));
-	if (recovery_head == TDB_OFF_ERR) {
-		tdb_logerr(tdb, tdb->ecode, TDB_LOG_ERROR,
+	if (TDB_OFF_IS_ERR(recovery_head)) {
+		tdb_logerr(tdb, recovery_head, TDB_LOG_ERROR,
 			 "tdb_recovery_allocate:"
 			 "tdb_recovery_allocate:"
 			 " failed to read recovery head");
 			 " failed to read recovery head");
 		return -1;
 		return -1;
@@ -1108,8 +1108,8 @@ int 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 (recovery_head == TDB_OFF_ERR) {
-		tdb_logerr(tdb, tdb->ecode, TDB_LOG_ERROR,
+	if (TDB_OFF_IS_ERR(recovery_head)) {
+		tdb_logerr(tdb, recovery_head, TDB_LOG_ERROR,
 			 "tdb_transaction_recover:"
 			 "tdb_transaction_recover:"
 			 " failed to read recovery head");
 			 " failed to read recovery head");
 		return -1;
 		return -1;
@@ -1241,7 +1241,8 @@ bool tdb_needs_recovery(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 (recovery_head == TDB_OFF_ERR) {
+	if (TDB_OFF_IS_ERR(recovery_head)) {
+		tdb->ecode = recovery_head;
 		return true;
 		return true;
 	}
 	}