Browse Source

tdb2: rework io functions to return enum TDB_ERROR.

We have a series of I/O functions which change depending on whether we're
inside a transaction or not.  This makes them return enum TDB_ERROR instead
of int.
Rusty Russell 15 years ago
parent
commit
012f68a073
6 changed files with 257 additions and 162 deletions
  1. 14 4
      ccan/tdb2/check.c
  2. 3 1
      ccan/tdb2/free.c
  3. 76 55
      ccan/tdb2/io.c
  4. 6 4
      ccan/tdb2/private.h
  5. 28 9
      ccan/tdb2/tdb.c
  6. 130 89
      ccan/tdb2/transaction.c

+ 14 - 4
ccan/tdb2/check.c

@@ -416,6 +416,8 @@ static bool check_free(struct tdb_context *tdb,
 		       tdb_off_t prev, unsigned int ftable,
 		       tdb_off_t prev, unsigned int ftable,
 		       unsigned int bucket)
 		       unsigned int bucket)
 {
 {
+	enum TDB_ERROR ecode;
+
 	if (frec_magic(frec) != TDB_FREE_MAGIC) {
 	if (frec_magic(frec) != TDB_FREE_MAGIC) {
 		tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
 		tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
 			   "tdb_check: offset %llu bad magic 0x%llx",
 			   "tdb_check: offset %llu bad magic 0x%llx",
@@ -429,10 +431,14 @@ static bool check_free(struct tdb_context *tdb,
 		return false;
 		return false;
 	}
 	}
 
 
-	if (tdb->methods->oob(tdb, off
-			      + frec_len(frec) + sizeof(struct tdb_used_record),
-			      false))
+	ecode = tdb->methods->oob(tdb, off
+				  + frec_len(frec)
+				  + sizeof(struct tdb_used_record),
+				  false);
+	if (ecode != TDB_SUCCESS) {
+		tdb->ecode = ecode;
 		return false;
 		return false;
+	}
 	if (size_to_bucket(frec_len(frec)) != bucket) {
 	if (size_to_bucket(frec_len(frec)) != bucket) {
 		tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
 		tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
 			   "tdb_check: offset %llu in wrong bucket %u vs %u",
 			   "tdb_check: offset %llu in wrong bucket %u vs %u",
@@ -509,11 +515,15 @@ static bool check_free_table(struct tdb_context *tdb,
 size_t dead_space(struct tdb_context *tdb, tdb_off_t off)
 size_t dead_space(struct tdb_context *tdb, tdb_off_t off)
 {
 {
 	size_t len;
 	size_t len;
+	enum TDB_ERROR ecode;
 
 
 	for (len = 0; off + len < tdb->map_size; len++) {
 	for (len = 0; off + len < tdb->map_size; len++) {
 		char c;
 		char c;
-		if (tdb->methods->tread(tdb, off, &c, 1))
+		ecode = tdb->methods->tread(tdb, off, &c, 1);
+		if (ecode != TDB_SUCCESS) {
+			tdb->ecode = ecode;
 			return 0;
 			return 0;
+		}
 		if (c != 0 && c != 0x43)
 		if (c != 0 && c != 0x43)
 			break;
 			break;
 	}
 	}

+ 3 - 1
ccan/tdb2/free.c

@@ -625,7 +625,9 @@ static int tdb_expand(struct tdb_context *tdb, tdb_len_t size)
 		return 0;
 		return 0;
 	}
 	}
 
 
-	if (tdb->methods->expand_file(tdb, wanted) == -1) {
+	ecode = tdb->methods->expand_file(tdb, wanted);
+	if (ecode != TDB_SUCCESS) {
+		tdb->ecode = ecode;
 		tdb_unlock_expand(tdb, F_WRLCK);
 		tdb_unlock_expand(tdb, F_WRLCK);
 		return -1;
 		return -1;
 	}
 	}

+ 76 - 55
ccan/tdb2/io.c

@@ -67,7 +67,8 @@ void tdb_mmap(struct tdb_context *tdb)
    if necessary
    if necessary
    note that "len" is the minimum length needed for the db
    note that "len" is the minimum length needed for the db
 */
 */
-static int tdb_oob(struct tdb_context *tdb, tdb_off_t len, bool probe)
+static enum TDB_ERROR tdb_oob(struct tdb_context *tdb, tdb_off_t len,
+			      bool probe)
 {
 {
 	struct stat st;
 	struct stat st;
 	enum TDB_ERROR ecode;
 	enum TDB_ERROR ecode;
@@ -87,20 +88,19 @@ static int tdb_oob(struct tdb_context *tdb, tdb_off_t len, bool probe)
 				 (long long)len,
 				 (long long)len,
 				 (long long)tdb->map_size);
 				 (long long)tdb->map_size);
 		}
 		}
-		return -1;
+		return TDB_ERR_IO;
 	}
 	}
 
 
 	ecode = tdb_lock_expand(tdb, F_RDLCK);
 	ecode = tdb_lock_expand(tdb, F_RDLCK);
 	if (ecode != TDB_SUCCESS) {
 	if (ecode != TDB_SUCCESS) {
-		tdb->ecode = ecode;
-		return -1;
+		return ecode;
 	}
 	}
 
 
 	if (fstat(tdb->fd, &st) != 0) {
 	if (fstat(tdb->fd, &st) != 0) {
 		tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
 		tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
 			   "Failed to fstat file: %s", strerror(errno));
 			   "Failed to fstat file: %s", strerror(errno));
 		tdb_unlock_expand(tdb, F_RDLCK);
 		tdb_unlock_expand(tdb, F_RDLCK);
-		return -1;
+		return TDB_ERR_IO;
 	}
 	}
 
 
 	tdb_unlock_expand(tdb, F_RDLCK);
 	tdb_unlock_expand(tdb, F_RDLCK);
@@ -111,7 +111,7 @@ static int tdb_oob(struct tdb_context *tdb, tdb_off_t len, bool probe)
 				   "tdb_oob len %zu beyond eof at %zu",
 				   "tdb_oob len %zu beyond eof at %zu",
 				   (size_t)len, st.st_size);
 				   (size_t)len, st.st_size);
 		}
 		}
-		return -1;
+		return TDB_ERR_IO;
 	}
 	}
 
 
 	/* Unmap, update size, remap */
 	/* Unmap, update size, remap */
@@ -119,7 +119,7 @@ static int tdb_oob(struct tdb_context *tdb, tdb_off_t len, bool probe)
 
 
 	tdb->map_size = st.st_size;
 	tdb->map_size = st.st_size;
 	tdb_mmap(tdb);
 	tdb_mmap(tdb);
-	return 0;
+	return TDB_SUCCESS;
 }
 }
 
 
 /* Endian conversion: we only ever deal with 8 byte quantities */
 /* Endian conversion: we only ever deal with 8 byte quantities */
