From: Rusty Russell Date: Tue, 1 Mar 2011 12:49:19 +0000 (+1030) Subject: tdb2: rework some io.c functions to return enum TDB_ERROR. X-Git-Url: http://git.ozlabs.org/?p=ccan;a=commitdiff_plain;h=7d6312518bd3a8e4cbad69b1f6b1800f7bcdf68c tdb2: rework some io.c functions to return enum TDB_ERROR. --- diff --git a/ccan/tdb2/check.c b/ccan/tdb2/check.c index 54e5bb1c..2b7576e6 100644 --- a/ccan/tdb2/check.c +++ b/ccan/tdb2/check.c @@ -34,9 +34,13 @@ static bool check_header(struct tdb_context *tdb, tdb_off_t *recovery) { uint64_t hash_test; struct tdb_header hdr; + enum TDB_ERROR ecode; - if (tdb_read_convert(tdb, 0, &hdr, sizeof(hdr)) == -1) + ecode = tdb_read_convert(tdb, 0, &hdr, sizeof(hdr)); + if (ecode != TDB_SUCCESS) { + tdb->ecode = ecode; return false; + } /* magic food should not be converted, so convert back. */ tdb_convert(tdb, hdr.magic_food, sizeof(hdr.magic_food)); @@ -91,9 +95,13 @@ static bool check_hash_chain(struct tdb_context *tdb, void *private_data) { struct tdb_used_record rec; + enum TDB_ERROR ecode; - if (tdb_read_convert(tdb, off, &rec, sizeof(rec)) == -1) + ecode = tdb_read_convert(tdb, off, &rec, sizeof(rec)); + if (ecode != TDB_SUCCESS) { + tdb->ecode = ecode; return false; + } if (rec_magic(&rec) != TDB_CHAIN_MAGIC) { tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR, @@ -148,13 +156,17 @@ static bool check_hash_record(struct tdb_context *tdb, void *private_data) { struct tdb_used_record rec; + enum TDB_ERROR ecode; if (hprefix_bits >= 64) return check_hash_chain(tdb, off, hprefix, used, num_used, num_found, check, private_data); - if (tdb_read_convert(tdb, off, &rec, sizeof(rec)) == -1) + ecode = tdb_read_convert(tdb, off, &rec, sizeof(rec)); + if (ecode != TDB_SUCCESS) { + tdb->ecode = ecode; return false; + } if (rec_magic(&rec) != TDB_HTABLE_MAGIC) { tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR, @@ -219,6 +231,7 @@ static bool check_hash_tree(struct tdb_context *tdb, unsigned int g, b; const tdb_off_t *hash; struct tdb_used_record rec; + enum TDB_ERROR ecode; hash = tdb_access_read(tdb, off, sizeof(tdb_off_t) @@ -269,9 +282,12 @@ static bool check_hash_tree(struct tdb_context *tdb, (long long)hprefix); goto fail; } - if (tdb_read_convert(tdb, off, &rec, - sizeof(rec))) + ecode = tdb_read_convert(tdb, off, &rec, + sizeof(rec)); + if (ecode != TDB_SUCCESS) { + tdb->ecode = ecode; goto fail; + } goto check; } @@ -346,8 +362,11 @@ static bool check_hash_tree(struct tdb_context *tdb, } } - if (tdb_read_convert(tdb, off, &rec, sizeof(rec))) + ecode = tdb_read_convert(tdb, off, &rec, sizeof(rec)); + if (ecode != TDB_SUCCESS) { + tdb->ecode = ecode; goto fail; + } /* Bottom bits must match header. */ if ((h & ((1 << 11)-1)) != rec_hash(&rec)) { @@ -466,9 +485,13 @@ static bool check_free_table(struct tdb_context *tdb, struct tdb_freetable ft; tdb_off_t h; unsigned int i; + enum TDB_ERROR ecode; - if (tdb_read_convert(tdb, ftable_off, &ft, sizeof(ft)) == -1) + ecode = tdb_read_convert(tdb, ftable_off, &ft, sizeof(ft)); + if (ecode != TDB_SUCCESS) { + tdb->ecode = ecode; return false; + } if (rec_magic(&ft.hdr) != TDB_FTABLE_MAGIC || rec_key_length(&ft.hdr) != 0 @@ -487,8 +510,11 @@ static bool check_free_table(struct tdb_context *tdb, for (off = tdb_read_off(tdb, h); off; off = f.next) { if (off == TDB_OFF_ERR) return false; - if (tdb_read_convert(tdb, off, &f, sizeof(f))) + ecode = tdb_read_convert(tdb, off, &f, sizeof(f)); + if (ecode != TDB_SUCCESS) { + tdb->ecode = ecode; return false; + } if (!check_free(tdb, off, &f, prev, ftable_num, i)) return false; @@ -537,6 +563,7 @@ static bool check_linear(struct tdb_context *tdb, { tdb_off_t off; tdb_len_t len; + enum TDB_ERROR ecode; bool found_recovery = false; for (off = sizeof(struct tdb_header); off < tdb->map_size; off += len) { @@ -546,15 +573,20 @@ static bool check_linear(struct tdb_context *tdb, struct tdb_recovery_record r; } rec; /* r is larger: only get that if we need to. */ - if (tdb_read_convert(tdb, off, &rec, sizeof(rec.f)) == -1) + ecode = tdb_read_convert(tdb, off, &rec, sizeof(rec.f)); + if (ecode != TDB_SUCCESS) { + tdb->ecode = ecode; return false; + } /* If we crash after ftruncate, we can get zeroes or fill. */ if (rec.r.magic == TDB_RECOVERY_INVALID_MAGIC || rec.r.magic == 0x4343434343434343ULL) { - if (tdb_read_convert(tdb, off, &rec, sizeof(rec.r))) + ecode = tdb_read_convert(tdb, off, &rec, sizeof(rec.r)); + if (ecode != TDB_SUCCESS) { + tdb->ecode = ecode; return false; - + } if (recovery == off) { found_recovery = true; len = sizeof(rec.r) + rec.r.max_len; @@ -575,8 +607,11 @@ static bool check_linear(struct tdb_context *tdb, (size_t)tdb->map_size); } } else if (rec.r.magic == TDB_RECOVERY_MAGIC) { - if (tdb_read_convert(tdb, off, &rec, sizeof(rec.r))) + ecode = tdb_read_convert(tdb, off, &rec, sizeof(rec.r)); + if (ecode != TDB_SUCCESS) { + tdb->ecode = ecode; return false; + } if (recovery != off) { tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR, diff --git a/ccan/tdb2/free.c b/ccan/tdb2/free.c index 83ad7ff5..fb45c80c 100644 --- a/ccan/tdb2/free.c +++ b/ccan/tdb2/free.c @@ -108,6 +108,7 @@ static int remove_from_list(struct tdb_context *tdb, const struct tdb_free_record *r) { tdb_off_t off; + enum TDB_ERROR ecode; /* Front of list? */ if (frec_prev(r) == 0) { @@ -126,7 +127,9 @@ static int remove_from_list(struct tdb_context *tdb, #endif /* r->prev->next = r->next */ - if (tdb_write_off(tdb, off, r->next)) { + ecode = tdb_write_off(tdb, off, r->next); + if (ecode != TDB_SUCCESS) { + tdb->ecode = ecode; return -1; } @@ -143,7 +146,9 @@ static int remove_from_list(struct tdb_context *tdb, } #endif - if (tdb_write_off(tdb, off, r->magic_and_prev)) { + ecode = tdb_write_off(tdb, off, r->magic_and_prev); + if (ecode != TDB_SUCCESS) { + tdb->ecode = ecode; return -1; } } @@ -157,6 +162,7 @@ static int enqueue_in_free(struct tdb_context *tdb, tdb_len_t len) { struct tdb_free_record new; + enum TDB_ERROR ecode; uint64_t magic = (TDB_FREE_MAGIC << (64 - TDB_OFF_UPPER_STEAL)); /* We only need to set ftable_and_len; rest is set in enqueue_in_free */ @@ -184,17 +190,28 @@ static int enqueue_in_free(struct tdb_context *tdb, } #endif /* next->prev = new. */ - if (tdb_write_off(tdb, new.next - + offsetof(struct tdb_free_record, - magic_and_prev), - off | magic) != 0) + ecode = tdb_write_off(tdb, new.next + + offsetof(struct tdb_free_record, + magic_and_prev), + off | magic); + if (ecode != TDB_SUCCESS) { + tdb->ecode = ecode; return -1; + } } /* head = new */ - if (tdb_write_off(tdb, b_off, off) != 0) + ecode = tdb_write_off(tdb, b_off, off); + if (ecode != TDB_SUCCESS) { + tdb->ecode = ecode; return -1; + } - return tdb_write_convert(tdb, off, &new, sizeof(new)); + ecode = tdb_write_convert(tdb, off, &new, sizeof(new)); + if (ecode != TDB_SUCCESS) { + tdb->ecode = ecode; + return -1; + } + return 0; } /* List need not be locked. */ @@ -269,6 +286,7 @@ static int coalesce(struct tdb_context *tdb, { tdb_off_t end; struct tdb_free_record rec; + enum TDB_ERROR ecode; add_stat(tdb, alloc_coalesce_tried, 1); end = off + sizeof(struct tdb_used_record) + data_len; @@ -301,7 +319,9 @@ static int coalesce(struct tdb_context *tdb, } /* Now we have lock, re-check. */ - if (tdb_read_convert(tdb, end, &rec, sizeof(rec))) { + ecode = tdb_read_convert(tdb, end, &rec, sizeof(rec)); + if (ecode != TDB_SUCCESS) { + tdb->ecode = ecode; tdb_unlock_free_bucket(tdb, nb_off); goto err; } @@ -334,8 +354,11 @@ static int coalesce(struct tdb_context *tdb, return 0; /* OK, expand initial record */ - if (tdb_read_convert(tdb, off, &rec, sizeof(rec))) + ecode = tdb_read_convert(tdb, off, &rec, sizeof(rec)); + if (ecode != TDB_SUCCESS) { + tdb->ecode = ecode; goto err; + } if (frec_len(&rec) != data_len) { tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR, @@ -351,10 +374,13 @@ static int coalesce(struct tdb_context *tdb, * doesn't get coalesced by someone else! */ rec.ftable_and_len = (TDB_FTABLE_NONE << (64 - TDB_OFF_UPPER_STEAL)) | (end - off - sizeof(struct tdb_used_record)); - if (tdb_write_off(tdb, off + offsetof(struct tdb_free_record, - ftable_and_len), - rec.ftable_and_len) != 0) + ecode = tdb_write_off(tdb, off + offsetof(struct tdb_free_record, + ftable_and_len), + rec.ftable_and_len); + if (ecode != TDB_SUCCESS) { + tdb->ecode = ecode; goto err; + } add_stat(tdb, alloc_coalesce_succeeded, 1); tdb_unlock_free_bucket(tdb, b_off); @@ -475,8 +501,11 @@ again: frec_len(&best) - leftover, hashlow) != 0) goto unlock_err; - if (tdb_write_convert(tdb, best_off, &rec, sizeof(rec)) != 0) + ecode = tdb_write_convert(tdb, best_off, &rec, sizeof(rec)); + if (ecode != TDB_SUCCESS) { + tdb->ecode = ecode; goto unlock_err; + } /* Bucket of leftover will be <= current bucket, so nested * locking is allowed. */ diff --git a/ccan/tdb2/hash.c b/ccan/tdb2/hash.c index a52ae467..5b34fc06 100644 --- a/ccan/tdb2/hash.c +++ b/ccan/tdb2/hash.c @@ -110,6 +110,7 @@ static bool match(struct tdb_context *tdb, struct tdb_used_record *rec) { tdb_off_t off; + enum TDB_ERROR ecode; add_stat(tdb, compares, 1); /* Desired bucket must match. */ @@ -127,8 +128,11 @@ static bool match(struct tdb_context *tdb, } off = val & TDB_OFF_MASK; - if (tdb_read_convert(tdb, off, rec, sizeof(*rec)) == -1) + ecode = tdb_read_convert(tdb, off, rec, sizeof(*rec)); + if (ecode != TDB_SUCCESS) { + tdb->ecode = ecode; return false; + } if ((h->h & ((1 << 11)-1)) != rec_hash(rec)) { add_stat(tdb, compare_wrong_rechash, 1); @@ -164,6 +168,7 @@ static tdb_off_t COLD find_in_chain(struct tdb_context *tdb, struct traverse_info *tinfo) { tdb_off_t off, next; + enum TDB_ERROR ecode; /* In case nothing is free, we set these to zero. */ h->home_bucket = h->found_bucket = 0; @@ -172,8 +177,11 @@ static tdb_off_t COLD find_in_chain(struct tdb_context *tdb, unsigned int i; h->group_start = off; - if (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) { + tdb->ecode = ecode; return TDB_OFF_ERR; + } for (i = 0; i < (1 << TDB_HASH_GROUP_BITS); i++) { tdb_off_t recoff; @@ -186,8 +194,12 @@ static tdb_off_t COLD find_in_chain(struct tdb_context *tdb, /* We can insert extra bits via add_to_hash * empty bucket logic. */ recoff = h->group[i] & TDB_OFF_MASK; - if (tdb_read_convert(tdb, recoff, rec, sizeof(*rec))) + ecode = tdb_read_convert(tdb, recoff, rec, + sizeof(*rec)); + if (ecode != TDB_SUCCESS) { + tdb->ecode = ecode; return TDB_OFF_ERR; + } if (key_matches(tdb, rec, recoff, &key)) { h->home_bucket = h->found_bucket = i; @@ -259,9 +271,12 @@ tdb_off_t find_and_lock(struct tdb_context *tdb, h->group_start = hashtable + group * (sizeof(tdb_off_t) << TDB_HASH_GROUP_BITS); - if (tdb_read_convert(tdb, h->group_start, &h->group, - sizeof(h->group)) == -1) + ecode = tdb_read_convert(tdb, h->group_start, &h->group, + sizeof(h->group)); + if (ecode != TDB_SUCCESS) { + tdb->ecode = ecode; goto fail; + } /* Pointer to another hash table? Go down... */ if (is_subhash(h->group[h->home_bucket])) { @@ -393,8 +408,15 @@ int replace_in_hash(struct tdb_context *tdb, struct hash_info *h, tdb_off_t new_off) { - return tdb_write_off(tdb, hbucket_off(h->group_start, h->found_bucket), - encode_offset(new_off, h)); + enum TDB_ERROR ecode; + + ecode = tdb_write_off(tdb, hbucket_off(h->group_start, h->found_bucket), + encode_offset(new_off, h)); + if (ecode != TDB_SUCCESS) { + tdb->ecode = ecode; + return -1; + } + return 0; } /* We slot in anywhere that's empty in the chain. */ @@ -403,6 +425,7 @@ static int COLD add_to_chain(struct tdb_context *tdb, tdb_off_t new_off) { size_t entry = tdb_find_zero_off(tdb, subhash, 1<ecode = ecode; return -1; - if (tdb_write_off(tdb, subhash - + offsetof(struct tdb_chain, next), - next) != 0) + } + ecode = tdb_write_off(tdb, subhash + + offsetof(struct tdb_chain, + next), + next); + if (ecode != TDB_SUCCESS) { + tdb->ecode = ecode; return -1; + } } return add_to_chain(tdb, next, new_off); } - return tdb_write_off(tdb, subhash + entry * sizeof(tdb_off_t), - new_off); + ecode = tdb_write_off(tdb, subhash + entry * sizeof(tdb_off_t), + new_off); + if (ecode != TDB_SUCCESS) { + tdb->ecode = ecode; + return -1; + } + return 0; } /* Add into a newly created subhash. */ @@ -439,6 +475,7 @@ static int add_to_subhash(struct tdb_context *tdb, tdb_off_t subhash, tdb_off_t off = (val & TDB_OFF_MASK), *group; struct hash_info h; unsigned int gnum; + enum TDB_ERROR ecode; h.hash_used = hash_used; @@ -456,7 +493,12 @@ static int add_to_subhash(struct tdb_context *tdb, tdb_off_t subhash, if (!group) return -1; force_into_group(group, h.home_bucket, encode_offset(off, &h)); - return tdb_access_commit(tdb, group); + ecode = tdb_access_commit(tdb, group); + if (ecode != TDB_SUCCESS) { + tdb->ecode = ecode; + return -1; + } + return 0; } static int expand_group(struct tdb_context *tdb, struct hash_info *h) @@ -465,6 +507,7 @@ static int expand_group(struct tdb_context *tdb, struct hash_info *h) size_t subsize; tdb_off_t subhash; tdb_off_t vals[1 << TDB_HASH_GROUP_BITS]; + enum TDB_ERROR ecode; /* Attach new empty subhash under fullest bucket. */ bucket = fullest_bucket(tdb, h->group, h->home_bucket); @@ -483,8 +526,12 @@ static int expand_group(struct tdb_context *tdb, struct hash_info *h) if (subhash == TDB_OFF_ERR) return -1; - if (zero_out(tdb, subhash + sizeof(struct tdb_used_record), subsize)) + ecode = zero_out(tdb, subhash + sizeof(struct tdb_used_record), + subsize); + if (ecode != TDB_SUCCESS) { + tdb->ecode = ecode; return -1; + } /* Remove any which are destined for bucket or are in wrong place. */ num_vals = 0; @@ -525,6 +572,7 @@ int delete_from_hash(struct tdb_context *tdb, struct hash_info *h) { unsigned int i, num_movers = 0; tdb_off_t movers[1 << TDB_HASH_GROUP_BITS]; + enum TDB_ERROR ecode; h->group[h->found_bucket] = 0; for (i = 1; i < (1 << TDB_HASH_GROUP_BITS); i++) { @@ -554,18 +602,30 @@ int delete_from_hash(struct tdb_context *tdb, struct hash_info *h) } /* Now we write back the hash group */ - return tdb_write_convert(tdb, h->group_start, - h->group, sizeof(h->group)); + ecode = tdb_write_convert(tdb, h->group_start, + h->group, sizeof(h->group)); + if (ecode != TDB_SUCCESS) { + tdb->ecode = ecode; + return -1; + } + return 0; } int add_to_hash(struct tdb_context *tdb, struct hash_info *h, tdb_off_t new_off) { + enum TDB_ERROR ecode; + /* We hit an empty bucket during search? That's where it goes. */ if (!h->group[h->found_bucket]) { h->group[h->found_bucket] = encode_offset(new_off, h); /* Write back the modified group. */ - return tdb_write_convert(tdb, h->group_start, - h->group, sizeof(h->group)); + ecode = tdb_write_convert(tdb, h->group_start, + h->group, sizeof(h->group)); + if (ecode != TDB_SUCCESS) { + tdb->ecode = ecode; + return -1; + } + return 0; } if (h->hash_used > 64) @@ -581,9 +641,12 @@ int add_to_hash(struct tdb_context *tdb, struct hash_info *h, tdb_off_t new_off) unsigned int gnum; /* Write back the modified group. */ - if (tdb_write_convert(tdb, h->group_start, h->group, - sizeof(h->group))) + ecode = tdb_write_convert(tdb, h->group_start, h->group, + sizeof(h->group)); + if (ecode != TDB_SUCCESS) { + tdb->ecode = ecode; return -1; + } /* Move hashinfo down a level. */ hashtable = (h->group[h->home_bucket] & TDB_OFF_MASK) @@ -592,16 +655,25 @@ int add_to_hash(struct tdb_context *tdb, struct hash_info *h, tdb_off_t new_off) h->home_bucket = use_bits(h, TDB_HASH_GROUP_BITS); h->group_start = hashtable + gnum * (sizeof(tdb_off_t) << TDB_HASH_GROUP_BITS); - if (tdb_read_convert(tdb, h->group_start, &h->group, - sizeof(h->group)) == -1) + ecode = tdb_read_convert(tdb, h->group_start, &h->group, + sizeof(h->group)); + if (ecode != TDB_SUCCESS) { + tdb->ecode = ecode; return -1; + } } /* Expanding the group must have made room if it didn't choose this * bucket. */ - if (put_into_group(h->group, h->home_bucket, encode_offset(new_off, h))) - return tdb_write_convert(tdb, h->group_start, - h->group, sizeof(h->group)); + if (put_into_group(h->group, h->home_bucket, encode_offset(new_off,h))){ + ecode = tdb_write_convert(tdb, h->group_start, + h->group, sizeof(h->group)); + if (ecode != TDB_SUCCESS) { + tdb->ecode = ecode; + return -1; + } + return 0; + } /* This can happen if all hashes in group (and us) dropped into same * group in subhash. */ @@ -705,7 +777,9 @@ int next_in_hash(struct tdb_context *tdb, if (off) { struct tdb_used_record rec; - if (tdb_read_convert(tdb, off, &rec, sizeof(rec))) { + ecode = tdb_read_convert(tdb, off, &rec, sizeof(rec)); + if (ecode != TDB_SUCCESS) { + tdb->ecode = ecode; tdb_unlock_hashes(tdb, hl_start, hl_range, F_RDLCK); return -1; diff --git a/ccan/tdb2/io.c b/ccan/tdb2/io.c index a0c5f523..71238afe 100644 --- a/ccan/tdb2/io.c +++ b/ccan/tdb2/io.c @@ -174,33 +174,33 @@ uint64_t tdb_find_zero_off(struct tdb_context *tdb, tdb_off_t off, return i; } -int zero_out(struct tdb_context *tdb, tdb_off_t off, tdb_len_t len) +enum TDB_ERROR zero_out(struct tdb_context *tdb, tdb_off_t off, tdb_len_t len) { char buf[8192] = { 0 }; void *p = tdb->methods->direct(tdb, off, len, true); - enum TDB_ERROR ecode; + enum TDB_ERROR ecode = TDB_SUCCESS; assert(!tdb->read_only); if (p) { memset(p, 0, len); - return 0; + return ecode; } while (len) { unsigned todo = len < sizeof(buf) ? len : sizeof(buf); ecode = tdb->methods->twrite(tdb, off, buf, todo); if (ecode != TDB_SUCCESS) { - tdb->ecode = ecode; - return -1; + break; } len -= todo; off += todo; } - return 0; + return ecode; } tdb_off_t tdb_read_off(struct tdb_context *tdb, tdb_off_t off) { tdb_off_t ret; + enum TDB_ERROR ecode; if (likely(!(tdb->flags & TDB_CONVERT))) { tdb_off_t *p = tdb->methods->direct(tdb, off, sizeof(*p), @@ -209,8 +209,11 @@ tdb_off_t tdb_read_off(struct tdb_context *tdb, tdb_off_t off) return *p; } - if (tdb_read_convert(tdb, off, &ret, sizeof(ret)) == -1) + ecode = tdb_read_convert(tdb, off, &ret, sizeof(ret)); + if (ecode != TDB_SUCCESS) { + tdb->ecode = ecode; return TDB_OFF_ERR; + } return ret; } @@ -281,18 +284,17 @@ static enum TDB_ERROR tdb_read(struct tdb_context *tdb, tdb_off_t off, return TDB_SUCCESS; } -int tdb_write_convert(struct tdb_context *tdb, tdb_off_t off, - const void *rec, size_t len) +enum TDB_ERROR tdb_write_convert(struct tdb_context *tdb, tdb_off_t off, + const void *rec, size_t len) { enum TDB_ERROR ecode; if (unlikely((tdb->flags & TDB_CONVERT))) { void *conv = malloc(len); if (!conv) { - tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_ERROR, - "tdb_write: no memory converting" - " %zu bytes", len); - return -1; + return tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_ERROR, + "tdb_write: no memory converting" + " %zu bytes", len); } memcpy(conv, rec, len); ecode = tdb->methods->twrite(tdb, off, @@ -301,32 +303,23 @@ int tdb_write_convert(struct tdb_context *tdb, tdb_off_t off, } else { ecode = tdb->methods->twrite(tdb, off, rec, len); } - - if (ecode != TDB_SUCCESS) { - tdb->ecode = ecode; - return -1; - } - return 0; + return ecode; } -int tdb_read_convert(struct tdb_context *tdb, tdb_off_t off, - void *rec, size_t len) +enum TDB_ERROR tdb_read_convert(struct tdb_context *tdb, tdb_off_t off, + void *rec, size_t len) { enum TDB_ERROR ecode = tdb->methods->tread(tdb, off, rec, len); tdb_convert(tdb, rec, len); - if (ecode != TDB_SUCCESS) { - tdb->ecode = ecode; - return -1; - } - return 0; + return ecode; } -int tdb_write_off(struct tdb_context *tdb, tdb_off_t off, tdb_off_t val) +enum TDB_ERROR tdb_write_off(struct tdb_context *tdb, + tdb_off_t off, tdb_off_t val) { 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"); } if (likely(!(tdb->flags & TDB_CONVERT))) { @@ -334,7 +327,7 @@ int tdb_write_off(struct tdb_context *tdb, tdb_off_t off, tdb_off_t val) true); if (p) { *p = val; - return 0; + return TDB_SUCCESS; } } return tdb_write_convert(tdb, off, &val, sizeof(val)); @@ -369,9 +362,9 @@ void *tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t len) return _tdb_alloc_read(tdb, offset, len, 0); } -static int fill(struct tdb_context *tdb, - const void *buf, size_t size, - tdb_off_t off, tdb_len_t len) +static enum TDB_ERROR fill(struct tdb_context *tdb, + const void *buf, size_t size, + tdb_off_t off, tdb_len_t len) { while (len) { size_t n = len > size ? size : len; @@ -380,16 +373,16 @@ static int fill(struct tdb_context *tdb, if (ret >= 0) errno = ENOSPC; - tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR, - "fill failed: %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, + "fill failed:" + " %zi at %zu len=%zu (%s)", + ret, (size_t)off, (size_t)len, + strerror(errno)); } len -= n; off += n; } - return 0; + return TDB_SUCCESS; } /* expand a file. we prefer to use ftruncate, as that is what posix @@ -398,6 +391,7 @@ static enum TDB_ERROR tdb_expand_file(struct tdb_context *tdb, tdb_len_t addition) { char buf[8192]; + enum TDB_ERROR ecode; if (tdb->read_only) { return tdb_logerr(tdb, TDB_ERR_RDONLY, TDB_LOG_USE_ERROR, @@ -425,8 +419,9 @@ static enum TDB_ERROR tdb_expand_file(struct tdb_context *tdb, file isn't sparse, which would be very bad if we ran out of disk. This must be done with write, not via mmap */ memset(buf, 0x43, sizeof(buf)); - if (fill(tdb, buf, sizeof(buf), tdb->map_size, addition) == -1) - return tdb->ecode; + ecode = fill(tdb, buf, sizeof(buf), tdb->map_size, addition); + if (ecode != TDB_SUCCESS) + return ecode; tdb->map_size += addition; tdb_mmap(tdb); } @@ -513,23 +508,25 @@ void tdb_access_release(struct tdb_context *tdb, const void *p) tdb->direct_access--; } -int tdb_access_commit(struct tdb_context *tdb, void *p) +enum TDB_ERROR tdb_access_commit(struct tdb_context *tdb, void *p) { struct tdb_access_hdr *hdr, **hp = find_hdr(tdb, p); - int ret = 0; + enum TDB_ERROR ecode; if (hp) { hdr = *hp; if (hdr->convert) - ret = tdb_write_convert(tdb, hdr->off, p, hdr->len); + ecode = tdb_write_convert(tdb, hdr->off, p, hdr->len); else - ret = tdb_write(tdb, hdr->off, p, hdr->len); + ecode = tdb_write(tdb, hdr->off, p, hdr->len); *hp = hdr->next; free(hdr); - } else + } else { tdb->direct_access--; + ecode = TDB_SUCCESS; + } - return ret; + return ecode; } static void *tdb_direct(struct tdb_context *tdb, tdb_off_t off, size_t len, diff --git a/ccan/tdb2/private.h b/ccan/tdb2/private.h index f0b5cae5..9abed97d 100644 --- a/ccan/tdb2/private.h +++ b/ccan/tdb2/private.h @@ -476,16 +476,17 @@ void *tdb_access_write(struct tdb_context *tdb, /* Release result of tdb_access_read/write. */ void tdb_access_release(struct tdb_context *tdb, const void *p); /* Commit result of tdb_acces_write. */ -int tdb_access_commit(struct tdb_context *tdb, void *p); +enum TDB_ERROR tdb_access_commit(struct tdb_context *tdb, void *p); /* Convenience routine to get an offset. */ tdb_off_t tdb_read_off(struct tdb_context *tdb, tdb_off_t off); /* Write an offset at an offset. */ -int tdb_write_off(struct tdb_context *tdb, tdb_off_t off, tdb_off_t val); +enum TDB_ERROR tdb_write_off(struct tdb_context *tdb, tdb_off_t off, + tdb_off_t val); /* Clear an ondisk area. */ -int zero_out(struct tdb_context *tdb, tdb_off_t off, tdb_len_t len); +enum TDB_ERROR zero_out(struct tdb_context *tdb, tdb_off_t off, tdb_len_t len); /* Return a non-zero offset between >= start < end in this array (or end). */ tdb_off_t tdb_find_nonzero_off(struct tdb_context *tdb, @@ -501,12 +502,12 @@ tdb_off_t tdb_find_zero_off(struct tdb_context *tdb, tdb_off_t off, void *tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t len); /* Writes a converted copy of a record. */ -int tdb_write_convert(struct tdb_context *tdb, tdb_off_t off, - const void *rec, size_t len); +enum TDB_ERROR tdb_write_convert(struct tdb_context *tdb, tdb_off_t off, + const void *rec, size_t len); /* Reads record and converts it */ -int tdb_read_convert(struct tdb_context *tdb, tdb_off_t off, - void *rec, size_t len); +enum TDB_ERROR tdb_read_convert(struct tdb_context *tdb, tdb_off_t off, + void *rec, size_t len); /* Adds a stat, if it's in range. */ void add_stat_(struct tdb_context *tdb, uint64_t *stat, size_t val); diff --git a/ccan/tdb2/tdb.c b/ccan/tdb2/tdb.c index ba5d3759..8079dad7 100644 --- a/ccan/tdb2/tdb.c +++ b/ccan/tdb2/tdb.c @@ -413,12 +413,18 @@ static int update_rec_hdr(struct tdb_context *tdb, uint64_t h) { uint64_t dataroom = rec_data_length(rec) + rec_extra_padding(rec); + enum TDB_ERROR ecode; if (set_header(tdb, rec, TDB_USED_MAGIC, keylen, datalen, keylen + dataroom, h)) return -1; - return tdb_write_convert(tdb, off, rec, sizeof(*rec)); + ecode = tdb_write_convert(tdb, off, rec, sizeof(*rec)); + if (ecode != TDB_SUCCESS) { + tdb->ecode = ecode; + return -1; + } + return 0; } /* Returns -1 on error, 0 on OK */ diff --git a/ccan/tdb2/test/run-03-coalesce.c b/ccan/tdb2/test/run-03-coalesce.c index 621ed01b..7325a449 100644 --- a/ccan/tdb2/test/run-03-coalesce.c +++ b/ccan/tdb2/test/run-03-coalesce.c @@ -12,11 +12,13 @@ static tdb_len_t free_record_length(struct tdb_context *tdb, tdb_off_t off) { struct tdb_free_record f; + enum TDB_ERROR ecode; - if (tdb_read_convert(tdb, off, &f, sizeof(f)) != 0) - return TDB_OFF_ERR; + ecode = tdb_read_convert(tdb, off, &f, sizeof(f)); + if (ecode != TDB_SUCCESS) + return ecode; if (frec_magic(&f) != TDB_FREE_MAGIC) - return TDB_OFF_ERR; + return TDB_ERR_CORRUPT; return frec_len(&f); } diff --git a/ccan/tdb2/transaction.c b/ccan/tdb2/transaction.c index 2c9f354a..e7050bfe 100644 --- a/ccan/tdb2/transaction.c +++ b/ccan/tdb2/transaction.c @@ -1121,8 +1121,9 @@ int tdb_transaction_recover(struct tdb_context *tdb) } /* read the recovery record */ - if (tdb_read_convert(tdb, recovery_head, &rec, sizeof(rec)) == -1) { - tdb_logerr(tdb, tdb->ecode, TDB_LOG_ERROR, + ecode = tdb_read_convert(tdb, recovery_head, &rec, sizeof(rec)); + if (ecode != TDB_SUCCESS) { + tdb_logerr(tdb, ecode, TDB_LOG_ERROR, "tdb_transaction_recover:" " failed to read recovery record"); return -1; @@ -1193,9 +1194,11 @@ int tdb_transaction_recover(struct tdb_context *tdb) /* if the recovery area is after the recovered eof then remove it */ if (recovery_eof <= recovery_head) { - if (tdb_write_off(tdb, offsetof(struct tdb_header,recovery), 0) - == -1) { - tdb_logerr(tdb, tdb->ecode, TDB_LOG_ERROR, + ecode = tdb_write_off(tdb, offsetof(struct tdb_header, + recovery), + 0); + if (ecode != TDB_SUCCESS) { + tdb_logerr(tdb, ecode, TDB_LOG_ERROR, "tdb_transaction_recover:" " failed to remove recovery head"); return -1; @@ -1203,11 +1206,12 @@ int tdb_transaction_recover(struct tdb_context *tdb) } /* remove the recovery magic */ - if (tdb_write_off(tdb, - recovery_head - + offsetof(struct tdb_recovery_record, magic), - TDB_RECOVERY_INVALID_MAGIC) == -1) { - tdb_logerr(tdb, tdb->ecode, TDB_LOG_ERROR, + ecode = tdb_write_off(tdb, + recovery_head + + offsetof(struct tdb_recovery_record, magic), + TDB_RECOVERY_INVALID_MAGIC); + if (ecode != TDB_SUCCESS) { + tdb_logerr(tdb, ecode, TDB_LOG_ERROR, "tdb_transaction_recover:" " failed to remove recovery magic"); return -1; @@ -1233,6 +1237,7 @@ bool tdb_needs_recovery(struct tdb_context *tdb) { tdb_off_t recovery_head; struct tdb_recovery_record rec; + enum TDB_ERROR ecode; /* find the recovery area */ recovery_head = tdb_read_off(tdb, offsetof(struct tdb_header,recovery)); @@ -1246,7 +1251,9 @@ bool tdb_needs_recovery(struct tdb_context *tdb) } /* read the recovery record */ - if (tdb_read_convert(tdb, recovery_head, &rec, sizeof(rec)) == -1) { + ecode = tdb_read_convert(tdb, recovery_head, &rec, sizeof(rec)); + if (ecode != TDB_SUCCESS) { + tdb->ecode = ecode; return true; }