- /* Updates tdb->map_size. */
- if (tdb->methods->expand_file(tdb, add) == -1)
- goto fail;
-
- /* Use first part as new free bucket array. */
- off = tdb->map_size - add;
- freebucket_size = new_num_zones
- * (new_num_buckets + 1) * sizeof(tdb_off_t);
-
- /* Write header. */
- if (set_header(tdb, &fhdr, 0, freebucket_size, freebucket_size, 0))
- goto fail;
- if (tdb_write_convert(tdb, off, &fhdr, sizeof(fhdr)) == -1)
- goto fail;
-
- /* Adjust off to point to start of buckets, add to be remainder. */
- add -= freebucket_size + sizeof(fhdr);
- off += sizeof(fhdr);
-
- /* Access the old zones. */
- old_num_total = tdb->header.v.num_zones*(tdb->header.v.free_buckets+1);
- old_free_off = tdb->header.v.free_off;
- oldf = tdb_access_read(tdb, old_free_off,
- old_num_total * sizeof(tdb_off_t), true);
- if (!oldf)
- goto fail;
-
- /* Switch to using our new zone. */
- if (zero_out(tdb, off, freebucket_size) == -1)
- goto fail_release;
-
- tdb->header.v.free_off = off;
- tdb->header.v.num_zones = new_num_zones;
- tdb->header.v.zone_bits = new_zone_bits;
- tdb->header.v.free_buckets = new_num_buckets;
-
- /* FIXME: If zone size hasn't changed, can simply copy pointers. */
- /* FIXME: Coalesce? */
- for (i = 0; i < old_num_total; i++) {
- tdb_off_t next;
- struct tdb_free_record rec;
- tdb_off_t list;
-
- for (off = oldf[i]; off; off = next) {
- if (tdb_read_convert(tdb, off, &rec, sizeof(rec)))
- goto fail_release;
-
- list = zone_of(tdb, off)
- * (tdb->header.v.free_buckets+1)
- + size_to_bucket(tdb, rec.data_len);
- next = rec.next;
-
- if (enqueue_in_free(tdb, list, off, &rec) == -1)
- goto fail_release;
- }