@@ -178,6 +178,7 @@ int zero_out(struct tdb_context *tdb, tdb_off_t off, tdb_len_t len)
 {
 {
 	char buf[8192] = { 0 };
 	char buf[8192] = { 0 };
 	void *p = tdb->methods->direct(tdb, off, len, true);
 	void *p = tdb->methods->direct(tdb, off, len, true);
+	enum TDB_ERROR ecode;
 
 
 	assert(!tdb->read_only);
 	assert(!tdb->read_only);
 	if (p) {
 	if (p) {
@@ -186,8 +187,11 @@ int zero_out(struct tdb_context *tdb, tdb_off_t off, tdb_len_t len)
 	}
 	}
 	while (len) {
 	while (len) {
 		unsigned todo = len < sizeof(buf) ? len : sizeof(buf);
 		unsigned todo = len < sizeof(buf) ? len : sizeof(buf);
-		if (tdb->methods->twrite(tdb, off, buf, todo) == -1)
+		ecode = tdb->methods->twrite(tdb, off, buf, todo);
+		if (ecode != TDB_SUCCESS) {
+			tdb->ecode = ecode;
 			return -1;
 			return -1;
+		}
 		len -= todo;
 		len -= todo;
 		off += todo;
 		off += todo;
 	}
 	}
@@ -211,22 +215,25 @@ tdb_off_t tdb_read_off(struct tdb_context *tdb, tdb_off_t off)
 }
 }
 
 
 /* write a lump of data at a specified offset */
 /* write a lump of data at a specified offset */
-static int tdb_write(struct tdb_context *tdb, tdb_off_t off,
-		     const void *buf, tdb_len_t len)
+static enum TDB_ERROR tdb_write(struct tdb_context *tdb, tdb_off_t off,
+				const void *buf, tdb_len_t len)
 {
 {
+	enum TDB_ERROR ecode;
+
 	if (tdb->read_only) {
 	if (tdb->read_only) {
-		tdb_logerr(tdb, TDB_ERR_RDONLY, TDB_LOG_USE_ERROR,
-			   "Write to read-only database");
-		return -1;
+		return tdb_logerr(tdb, TDB_ERR_RDONLY, TDB_LOG_USE_ERROR,
+				  "Write to read-only database");
 	}
 	}
 
 
 	/* FIXME: Bogus optimization? */
 	/* FIXME: Bogus optimization? */
 	if (len == 0) {
 	if (len == 0) {
-		return 0;
+		return TDB_SUCCESS;
 	}
 	}
 
 
-	if (tdb->methods->oob(tdb, off + len, 0) != 0)
-		return -1;
+	ecode = tdb->methods->oob(tdb, off + len, 0);
+	if (ecode != TDB_SUCCESS) {
+		return ecode;
+	}
 
 
 	if (tdb->map_ptr) {
 	if (tdb->map_ptr) {
 		memcpy(off + (char *)tdb->map_ptr, buf, len);
 		memcpy(off + (char *)tdb->map_ptr, buf, len);
@@ -238,22 +245,24 @@ static int tdb_write(struct tdb_context *tdb, tdb_off_t off,
 			if (ret >= 0)
 			if (ret >= 0)
 				errno = ENOSPC;
 				errno = ENOSPC;
 
 
-			tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
-				   "tdb_write: %zi at %zu len=%zu (%s)",
-				   ret, (size_t)off, (size_t)len,
-				   strerror(errno));
-			return -1;
+			return tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
+					  "tdb_write: %zi at %zu len=%zu (%s)",
+					  ret, (size_t)off, (size_t)len,
+					  strerror(errno));
 		}
 		}
 	}
 	}
-	return 0;
+	return TDB_SUCCESS;
 }
 }
 
 
 /* read a lump of data at a specified offset */
 /* read a lump of data at a specified offset */
-static int tdb_read(struct tdb_context *tdb, tdb_off_t off, void *buf,
-		    tdb_len_t len)
+static enum TDB_ERROR tdb_read(struct tdb_context *tdb, tdb_off_t off,
+			       void *buf, tdb_len_t len)
 {
 {
-	if (tdb->methods->oob(tdb, off + len, 0) != 0) {
-		return -1;
+	enum TDB_ERROR ecode;
+
+	ecode = tdb->methods->oob(tdb, off + len, 0);
+	if (ecode != TDB_SUCCESS) {
+		return ecode;
 	}
 	}
 
 
 	if (tdb->map_ptr) {
 	if (tdb->map_ptr) {
@@ -261,22 +270,22 @@ static int tdb_read(struct tdb_context *tdb, tdb_off_t off, void *buf,
 	} else {
 	} else {
 		ssize_t r = pread(tdb->fd, buf, len, off);
 		ssize_t r = pread(tdb->fd, buf, len, off);
 		if (r != len) {
 		if (r != len) {
-			tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
-				   "tdb_read failed with %zi at %zu "
-				   "len=%zu (%s) map_size=%zu",
-				   r, (size_t)off, (size_t)len,
-				   strerror(errno),
-				   (size_t)tdb->map_size);
-			return -1;
+			return tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
+					  "tdb_read failed with %zi at %zu "
+					  "len=%zu (%s) map_size=%zu",
+					  r, (size_t)off, (size_t)len,
+					  strerror(errno),
+					  (size_t)tdb->map_size);
 		}
 		}
 	}
 	}
-	return 0;
+	return TDB_SUCCESS;
 }
 }
 
 
 int tdb_write_convert(struct tdb_context *tdb, tdb_off_t off,
 int tdb_write_convert(struct tdb_context *tdb, tdb_off_t off,
 		      const void *rec, size_t len)
 		      const void *rec, size_t len)
 {
 {
-	int ret;
+	enum TDB_ERROR ecode;
+
 	if (unlikely((tdb->flags & TDB_CONVERT))) {
 	if (unlikely((tdb->flags & TDB_CONVERT))) {
 		void *conv = malloc(len);
 		void *conv = malloc(len);
 		if (!conv) {
 		if (!conv) {
@@ -286,21 +295,30 @@ int tdb_write_convert(struct tdb_context *tdb, tdb_off_t off,
 			return -1;
 			return -1;
 		}
 		}
 		memcpy(conv, rec, len);
 		memcpy(conv, rec, len);
-		ret = tdb->methods->twrite(tdb, off,
+		ecode = tdb->methods->twrite(tdb, off,
 					   tdb_convert(tdb, conv, len), len);
 					   tdb_convert(tdb, conv, len), len);
 		free(conv);
 		free(conv);
-	} else
-		ret = tdb->methods->twrite(tdb, off, rec, len);
+	} else {
+		ecode = tdb->methods->twrite(tdb, off, rec, len);
+	}
 
 
-	return ret;
+	if (ecode != TDB_SUCCESS) {
+		tdb->ecode = ecode;
+		return -1;
+	}
+	return 0;
 }
 }
 
 
 int tdb_read_convert(struct tdb_context *tdb, tdb_off_t off,
 int tdb_read_convert(struct tdb_context *tdb, tdb_off_t off,
 		      void *rec, size_t len)
 		      void *rec, size_t len)
 {
 {
-	int ret = tdb->methods->tread(tdb, off, rec, len);
+	enum TDB_ERROR ecode = tdb->methods->tread(tdb, off, rec, len);
 	tdb_convert(tdb, rec, len);
 	tdb_convert(tdb, rec, len);
-	return ret;
+	if (ecode != TDB_SUCCESS) {
+		tdb->ecode = ecode;
+		return -1;
+	}
+	return 0;
 }
 }
 
 
 int tdb_write_off(struct tdb_context *tdb, tdb_off_t off, tdb_off_t val)
 int tdb_write_off(struct tdb_context *tdb, tdb_off_t off, tdb_off_t val)
@@ -326,6 +344,7 @@ static void *_tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset,
 			     tdb_len_t len, unsigned int prefix)
 			     tdb_len_t len, unsigned int prefix)
 {
 {
 	void *buf;
 	void *buf;
+	enum TDB_ERROR ecode;
 
 
 	/* some systems don't like zero length malloc */
 	/* some systems don't like zero length malloc */
 	buf = malloc(prefix + len ? prefix + len : 1);
 	buf = malloc(prefix + len ? prefix + len : 1);
@@ -333,10 +352,13 @@ static void *_tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset,
 		tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_USE_ERROR,
 		tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_USE_ERROR,
 			   "tdb_alloc_read malloc failed len=%zu",
 			   "tdb_alloc_read malloc failed len=%zu",
 			   (size_t)(prefix + len));
 			   (size_t)(prefix + len));
