X-Git-Url: http://git.ozlabs.org/?p=ccan;a=blobdiff_plain;f=ccan%2Ftdb2%2Fcheck.c;h=6d846f414264404255eac5f67d0c93ea824b219b;hp=577086689f373f75c1774d9be2fd1175180af950;hb=49475d68deecd0b31597ed6094229171d2699b11;hpb=f367a1dc8573db0a1f6f49fcda474eb51c192241 diff --git a/ccan/tdb2/check.c b/ccan/tdb2/check.c index 57708668..6d846f41 100644 --- a/ccan/tdb2/check.c +++ b/ccan/tdb2/check.c @@ -94,7 +94,7 @@ static enum TDB_ERROR check_hash_tree(struct tdb_context *tdb, size_t *num_found, enum TDB_ERROR (*check)(TDB_DATA, TDB_DATA, void *), - void *private_data); + void *data); static enum TDB_ERROR check_hash_chain(struct tdb_context *tdb, tdb_off_t off, @@ -105,7 +105,7 @@ static enum TDB_ERROR check_hash_chain(struct tdb_context *tdb, enum TDB_ERROR (*check)(TDB_DATA, TDB_DATA, void *), - void *private_data) + void *data) { struct tdb_used_record rec; enum TDB_ERROR ecode; @@ -141,7 +141,7 @@ static enum TDB_ERROR check_hash_chain(struct tdb_context *tdb, off += sizeof(rec); ecode = check_hash_tree(tdb, off, 0, hash, 64, - used, num_used, num_found, check, private_data); + used, num_used, num_found, check, data); if (ecode != TDB_SUCCESS) { return ecode; } @@ -154,7 +154,7 @@ static enum TDB_ERROR check_hash_chain(struct tdb_context *tdb, return TDB_SUCCESS; (*num_found)++; return check_hash_chain(tdb, off, hash, used, num_used, num_found, - check, private_data); + check, data); } static enum TDB_ERROR check_hash_record(struct tdb_context *tdb, @@ -167,14 +167,14 @@ static enum TDB_ERROR check_hash_record(struct tdb_context *tdb, enum TDB_ERROR (*check)(TDB_DATA, TDB_DATA, void *), - void *private_data) + void *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); + num_found, check, data); ecode = tdb_read_convert(tdb, off, &rec, sizeof(rec)); if (ecode != TDB_SUCCESS) { @@ -210,7 +210,7 @@ static enum TDB_ERROR check_hash_record(struct tdb_context *tdb, return check_hash_tree(tdb, off, TDB_SUBLEVEL_HASH_BITS-TDB_HASH_GROUP_BITS, hprefix, hprefix_bits, - used, num_used, num_found, check, private_data); + used, num_used, num_found, check, data); } static int off_cmp(const tdb_off_t *a, const tdb_off_t *b) @@ -237,7 +237,7 @@ static enum TDB_ERROR check_hash_tree(struct tdb_context *tdb, size_t *num_found, enum TDB_ERROR (*check)(TDB_DATA, TDB_DATA, void *), - void *private_data) + void *data) { unsigned int g, b; const tdb_off_t *hash; @@ -318,7 +318,7 @@ static enum TDB_ERROR check_hash_tree(struct tdb_context *tdb, + group_bits + TDB_HASH_GROUP_BITS, used, num_used, num_found, - check, private_data); + check, data); if (ecode != TDB_SUCCESS) { goto fail; } @@ -401,7 +401,7 @@ static enum TDB_ERROR check_hash_tree(struct tdb_context *tdb, check: if (check) { - TDB_DATA key, data; + TDB_DATA k, d; const unsigned char *kptr; kptr = tdb_access_read(tdb, @@ -414,10 +414,10 @@ static enum TDB_ERROR check_hash_tree(struct tdb_context *tdb, goto fail; } - key = tdb_mkdata(kptr, rec_key_length(&rec)); - data = tdb_mkdata(kptr + key.dsize, - rec_data_length(&rec)); - ecode = check(key, data, private_data); + k = tdb_mkdata(kptr, rec_key_length(&rec)); + d = tdb_mkdata(kptr + k.dsize, + rec_data_length(&rec)); + ecode = check(k, d, data); tdb_access_release(tdb, kptr); if (ecode != TDB_SUCCESS) { goto fail; @@ -437,7 +437,7 @@ static enum TDB_ERROR check_hash(struct tdb_context *tdb, tdb_off_t used[], size_t num_used, size_t num_ftables, int (*check)(TDB_DATA, TDB_DATA, void *), - void *private_data) + void *data) { /* Free tables also show up as used. */ size_t num_found = num_ftables; @@ -446,7 +446,7 @@ static enum TDB_ERROR check_hash(struct tdb_context *tdb, ecode = check_hash_tree(tdb, offsetof(struct tdb_header, hashtable), TDB_TOPLEVEL_HASH_BITS-TDB_HASH_GROUP_BITS, 0, 0, used, num_used, &num_found, - check, private_data); + check, data); if (ecode == TDB_SUCCESS) { if (num_found != num_used) { ecode = tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR, @@ -478,7 +478,7 @@ static enum TDB_ERROR check_free(struct tdb_context *tdb, } - ecode = tdb->methods->oob(tdb, off + ecode = tdb->tdb2.io->oob(tdb, off + frec_len(frec) + sizeof(struct tdb_used_record), false); @@ -492,7 +492,7 @@ static enum TDB_ERROR check_free(struct tdb_context *tdb, (long long)off, bucket, size_to_bucket(frec_len(frec))); } - if (prev != frec_prev(frec)) { + if (prev && prev != frec_prev(frec)) { return tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR, "tdb_check: offset %llu bad prev" " (%llu vs %llu)", @@ -528,7 +528,7 @@ static enum TDB_ERROR check_free_table(struct tdb_context *tdb, } for (i = 0; i < TDB_FREE_BUCKETS; i++) { - tdb_off_t off, prev = 0, *p; + tdb_off_t off, prev = 0, *p, first = 0; struct tdb_free_record f; h = bucket_off(ftable_off, i); @@ -536,6 +536,10 @@ static enum TDB_ERROR check_free_table(struct tdb_context *tdb, if (TDB_OFF_IS_ERR(off)) { return off; } + if (!first) { + off &= TDB_OFF_MASK; + first = off; + } ecode = tdb_read_convert(tdb, off, &f, sizeof(f)); if (ecode != TDB_SUCCESS) { return ecode; @@ -559,6 +563,18 @@ static enum TDB_ERROR check_free_table(struct tdb_context *tdb, (*num_found)++; prev = off; } + + if (first) { + /* Now we can check first back pointer. */ + ecode = tdb_read_convert(tdb, first, &f, sizeof(f)); + if (ecode != TDB_SUCCESS) { + return ecode; + } + ecode = check_free(tdb, first, &f, prev, ftable_num, i); + if (ecode != TDB_SUCCESS) { + return ecode; + } + } } return TDB_SUCCESS; } @@ -571,7 +587,7 @@ tdb_off_t dead_space(struct tdb_context *tdb, tdb_off_t off) for (len = 0; off + len < tdb->file->map_size; len++) { char c; - ecode = tdb->methods->tread(tdb, off, &c, 1); + ecode = tdb->tdb2.io->tread(tdb, off, &c, 1); if (ecode != TDB_SUCCESS) { return ecode; } @@ -758,9 +774,8 @@ static enum TDB_ERROR check_linear(struct tdb_context *tdb, } enum TDB_ERROR tdb_check_(struct tdb_context *tdb, - enum TDB_ERROR (*check)(TDB_DATA key, TDB_DATA data, - void *private), - void *private) + enum TDB_ERROR (*check)(TDB_DATA, TDB_DATA, void *), + void *data) { tdb_off_t *fr = NULL, *used = NULL, ft, recovery; size_t num_free = 0, num_used = 0, num_found = 0, num_ftables = 0; @@ -801,7 +816,7 @@ enum TDB_ERROR tdb_check_(struct tdb_context *tdb, } /* FIXME: Check key uniqueness? */ - ecode = check_hash(tdb, used, num_used, num_ftables, check, private); + ecode = check_hash(tdb, used, num_used, num_ftables, check, data); if (ecode != TDB_SUCCESS) goto out;