- /* FIXME: Encode extra hash bits! */
- return tdb_write_off(tdb, hash_off(tdb, i + num), off);
-}
-
-/* If we fail, others will try after us. */
-static void enlarge_hash(struct tdb_context *tdb)
-{
- tdb_off_t newoff, oldoff, i;
- tdb_len_t hlen;
- uint64_t num = 1ULL << tdb->header.v.hash_bits;
- struct tdb_used_record pad, *r;
- unsigned int records = 0;
-
- /* FIXME: We should do this without holding locks throughout. */
- if (tdb_allrecord_lock(tdb, F_WRLCK, TDB_LOCK_WAIT, false) == -1)
- return;
-
- /* Someone else enlarged for us? Nothing to do. */
- if ((1ULL << tdb->header.v.hash_bits) != num)
- goto unlock;
-
-again:
- /* Allocate our new array. */
- hlen = num * sizeof(tdb_off_t) * 2;
- newoff = alloc(tdb, 0, hlen, 0, false);
- if (unlikely(newoff == TDB_OFF_ERR))
- goto unlock;
- if (unlikely(newoff == 0)) {
- if (tdb_expand(tdb, 0, hlen, false) == -1)
- goto unlock;
- goto again;
- }
- /* Step over record header! */
- newoff += sizeof(struct tdb_used_record);
-
- /* Starts all zero. */
- if (zero_out(tdb, newoff, hlen) == -1)
- goto unlock;
-
- /* Update header now so we can use normal routines. */
- oldoff = tdb->header.v.hash_off;
-
- tdb->header.v.hash_bits++;
- tdb->header.v.hash_off = newoff;
-
- /* FIXME: If the space before is empty, we know this is in its ideal
- * location. Or steal a bit from the pointer to avoid rehash. */
- for (i = 0; i < num; i++) {
- tdb_off_t off;
- off = tdb_read_off(tdb, oldoff + i * sizeof(tdb_off_t));
- if (unlikely(off == TDB_OFF_ERR))
- goto oldheader;
- if (off && hash_add(tdb, hash_record(tdb, off), off) == -1)
- goto oldheader;
- if (off)
- records++;