-	} else if (unlikely(tdb->methods->tread(tdb, offset, buf+prefix, len)
-			    == -1)) {
-		free(buf);
-		buf = NULL;
+	} else {
+		ecode = tdb->methods->tread(tdb, offset, buf+prefix, len);
+		if (unlikely(ecode != TDB_SUCCESS)) {
+			tdb->ecode = ecode;
+			free(buf);
+			buf = NULL;
+		}
 	}
 	}
 	return buf;
 	return buf;
 }
 }
@@ -372,22 +394,21 @@ static int fill(struct tdb_context *tdb,
 
 
 /* expand a file.  we prefer to use ftruncate, as that is what posix
 /* expand a file.  we prefer to use ftruncate, as that is what posix
   says to use for mmap expansion */
   says to use for mmap expansion */
-static int tdb_expand_file(struct tdb_context *tdb, tdb_len_t addition)
+static enum TDB_ERROR tdb_expand_file(struct tdb_context *tdb,
+				      tdb_len_t addition)
 {
 {
 	char buf[8192];
 	char buf[8192];
 
 
 	if (tdb->read_only) {
 	if (tdb->read_only) {
-		tdb_logerr(tdb, TDB_ERR_RDONLY, TDB_LOG_USE_ERROR,
-			   "Expand on read-only database");
-		return -1;
+		return tdb_logerr(tdb, TDB_ERR_RDONLY, TDB_LOG_USE_ERROR,
+				  "Expand on read-only database");
 	}
 	}
 
 
 	if (tdb->flags & TDB_INTERNAL) {
 	if (tdb->flags & TDB_INTERNAL) {
 		char *new = realloc(tdb->map_ptr, tdb->map_size + addition);
 		char *new = realloc(tdb->map_ptr, tdb->map_size + addition);
 		if (!new) {
 		if (!new) {
-			tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_ERROR,
-				   "No memory to expand database");
-			return -1;
+			return tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_ERROR,
+					  "No memory to expand database");
 		}
 		}
 		tdb->map_ptr = new;
 		tdb->map_ptr = new;
 		tdb->map_size += addition;
 		tdb->map_size += addition;
@@ -405,11 +426,11 @@ static int tdb_expand_file(struct tdb_context *tdb, tdb_len_t addition)
 		   disk. This must be done with write, not via mmap */
 		   disk. This must be done with write, not via mmap */
 		memset(buf, 0x43, sizeof(buf));
 		memset(buf, 0x43, sizeof(buf));
 		if (fill(tdb, buf, sizeof(buf), tdb->map_size, addition) == -1)
 		if (fill(tdb, buf, sizeof(buf), tdb->map_size, addition) == -1)
-			return -1;
+			return tdb->ecode;
 		tdb->map_size += addition;
 		tdb->map_size += addition;
 		tdb_mmap(tdb);
 		tdb_mmap(tdb);
 	}
 	}
-	return 0;
+	return TDB_SUCCESS;
 }
 }
 
 
 const void *tdb_access_read(struct tdb_context *tdb,
 const void *tdb_access_read(struct tdb_context *tdb,
@@ -517,7 +538,7 @@ static void *tdb_direct(struct tdb_context *tdb, tdb_off_t off, size_t len,
 	if (unlikely(!tdb->map_ptr))
 	if (unlikely(!tdb->map_ptr))
 		return NULL;
 		return NULL;
 
 
-	if (unlikely(tdb_oob(tdb, off + len, true) == -1))
+	if (unlikely(tdb_oob(tdb, off + len, true) != TDB_SUCCESS))
 		return NULL;
 		return NULL;
 	return (char *)tdb->map_ptr + off;
 	return (char *)tdb->map_ptr + off;
 }
 }

+ 6 - 4
ccan/tdb2/private.h

@@ -379,10 +379,12 @@ struct tdb_context {
 };
 };
 
 
 struct tdb_methods {
 struct tdb_methods {
-	int (*tread)(struct tdb_context *, tdb_off_t, void *, tdb_len_t);
-	int (*twrite)(struct tdb_context *, tdb_off_t, const void *, tdb_len_t);
-	int (*oob)(struct tdb_context *, tdb_off_t, bool);
-	int (*expand_file)(struct tdb_context *, tdb_len_t);
+	enum TDB_ERROR (*tread)(struct tdb_context *, tdb_off_t, void *,
+				tdb_len_t);
+	enum TDB_ERROR (*twrite)(struct tdb_context *, tdb_off_t, const void *,
+				 tdb_len_t);
+	enum TDB_ERROR (*oob)(struct tdb_context *, tdb_off_t, bool);
+	enum TDB_ERROR (*expand_file)(struct tdb_context *, tdb_len_t);
 	void *(*direct)(struct tdb_context *, tdb_off_t, size_t, bool);
 	void *(*direct)(struct tdb_context *, tdb_off_t, size_t, bool);
 };
 };
 
 

+ 28 - 9
ccan/tdb2/tdb.c

@@ -429,6 +429,7 @@ static int replace_data(struct tdb_context *tdb,
 			bool growing)
 			bool growing)
 {
 {
 	tdb_off_t new_off;
 	tdb_off_t new_off;
+	enum TDB_ERROR ecode;
 
 
 	/* Allocate a new record. */
 	/* Allocate a new record. */
 	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,
@@ -450,12 +451,18 @@ static int replace_data(struct tdb_context *tdb,
 	}
 	}
 
 
 	new_off += sizeof(struct tdb_used_record);
 	new_off += sizeof(struct tdb_used_record);
-	if (tdb->methods->twrite(tdb, new_off, key.dptr, key.dsize) == -1)
+	ecode = tdb->methods->twrite(tdb, new_off, key.dptr, key.dsize);
+	if (ecode != TDB_SUCCESS) {
+		tdb->ecode = ecode;
 		return -1;
 		return -1;
+	}
 
 
 	new_off += key.dsize;
 	new_off += key.dsize;
-	if (tdb->methods->twrite(tdb, new_off, dbuf.dptr, dbuf.dsize) == -1)
+	ecode = tdb->methods->twrite(tdb, new_off, dbuf.dptr, dbuf.dsize);
+	if (ecode != TDB_SUCCESS) {
+		tdb->ecode = ecode;
 		return -1;
 		return -1;
+	}
 
 
 	/* FIXME: tdb_increment_seqnum(tdb); */
 	/* FIXME: tdb_increment_seqnum(tdb); */
 	return 0;
 	return 0;
@@ -469,6 +476,7 @@ int tdb_store(struct tdb_context *tdb,
 	tdb_len_t old_room = 0;
 	tdb_len_t old_room = 0;
 	struct tdb_used_record rec;
 	struct tdb_used_record rec;
 	int ret;
 	int ret;
+	enum TDB_ERROR ecode;
 
 
 	off = find_and_lock(tdb, key, F_WRLCK, &h, &rec, NULL);
 	off = find_and_lock(tdb, key, F_WRLCK, &h, &rec, NULL);
 	if (unlikely(off == TDB_OFF_ERR))
 	if (unlikely(off == TDB_OFF_ERR))
@@ -490,10 +498,15 @@ int tdb_store(struct tdb_context *tdb,
 						   key.dsize, dbuf.dsize,
 						   key.dsize, dbuf.dsize,
 						   &rec, h.h))
 						   &rec, h.h))
 					goto fail;
 					goto fail;
-				if (tdb->methods->twrite(tdb, off + sizeof(rec)
-							 + key.dsize,
-							 dbuf.dptr, dbuf.dsize))
+				ecode = tdb->methods->twrite(tdb,
+							     off + sizeof(rec)
+							     + key.dsize,
+							     dbuf.dptr,
+							     dbuf.dsize);
+				if (ecode != TDB_SUCCESS) {
+					tdb->ecode = ecode;
 					goto fail;
 					goto fail;
+				}
 				tdb_unlock_hashes(tdb, h.hlock_start,
 				tdb_unlock_hashes(tdb, h.hlock_start,
 						  h.hlock_range, F_WRLCK);
 						  h.hlock_range, F_WRLCK);
 				return 0;
 				return 0;
@@ -528,6 +541,7 @@ int tdb_append(struct tdb_context *tdb,
 	tdb_len_t old_room = 0, old_dlen;
 	tdb_len_t old_room = 0, old_dlen;
 	unsigned char *newdata;
 	unsigned char *newdata;
 	struct tdb_data new_dbuf;
 	struct tdb_data new_dbuf;
+	enum TDB_ERROR ecode;
 	int ret;
 	int ret;
 
 
 	off = find_and_lock(tdb, key, F_WRLCK, &h, &rec, NULL);
 	off = find_and_lock(tdb, key, F_WRLCK, &h, &rec, NULL);
@@ -545,9 +559,12 @@ int tdb_append(struct tdb_context *tdb,
 				goto fail;
 				goto fail;
 
 
 			off += sizeof(rec) + key.dsize + old_dlen;
 			off += sizeof(rec) + key.dsize + old_dlen;
-			if (tdb->methods->twrite(tdb, off, dbuf.dptr,
-						 dbuf.dsize) == -1)
+			ecode = tdb->methods->twrite(tdb, off, dbuf.dptr,
+						     dbuf.dsize);
+			if (ecode != TDB_SUCCESS) {
+				tdb->ecode = ecode;
 				goto fail;
 				goto fail;
+			}
 
 
 			/* FIXME: tdb_increment_seqnum(tdb); */
 			/* FIXME: tdb_increment_seqnum(tdb); */
 			tdb_unlock_hashes(tdb, h.hlock_start, h.hlock_range,
 			tdb_unlock_hashes(tdb, h.hlock_start, h.hlock_range,
@@ -563,8 +580,10 @@ int tdb_append(struct tdb_context *tdb,
 				   (size_t)(key.dsize+old_dlen+dbuf.dsize));
 				   (size_t)(key.dsize+old_dlen+dbuf.dsize));
 			goto fail;
 			goto fail;
 		}
 		}
-		if (tdb->methods->tread(tdb, off + sizeof(rec) + key.dsize,
-					newdata, old_dlen) != 0) {
+		ecode = tdb->methods->tread(tdb, off + sizeof(rec) + key.dsize,
+					    newdata, old_dlen);
+		if (ecode != TDB_SUCCESS) {
+			tdb->ecode = ecode;
 			free(newdata);
 			free(newdata);
 			goto fail;
 			goto fail;
 		}
 		}

+ 130 - 89
ccan/tdb2/transaction.c

@@ -125,16 +125,18 @@ struct tdb_transaction {
   read while in a transaction. We need to check first if the data is in our list
   read while in a transaction. We need to check first if the data is in our list
   of transaction elements, then if not do a real read
   of transaction elements, then if not do a real read
 */
 */
-static int transaction_read(struct tdb_context *tdb, tdb_off_t off, void *buf,
-			    tdb_len_t len)
+static enum TDB_ERROR transaction_read(struct tdb_context *tdb, tdb_off_t off,
+				       void *buf, tdb_len_t len)
 {
 {
 	size_t blk;
 	size_t blk;
+	enum TDB_ERROR ecode;
 
 
 	/* break it down into block sized ops */
 	/* break it down into block sized ops */
 	while (len + (off % getpagesize()) > getpagesize()) {
 	while (len + (off % getpagesize()) > getpagesize()) {
 		tdb_len_t len2 = getpagesize() - (off % getpagesize());
 		tdb_len_t len2 = getpagesize() - (off % getpagesize());
-		if (transaction_read(tdb, off, buf, len2) != 0) {
-			return -1;
+		ecode = transaction_read(tdb, off, buf, len2);
+		if (ecode != TDB_SUCCESS) {
+			return ecode;
 		}
 		}
 		len -= len2;
 		len -= len2;
 		off += len2;
 		off += len2;
@@ -142,7 +144,7 @@ static int transaction_read(struct tdb_context *tdb, tdb_off_t off, void *buf,
 	}
 	}
 
 
 	if (len == 0) {
 	if (len == 0) {
-		return 0;
+		return TDB_SUCCESS;
 	}
 	}
 
 
 	blk = off / getpagesize();
 	blk = off / getpagesize();
@@ -151,8 +153,8 @@ static int transaction_read(struct tdb_context *tdb, tdb_off_t off, void *buf,
 	if (tdb->transaction->num_blocks <= blk ||
 	if (tdb->transaction->num_blocks <= blk ||
 	    tdb->transaction->blocks[blk] == NULL) {
 	    tdb->transaction->blocks[blk] == NULL) {
 		/* nope, do a real read */
 		/* nope, do a real read */
-		if (tdb->transaction->io_methods->tread(tdb, off, buf, len)
-		    != 0) {
+		ecode = tdb->transaction->io_methods->tread(tdb, off, buf, len);
+		if (ecode != TDB_SUCCESS) {
 			goto fail;
 			goto fail;
 		}
 		}
 		return 0;
 		return 0;
@@ -161,43 +163,45 @@ static int transaction_read(struct tdb_context *tdb, tdb_off_t off, void *buf,
 	/* it is in the block list. Now check for the last block */
 	/* it is in the block list. Now check for the last block */
 	if (blk == tdb->transaction->num_blocks-1) {
 	if (blk == tdb->transaction->num_blocks-1) {
 		if (len > tdb->transaction->last_block_size) {
 		if (len > tdb->transaction->last_block_size) {
+			ecode = TDB_ERR_IO;
 			goto fail;
 			goto fail;
 		}
 		}
 	}
 	}
 
 
 	/* now copy it out of this block */
 	/* now copy it out of this block */
 	memcpy(buf, tdb->transaction->blocks[blk] + (off % getpagesize()), len);
 	memcpy(buf, tdb->transaction->blocks[blk] + (off % getpagesize()), len);
-	return 0;
+	return TDB_SUCCESS;
 
 
 fail:
 fail:
-	tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
-		   "transaction_read: failed at off=%zu len=%zu",
-		   (size_t)off, (size_t)len);
 	tdb->transaction->transaction_error = 1;
 	tdb->transaction->transaction_error = 1;
-	return -1;
+	return tdb_logerr(tdb, ecode, TDB_LOG_ERROR,
+			  "transaction_read: failed at off=%zu len=%zu",
+			  (size_t)off, (size_t)len);
 }
 }
 
 
 
 
 /*
 /*
   write while in a transaction
   write while in a transaction
 */
 */
-static int transaction_write(struct tdb_context *tdb, tdb_off_t off,
-			     const void *buf, tdb_len_t len)
+static enum TDB_ERROR transaction_write(struct tdb_context *tdb, tdb_off_t off,
+					const void *buf, tdb_len_t len)
 {
 {
 	size_t blk;
 	size_t blk;
+	enum TDB_ERROR ecode;
 
 
 	/* Only a commit is allowed on a prepared transaction */
 	/* Only a commit is allowed on a prepared transaction */
 	if (tdb->transaction->prepared) {
 	if (tdb->transaction->prepared) {
-		tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_ERROR,
-			 "transaction_write: transaction already prepared,"
-			 " write not allowed");
+		ecode = tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_ERROR,
+				   "transaction_write: transaction already"
+				   " prepared, write not allowed");
 		goto fail;
 		goto fail;
 	}
 	}
 
 
 	/* break it up into block sized chunks */
 	/* break it up into block sized chunks */
 	while (len + (off % getpagesize()) > getpagesize()) {
 	while (len + (off % getpagesize()) > getpagesize()) {
 		tdb_len_t len2 = getpagesize() - (off % getpagesize());
 		tdb_len_t len2 = getpagesize() - (off % getpagesize());
-		if (transaction_write(tdb, off, buf, len2) != 0) {
+		ecode = transaction_write(tdb, off, buf, len2);
+		if (ecode != TDB_SUCCESS) {
 			return -1;
 			return -1;
 		}
 		}
 		len -= len2;
 		len -= len2;
@@ -208,7 +212,7 @@ static int transaction_write(struct tdb_context *tdb, tdb_off_t off,
 	}
 	}
 
 
 	if (len == 0) {
 	if (len == 0) {
-		return 0;
+		return TDB_SUCCESS;
 	}
 	}
 
 
 	blk = off / getpagesize();
 	blk = off / getpagesize();
@@ -226,8 +230,9 @@ static int transaction_write(struct tdb_context *tdb, tdb_off_t off,
 				(blk+1)*sizeof(uint8_t *));
 				(blk+1)*sizeof(uint8_t *));
 		}
 		}
 		if (new_blocks == NULL) {
 		if (new_blocks == NULL) {
-			tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_ERROR,
-				   "transaction_write: failed to allocate");
+			ecode = tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_ERROR,
+					   "transaction_write:"
+					   " failed to allocate");
 			goto fail;
 			goto fail;
 		}
 		}
 		memset(&new_blocks[tdb->transaction->num_blocks], 0,
 		memset(&new_blocks[tdb->transaction->num_blocks], 0,
@@ -241,8 +246,9 @@ static int transaction_write(struct tdb_context *tdb, tdb_off_t off,
 	if (tdb->transaction->blocks[blk] == NULL) {
 	if (tdb->transaction->blocks[blk] == NULL) {
 		tdb->transaction->blocks[blk] = (uint8_t *)calloc(getpagesize(), 1);
 		tdb->transaction->blocks[blk] = (uint8_t *)calloc(getpagesize(), 1);
 		if (tdb->transaction->blocks[blk] == NULL) {
 		if (tdb->transaction->blocks[blk] == NULL) {
-			tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_ERROR,
-				   "transaction_write: failed to allocate");
+			ecode = tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_ERROR,
+					   "transaction_write:"
+					   " failed to allocate");
 			goto fail;
 			goto fail;
 		}
 		}
 		if (tdb->transaction->old_map_size > blk * getpagesize()) {
 		if (tdb->transaction->old_map_size > blk * getpagesize()) {
@@ -250,13 +256,17 @@ static int transaction_write(struct tdb_context *tdb, tdb_off_t off,
 			if (len2 + (blk * getpagesize()) > tdb->transaction->old_map_size) {
 			if (len2 + (blk * getpagesize()) > tdb->transaction->old_map_size) {
 				len2 = tdb->transaction->old_map_size - (blk * getpagesize());
 				len2 = tdb->transaction->old_map_size - (blk * getpagesize());
 			}
 			}
-			if (tdb->transaction->io_methods->tread(tdb, blk * getpagesize(),
-								tdb->transaction->blocks[blk],
-								len2) != 0) {
-				tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_ERROR,
-					   "transaction_write: failed to"
-					   " read old block: %s",
-					   strerror(errno));
+			ecode = tdb->transaction->io_methods->tread(tdb,
+					blk * getpagesize(),
+					tdb->transaction->blocks[blk],
+					len2);
+			if (ecode != TDB_SUCCESS) {
+				ecode = tdb_logerr(tdb, ecode,
+						   TDB_LOG_ERROR,
+						   "transaction_write:"
+						   " failed to"
+						   " read old block: %s",
+						   strerror(errno));
 				SAFE_FREE(tdb->transaction->blocks[blk]);
 				SAFE_FREE(tdb->transaction->blocks[blk]);
 				goto fail;
 				goto fail;
 			}
 			}
@@ -278,11 +288,11 @@ static int transaction_write(struct tdb_context *tdb, tdb_off_t off,
 		}
 		}
 	}
 	}
 
 
-	return 0;
+	return TDB_SUCCESS;
 
 
 fail:
 fail:
 	tdb->transaction->transaction_error = 1;
 	tdb->transaction->transaction_error = 1;
-	return -1;
+	return ecode;
 }
 }
 
 
 
 
@@ -334,33 +344,38 @@ static void transaction_write_existing(struct tdb_context *tdb, tdb_off_t off,
 /*
 /*
   out of bounds check during a transaction
   out of bounds check during a transaction
 */
 */
-static int transaction_oob(struct tdb_context *tdb, tdb_off_t len, bool probe)
+static enum TDB_ERROR transaction_oob(struct tdb_context *tdb, tdb_off_t len,
+				      bool probe)
 {
 {
 	if (len <= tdb->map_size) {
 	if (len <= tdb->map_size) {
-		return 0;
+		return TDB_SUCCESS;
 	}
 	}
-	tdb->ecode = TDB_ERR_IO;
 	if (!probe) {
 	if (!probe) {
 		tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
 		tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
 			   "tdb_oob len %lld beyond transaction size %lld",
 			   "tdb_oob len %lld beyond transaction size %lld",
 			   (long long)len,
 			   (long long)len,
 			   (long long)tdb->map_size);
 			   (long long)tdb->map_size);
 	}
 	}
-	return -1;
+	return TDB_ERR_IO;
 }
 }
 
 
 /*
 /*
   transaction version of tdb_expand().
   transaction version of tdb_expand().
 */
 */
-static int transaction_expand_file(struct tdb_context *tdb, tdb_off_t addition)
+static enum TDB_ERROR transaction_expand_file(struct tdb_context *tdb,
+					      tdb_off_t addition)
 {
 {
+	enum TDB_ERROR ecode;
+
 	/* add a write to the transaction elements, so subsequent
 	/* add a write to the transaction elements, so subsequent
 	   reads see the zero data */
 	   reads see the zero data */
-	if (transaction_write(tdb, tdb->map_size, NULL, addition) != 0) {
-		return -1;
+	ecode = transaction_write(tdb, tdb->map_size, NULL, addition);
+	if (ecode != TDB_SUCCESS) {
+		tdb->ecode = ecode;
+		return ecode;
 	}
 	}
 	tdb->map_size += addition;
 	tdb->map_size += addition;
-	return 0;
+	return ecode;
 }
 }
 
 
 static void *transaction_direct(struct tdb_context *tdb, tdb_off_t off,
 static void *transaction_direct(struct tdb_context *tdb, tdb_off_t off,
@@ -410,37 +425,37 @@ static const struct tdb_methods transaction_methods = {
 /*
 /*
   sync to disk
   sync to disk
 */
 */
-static int transaction_sync(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t length)
+static enum TDB_ERROR transaction_sync(struct tdb_context *tdb,
+				       tdb_off_t offset, tdb_len_t length)
 {
 {
 	if (tdb->flags & TDB_NOSYNC) {
 	if (tdb->flags & TDB_NOSYNC) {
-		return 0;
+		return TDB_SUCCESS;
 	}
 	}
 
 
 	if (fsync(tdb->fd) != 0) {
 	if (fsync(tdb->fd) != 0) {
-		tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
-			   "tdb_transaction: fsync failed: %s",
-			   strerror(errno));
-		return -1;
+		return tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
+				  "tdb_transaction: fsync failed: %s",
+				  strerror(errno));
 	}
 	}
 #ifdef MS_SYNC
 #ifdef MS_SYNC
 	if (tdb->map_ptr) {
 	if (tdb->map_ptr) {
 		tdb_off_t moffset = offset & ~(getpagesize()-1);
 		tdb_off_t moffset = offset & ~(getpagesize()-1);
 		if (msync(moffset + (char *)tdb->map_ptr,
 		if (msync(moffset + (char *)tdb->map_ptr,
 			  length + (offset - moffset), MS_SYNC) != 0) {
 			  length + (offset - moffset), MS_SYNC) != 0) {
-			tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
-				   "tdb_transaction: msync failed: %s",
-				   strerror(errno));
-			return -1;
+			return tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
+					  "tdb_transaction: msync failed: %s",
+					  strerror(errno));
 		}
 		}
 	}
 	}
 #endif
 #endif
-	return 0;
+	return TDB_SUCCESS;
 }
 }
 
 
 
 
 static void _tdb_transaction_cancel(struct tdb_context *tdb)
 static void _tdb_transaction_cancel(struct tdb_context *tdb)
 {
 {
 	int i;
 	int i;
+	enum TDB_ERROR ecode;
 
 
 	if (tdb->transaction == NULL) {
 	if (tdb->transaction == NULL) {
 		tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR,
 		tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR,
@@ -469,11 +484,14 @@ static void _tdb_transaction_cancel(struct tdb_context *tdb)
 		uint64_t invalid = TDB_RECOVERY_INVALID_MAGIC;
 		uint64_t invalid = TDB_RECOVERY_INVALID_MAGIC;
 
 
 		/* remove the recovery marker */
 		/* remove the recovery marker */
-		if (methods->twrite(tdb, tdb->transaction->magic_offset,
-				    &invalid, sizeof(invalid)) == -1 ||
-		    transaction_sync(tdb, tdb->transaction->magic_offset,
-				     sizeof(invalid)) == -1) {
-			tdb_logerr(tdb, tdb->ecode, TDB_LOG_ERROR,
+		ecode = methods->twrite(tdb, tdb->transaction->magic_offset,
+					&invalid, sizeof(invalid));
+		if (ecode == TDB_SUCCESS)
+			ecode = transaction_sync(tdb,
+						 tdb->transaction->magic_offset,
+						 sizeof(invalid));
+		if (ecode != TDB_SUCCESS) {
+			tdb_logerr(tdb, ecode, TDB_LOG_ERROR,
 				   "tdb_transaction_cancel: failed to remove"
 				   "tdb_transaction_cancel: failed to remove"
 				   " recovery magic");
 				   " recovery magic");
 		}
 		}
@@ -621,6 +639,7 @@ static int tdb_recovery_allocate(struct tdb_context *tdb,
 	const struct tdb_methods *methods = tdb->transaction->io_methods;
 	const struct tdb_methods *methods = tdb->transaction->io_methods;
 	tdb_off_t recovery_head;
 	tdb_off_t recovery_head;
 	size_t addition;
 	size_t addition;
+	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) {
 	if (recovery_head == TDB_OFF_ERR) {
@@ -631,8 +650,9 @@ static int tdb_recovery_allocate(struct tdb_context *tdb,
 	}
 	}
 
 
 	if (recovery_head != 0) {
 	if (recovery_head != 0) {
-		if (methods->tread(tdb, recovery_head, &rec, sizeof(rec))) {
-			tdb_logerr(tdb, tdb->ecode, TDB_LOG_ERROR,
+		ecode = methods->tread(tdb, recovery_head, &rec, sizeof(rec));
+		if (ecode != TDB_SUCCESS) {
+			tdb_logerr(tdb, ecode, TDB_LOG_ERROR,
 				 "tdb_recovery_allocate:"
 				 "tdb_recovery_allocate:"
 				 " failed to read recovery record");
 				 " failed to read recovery record");
 			return -1;
 			return -1;
@@ -688,8 +708,9 @@ static int tdb_recovery_allocate(struct tdb_context *tdb,
 	addition = (tdb->map_size - tdb->transaction->old_map_size) +
 	addition = (tdb->map_size - tdb->transaction->old_map_size) +
 		sizeof(rec) + *recovery_max_size;
 		sizeof(rec) + *recovery_max_size;
 	tdb->map_size = tdb->transaction->old_map_size;
 	tdb->map_size = tdb->transaction->old_map_size;
-	if (methods->expand_file(tdb, addition) == -1) {
-		tdb_logerr(tdb, tdb->ecode, TDB_LOG_ERROR,
+	ecode = methods->expand_file(tdb, addition);
+	if (ecode != TDB_SUCCESS) {
+		tdb_logerr(tdb, ecode, TDB_LOG_ERROR,
 			 "tdb_recovery_allocate:"
 			 "tdb_recovery_allocate:"
 			 " failed to create recovery area");
 			 " failed to create recovery area");
 		return -1;
 		return -1;
@@ -703,9 +724,10 @@ static int tdb_recovery_allocate(struct tdb_context *tdb,
 	/* write the recovery header offset and sync - we can sync without a race here
 	/* write the recovery header offset and sync - we can sync without a race here
 	   as the magic ptr in the recovery record has not been set */
 	   as the magic ptr in the recovery record has not been set */
 	tdb_convert(tdb, &recovery_head, sizeof(recovery_head));
 	tdb_convert(tdb, &recovery_head, sizeof(recovery_head));
-	if (methods->twrite(tdb, offsetof(struct tdb_header, recovery),
-			    &recovery_head, sizeof(tdb_off_t)) == -1) {
-		tdb_logerr(tdb, tdb->ecode, TDB_LOG_ERROR,
+	ecode = methods->twrite(tdb, offsetof(struct tdb_header, recovery),
+				&recovery_head, sizeof(tdb_off_t));
+	if (ecode != TDB_SUCCESS) {
+		tdb_logerr(tdb, ecode, TDB_LOG_ERROR,
 			 "tdb_recovery_allocate:"
 			 "tdb_recovery_allocate:"
 			 " failed to write recovery head");
 			 " failed to write recovery head");
 		return -1;
 		return -1;
@@ -742,6 +764,7 @@ static int transaction_setup_recovery(struct tdb_context *tdb,
 	tdb_off_t old_map_size = tdb->transaction->old_map_size;
 	tdb_off_t old_map_size = tdb->transaction->old_map_size;
 	uint64_t magic, tailer;
 	uint64_t magic, tailer;
 	int i;
 	int i;
+	enum TDB_ERROR ecode;
 
 
 	/*
 	/*
 	  check that the recovery area has enough space
 	  check that the recovery area has enough space
@@ -797,9 +820,11 @@ static int transaction_setup_recovery(struct tdb_context *tdb,
 		/* the recovery area contains the old data, not the
 		/* the recovery area contains the old data, not the
 		   new data, so we have to call the original tdb_read
 		   new data, so we have to call the original tdb_read
 		   method to get it */
 		   method to get it */
-		if (methods->tread(tdb, offset,
-				   p + sizeof(offset) + sizeof(length),
-				   length) != 0) {
+		ecode = methods->tread(tdb, offset,
+				       p + sizeof(offset) + sizeof(length),
+				       length);
+		if (ecode != TDB_SUCCESS) {
+			tdb->ecode = ecode;
 			free(data);
 			free(data);
 			return -1;
 			return -1;
 		}
 		}
@@ -812,9 +837,10 @@ static int transaction_setup_recovery(struct tdb_context *tdb,
 	tdb_convert(tdb, p, sizeof(tailer));
 	tdb_convert(tdb, p, sizeof(tailer));
 
 
 	/* write the recovery data to the recovery area */
 	/* write the recovery data to the recovery area */
-	if (methods->twrite(tdb, recovery_offset, data,
-			    sizeof(*rec) + recovery_size) == -1) {
-		tdb_logerr(tdb, tdb->ecode, TDB_LOG_ERROR,
+	ecode = methods->twrite(tdb, recovery_offset, data,
+				sizeof(*rec) + recovery_size);
+	if (ecode != TDB_SUCCESS) {
+		tdb_logerr(tdb, ecode, TDB_LOG_ERROR,
 			 "tdb_transaction_setup_recovery:"
 			 "tdb_transaction_setup_recovery:"
 			 " failed to write recovery data");
 			 " failed to write recovery data");
 		free(data);
 		free(data);
@@ -826,9 +852,11 @@ static int transaction_setup_recovery(struct tdb_context *tdb,
 	/* as we don't have ordered writes, we have to sync the recovery
 	/* as we don't have ordered writes, we have to sync the recovery
 	   data before we update the magic to indicate that the recovery
 	   data before we update the magic to indicate that the recovery
 	   data is present */
 	   data is present */
-	if (transaction_sync(tdb, recovery_offset,
-			     sizeof(*rec) + recovery_size) == -1) {
+	ecode = transaction_sync(tdb, recovery_offset,
+				 sizeof(*rec) + recovery_size);
+	if (ecode != TDB_SUCCESS) {
 		free(data);
 		free(data);
+		tdb->ecode = ecode;
 		return -1;
 		return -1;
 	}
 	}
 
 
@@ -840,8 +868,9 @@ static int transaction_setup_recovery(struct tdb_context *tdb,
 	*magic_offset = recovery_offset + offsetof(struct tdb_recovery_record,
 	*magic_offset = recovery_offset + offsetof(struct tdb_recovery_record,
 						   magic);
 						   magic);
 
 
-	if (methods->twrite(tdb, *magic_offset, &magic, sizeof(magic)) == -1) {
-		tdb_logerr(tdb, tdb->ecode, TDB_LOG_ERROR,
+	ecode = methods->twrite(tdb, *magic_offset, &magic, sizeof(magic));
+	if (ecode != TDB_SUCCESS) {
+		tdb_logerr(tdb, ecode, TDB_LOG_ERROR,
 			 "tdb_transaction_setup_recovery:"
 			 "tdb_transaction_setup_recovery:"
 			 " failed to write recovery magic");
 			 " failed to write recovery magic");
 		return -1;
 		return -1;
@@ -849,7 +878,9 @@ static int transaction_setup_recovery(struct tdb_context *tdb,
 	transaction_write_existing(tdb, *magic_offset, &magic, sizeof(magic));
 	transaction_write_existing(tdb, *magic_offset, &magic, sizeof(magic));
 
 
 	/* ensure the recovery magic marker is on disk */
 	/* ensure the recovery magic marker is on disk */
-	if (transaction_sync(tdb, *magic_offset, sizeof(magic)) == -1) {
+	ecode = transaction_sync(tdb, *magic_offset, sizeof(magic));
+	if (ecode != TDB_SUCCESS) {
+		tdb->ecode = ecode;
 		return -1;
 		return -1;
 	}
 	}
 
 
@@ -936,8 +967,9 @@ static int _tdb_transaction_prepare_commit(struct tdb_context *tdb)
 		tdb_len_t add = tdb->map_size - tdb->transaction->old_map_size;
 		tdb_len_t add = tdb->map_size - tdb->transaction->old_map_size;
 		/* Restore original map size for tdb_expand_file */
 		/* Restore original map size for tdb_expand_file */
 		tdb->map_size = tdb->transaction->old_map_size;
 		tdb->map_size = tdb->transaction->old_map_size;
-		if (methods->expand_file(tdb, add) == -1) {
-			tdb_logerr(tdb, tdb->ecode, TDB_LOG_ERROR,
+		ecode = methods->expand_file(tdb, add);
+		if (ecode != TDB_SUCCESS) {
+			tdb_logerr(tdb, ecode, TDB_LOG_ERROR,
 				 "tdb_transaction_prepare_commit:"
 				 "tdb_transaction_prepare_commit:"
 				 " expansion failed");
 				 " expansion failed");
 			_tdb_transaction_cancel(tdb);
 			_tdb_transaction_cancel(tdb);
@@ -965,6 +997,7 @@ int tdb_transaction_commit(struct tdb_context *tdb)
 {
 {
 	const struct tdb_methods *methods;
 	const struct tdb_methods *methods;
 	int i;
 	int i;
+	enum TDB_ERROR ecode;
 
 
 	if (tdb->transaction == NULL) {
 	if (tdb->transaction == NULL) {
 		tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR,
 		tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR,
@@ -1008,9 +1041,10 @@ int tdb_transaction_commit(struct tdb_context *tdb)
 			length = tdb->transaction->last_block_size;
 			length = tdb->transaction->last_block_size;
 		}
 		}
 
 
-		if (methods->twrite(tdb, offset, tdb->transaction->blocks[i],
-				    length) == -1) {
-			tdb_logerr(tdb, tdb->ecode, TDB_LOG_ERROR,
+		ecode = methods->twrite(tdb, offset,
+					tdb->transaction->blocks[i], length);
+		if (ecode != TDB_SUCCESS) {
+			tdb_logerr(tdb, ecode, TDB_LOG_ERROR,
 				   "tdb_transaction_commit:"
 				   "tdb_transaction_commit:"
 				   " write failed during commit");
 				   " write failed during commit");
 
 
@@ -1031,7 +1065,9 @@ int tdb_transaction_commit(struct tdb_context *tdb)
 	tdb->transaction->num_blocks = 0;
 	tdb->transaction->num_blocks = 0;
 
 
 	/* ensure the new data is on disk */
 	/* ensure the new data is on disk */
-	if (transaction_sync(tdb, 0, tdb->map_size) == -1) {
+	ecode = transaction_sync(tdb, 0, tdb->map_size);
+	if (ecode != TDB_SUCCESS) {
+		tdb->ecode = ecode;
 		return -1;
 		return -1;
 	}
 	}
 
 
@@ -1068,6 +1104,7 @@ int tdb_transaction_recover(struct tdb_context *tdb)
 	tdb_off_t recovery_head, recovery_eof;
 	tdb_off_t recovery_head, recovery_eof;
 	unsigned char *data, *p;
 	unsigned char *data, *p;
 	struct tdb_recovery_record rec;
 	struct tdb_recovery_record rec;
+	enum TDB_ERROR ecode;
 
 
 	/* 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));
@@ -1114,9 +1151,10 @@ int tdb_transaction_recover(struct tdb_context *tdb)
 	}
 	}
 
 
 	/* read the full recovery data */
 	/* read the full recovery data */
-	if (tdb->methods->tread(tdb, recovery_head + sizeof(rec), data,
-				rec.len) == -1) {
-		tdb_logerr(tdb, tdb->ecode, TDB_LOG_ERROR,
+	ecode = tdb->methods->tread(tdb, recovery_head + sizeof(rec), data,
+				    rec.len);
+	if (ecode != TDB_SUCCESS) {
+		tdb_logerr(tdb, ecode, TDB_LOG_ERROR,
 			   "tdb_transaction_recover:"
 			   "tdb_transaction_recover:"
 			   " failed to read recovery data");
 			   " failed to read recovery data");
 		return -1;
 		return -1;
@@ -1132,9 +1170,10 @@ int tdb_transaction_recover(struct tdb_context *tdb)
 		memcpy(&len, p + sizeof(ofs), sizeof(len));
 		memcpy(&len, p + sizeof(ofs), sizeof(len));
 		p += sizeof(ofs) + sizeof(len);
 		p += sizeof(ofs) + sizeof(len);
 
 
-		if (tdb->methods->twrite(tdb, ofs, p, len) == -1) {
+		ecode = tdb->methods->twrite(tdb, ofs, p, len);
+		if (ecode != TDB_SUCCESS) {
 			free(data);
 			free(data);
-			tdb_logerr(tdb, tdb->ecode, TDB_LOG_ERROR,
+			tdb_logerr(tdb, ecode, TDB_LOG_ERROR,
 				 "tdb_transaction_recover:"
 				 "tdb_transaction_recover:"
 				 " failed to recover %zu bytes at offset %zu",
 				 " failed to recover %zu bytes at offset %zu",
 				 (size_t)len, (size_t)ofs);
 				 (size_t)len, (size_t)ofs);
@@ -1145,8 +1184,9 @@ int tdb_transaction_recover(struct tdb_context *tdb)
 
 
 	free(data);
 	free(data);
 
 
-	if (transaction_sync(tdb, 0, tdb->map_size) == -1) {
-		tdb_logerr(tdb, tdb->ecode, TDB_LOG_ERROR,
+	ecode = transaction_sync(tdb, 0, tdb->map_size);
+	if (ecode != TDB_SUCCESS) {
+		tdb_logerr(tdb, ecode, TDB_LOG_ERROR,
 			   "tdb_transaction_recover: failed to sync recovery");
 			   "tdb_transaction_recover: failed to sync recovery");
 		return -1;
 		return -1;
 	}
 	}
@@ -1173,8 +1213,9 @@ int tdb_transaction_recover(struct tdb_context *tdb)
 		return -1;
 		return -1;
 	}
 	}
 
 
-	if (transaction_sync(tdb, 0, recovery_eof) == -1) {
-		tdb_logerr(tdb, tdb->ecode, TDB_LOG_ERROR,
+	ecode = transaction_sync(tdb, 0, recovery_eof);
+	if (ecode != TDB_SUCCESS) {
+		tdb_logerr(tdb, ecode, TDB_LOG_ERROR,
 			 "tdb_transaction_recover: failed to sync2 recovery");
 			 "tdb_transaction_recover: failed to sync2 recovery");
 		return -1;
 		return -1;
 	}
 	}