]> git.ozlabs.org Git - ccan/blob - ccan/tdb2/free.c
97320b585d727d82796e725ef97d1f71e3461e30
[ccan] / ccan / tdb2 / free.c
1  /*
2    Trivial Database 2: free list/block handling
3    Copyright (C) Rusty Russell 2010
4
5    This library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 3 of the License, or (at your option) any later version.
9
10    This library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with this library; if not, see <http://www.gnu.org/licenses/>.
17 */
18 #include "private.h"
19 #include <ccan/likely/likely.h>
20 #include <ccan/ilog/ilog.h>
21 #include <time.h>
22 #include <assert.h>
23 #include <limits.h>
24
25 static unsigned fls64(uint64_t val)
26 {
27         return ilog64(val);
28 }
29
30 /* In which bucket would we find a particular record size? (ignoring header) */
31 unsigned int size_to_bucket(tdb_len_t data_len)
32 {
33         unsigned int bucket;
34
35         /* We can't have records smaller than this. */
36         assert(data_len >= TDB_MIN_DATA_LEN);
37
38         /* Ignoring the header... */
39         if (data_len - TDB_MIN_DATA_LEN <= 64) {
40                 /* 0 in bucket 0, 8 in bucket 1... 64 in bucket 8. */
41                 bucket = (data_len - TDB_MIN_DATA_LEN) / 8;
42         } else {
43                 /* After that we go power of 2. */
44                 bucket = fls64(data_len - TDB_MIN_DATA_LEN) + 2;
45         }
46
47         if (unlikely(bucket >= TDB_FREE_BUCKETS))
48                 bucket = TDB_FREE_BUCKETS - 1;
49         return bucket;
50 }
51
52 tdb_off_t first_ftable(struct tdb_context *tdb)
53 {
54         return tdb_read_off(tdb, offsetof(struct tdb_header, free_table));
55 }
56
57 tdb_off_t next_ftable(struct tdb_context *tdb, tdb_off_t ftable)
58 {
59         return tdb_read_off(tdb, ftable + offsetof(struct tdb_freetable,next));
60 }
61
62 enum TDB_ERROR tdb_ftable_init(struct tdb_context *tdb)
63 {
64         /* Use reservoir sampling algorithm to select a free list at random. */
65         unsigned int rnd, max = 0, count = 0;
66         tdb_off_t off;
67
68         tdb->ftable_off = off = first_ftable(tdb);
69         tdb->ftable = 0;
70
71         while (off) {
72                 if (TDB_OFF_IS_ERR(off)) {
73                         return off;
74                 }
75
76                 rnd = random();
77                 if (rnd >= max) {
78                         tdb->ftable_off = off;
79                         tdb->ftable = count;
80                         max = rnd;
81                 }
82
83                 off = next_ftable(tdb, off);
84                 count++;
85         }
86         return TDB_SUCCESS;
87 }
88
89 /* Offset of a given bucket. */
90 tdb_off_t bucket_off(tdb_off_t ftable_off, unsigned bucket)
91 {
92         return ftable_off + offsetof(struct tdb_freetable, buckets)
93                 + bucket * sizeof(tdb_off_t);
94 }
95
96 /* Returns free_buckets + 1, or list number to search, or -ve error. */
97 static tdb_off_t find_free_head(struct tdb_context *tdb,
98                                 tdb_off_t ftable_off,
99                                 tdb_off_t bucket)
100 {
101         /* Speculatively search for a non-zero bucket. */
102         return tdb_find_nonzero_off(tdb, bucket_off(ftable_off, 0),
103                                     bucket, TDB_FREE_BUCKETS);
104 }
105
106 /* Remove from free bucket. */
107 static enum TDB_ERROR remove_from_list(struct tdb_context *tdb,
108                                        tdb_off_t b_off, tdb_off_t r_off,
109                                        const struct tdb_free_record *r)
110 {
111         tdb_off_t off;
112         enum TDB_ERROR ecode;
113
114         /* Front of list? */
115         if (frec_prev(r) == 0) {
116                 off = b_off;
117         } else {
118                 off = frec_prev(r) + offsetof(struct tdb_free_record, next);
119         }
120
121 #ifdef CCAN_TDB2_DEBUG
122         if (tdb_read_off(tdb, off) != r_off) {
123                 return tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
124                                   "remove_from_list:"
125                                   " %llu bad prev in list %llu",
126                                   (long long)r_off, (long long)b_off);
127         }
128 #endif
129
130         /* r->prev->next = r->next */
131         ecode = tdb_write_off(tdb, off, r->next);
132         if (ecode != TDB_SUCCESS) {
133                 return ecode;
134         }
135
136         if (r->next != 0) {
137                 off = r->next + offsetof(struct tdb_free_record,magic_and_prev);
138                 /* r->next->prev = r->prev */
139
140 #ifdef CCAN_TDB2_DEBUG
141                 if (tdb_read_off(tdb, off) & TDB_OFF_MASK != r_off) {
142                         return tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
143                                           "remove_from_list:"
144                                           " %llu bad list %llu",
145                                           (long long)r_off, (long long)b_off);
146                 }
147 #endif
148
149                 ecode = tdb_write_off(tdb, off, r->magic_and_prev);
150                 if (ecode != TDB_SUCCESS) {
151                         return ecode;
152                 }
153         }
154         return TDB_SUCCESS;
155 }
156
157 /* Enqueue in this free bucket. */
158 static enum TDB_ERROR enqueue_in_free(struct tdb_context *tdb,
159                                       tdb_off_t b_off,
160                                       tdb_off_t off,
161                                       tdb_len_t len)
162 {
163         struct tdb_free_record new;
164         enum TDB_ERROR ecode;
165         uint64_t magic = (TDB_FREE_MAGIC << (64 - TDB_OFF_UPPER_STEAL));
166
167         /* We only need to set ftable_and_len; rest is set in enqueue_in_free */
168         new.ftable_and_len = ((uint64_t)tdb->ftable << (64 - TDB_OFF_UPPER_STEAL))
169                 | len;
170         /* prev = 0. */
171         new.magic_and_prev = magic;
172
173         /* new->next = head. */
174         new.next = tdb_read_off(tdb, b_off);
175         if (TDB_OFF_IS_ERR(new.next)) {
176                 return new.next;
177         }
178
179         if (new.next) {
180 #ifdef CCAN_TDB2_DEBUG
181                 if (tdb_read_off(tdb,
182                                  new.next + offsetof(struct tdb_free_record,
183                                                      magic_and_prev))
184                     != magic) {
185                         return tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
186                                           "enqueue_in_free: %llu bad head"
187                                           " prev %llu",
188                                           (long long)new.next,
189                                           (long long)b_off);
190                 }
191 #endif
192                 /* next->prev = new. */
193                 ecode = tdb_write_off(tdb, new.next
194                                       + offsetof(struct tdb_free_record,
195                                                  magic_and_prev),
196                                       off | magic);
197                 if (ecode != TDB_SUCCESS) {
198                         return ecode;
199                 }
200         }
201         /* head = new */
202         ecode = tdb_write_off(tdb, b_off, off);
203         if (ecode != TDB_SUCCESS) {
204                 return ecode;
205         }
206
207         return tdb_write_convert(tdb, off, &new, sizeof(new));
208 }
209
210 /* List need not be locked. */
211 enum TDB_ERROR add_free_record(struct tdb_context *tdb,
212                                tdb_off_t off, tdb_len_t len_with_header)
213 {
214         tdb_off_t b_off;
215         tdb_len_t len;
216         enum TDB_ERROR ecode;
217
218         assert(len_with_header >= sizeof(struct tdb_free_record));
219
220         len = len_with_header - sizeof(struct tdb_used_record);
221
222         b_off = bucket_off(tdb->ftable_off, size_to_bucket(len));
223         ecode = tdb_lock_free_bucket(tdb, b_off, TDB_LOCK_WAIT);
224         if (ecode != TDB_SUCCESS) {
225                 return ecode;
226         }
227
228         ecode = enqueue_in_free(tdb, b_off, off, len);
229         tdb_unlock_free_bucket(tdb, b_off);
230         return ecode;
231 }
232
233 static size_t adjust_size(size_t keylen, size_t datalen)
234 {
235         size_t size = keylen + datalen;
236
237         if (size < TDB_MIN_DATA_LEN)
238                 size = TDB_MIN_DATA_LEN;
239
240         /* Round to next uint64_t boundary. */
241         return (size + (sizeof(uint64_t) - 1ULL)) & ~(sizeof(uint64_t) - 1ULL);
242 }
243
244 /* If we have enough left over to be useful, split that off. */
245 static size_t record_leftover(size_t keylen, size_t datalen,
246                               bool want_extra, size_t total_len)
247 {
248         ssize_t leftover;
249
250         if (want_extra)
251                 datalen += datalen / 2;
252         leftover = total_len - adjust_size(keylen, datalen);
253
254         if (leftover < (ssize_t)sizeof(struct tdb_free_record))
255                 return 0;
256
257         return leftover;
258 }
259
260 static tdb_off_t ftable_offset(struct tdb_context *tdb, unsigned int ftable)
261 {
262         tdb_off_t off;
263         unsigned int i;
264
265         if (likely(tdb->ftable == ftable))
266                 return tdb->ftable_off;
267
268         off = first_ftable(tdb);
269         for (i = 0; i < ftable; i++) {
270                 if (TDB_OFF_IS_ERR(off)) {
271                         tdb->ecode = off;
272                         break;
273                 }
274                 off = next_ftable(tdb, off);
275         }
276         return off;
277 }
278
279 /* Note: we unlock the current bucket if we coalesce or fail. */
280 static tdb_bool_err coalesce(struct tdb_context *tdb,
281                              tdb_off_t off, tdb_off_t b_off,
282                              tdb_len_t data_len)
283 {
284         tdb_off_t end;
285         struct tdb_free_record rec;
286         enum TDB_ERROR ecode;
287
288         add_stat(tdb, alloc_coalesce_tried, 1);
289         end = off + sizeof(struct tdb_used_record) + data_len;
290
291         while (end < tdb->map_size) {
292                 const struct tdb_free_record *r;
293                 tdb_off_t nb_off;
294                 unsigned ftable, bucket;
295
296                 r = tdb_access_read(tdb, end, sizeof(*r), true);
297                 if (TDB_PTR_IS_ERR(r)) {
298                         ecode = TDB_PTR_ERR(r);
299                         goto err;
300                 }
301
302                 if (frec_magic(r) != TDB_FREE_MAGIC
303                     || frec_ftable(r) == TDB_FTABLE_NONE) {
304                         tdb_access_release(tdb, r);
305                         break;
306                 }
307
308                 ftable = frec_ftable(r);
309                 bucket = size_to_bucket(frec_len(r));
310                 nb_off = ftable_offset(tdb, ftable);
311                 if (TDB_OFF_IS_ERR(nb_off)) {
312                         tdb_access_release(tdb, r);
313                         ecode = nb_off;
314                         goto err;
315                 }
316                 nb_off = bucket_off(nb_off, bucket);
317                 tdb_access_release(tdb, r);
318
319                 /* We may be violating lock order here, so best effort. */
320                 if (tdb_lock_free_bucket(tdb, nb_off, TDB_LOCK_NOWAIT)
321                     != TDB_SUCCESS) {
322                         add_stat(tdb, alloc_coalesce_lockfail, 1);
323                         break;
324                 }
325
326                 /* Now we have lock, re-check. */
327                 ecode = tdb_read_convert(tdb, end, &rec, sizeof(rec));
328                 if (ecode != TDB_SUCCESS) {
329                         tdb_unlock_free_bucket(tdb, nb_off);
330                         goto err;
331                 }
332
333                 if (unlikely(frec_magic(&rec) != TDB_FREE_MAGIC)) {
334                         add_stat(tdb, alloc_coalesce_race, 1);
335                         tdb_unlock_free_bucket(tdb, nb_off);
336                         break;
337                 }
338
339                 if (unlikely(frec_ftable(&rec) != ftable)
340                     || unlikely(size_to_bucket(frec_len(&rec)) != bucket)) {
341                         add_stat(tdb, alloc_coalesce_race, 1);
342                         tdb_unlock_free_bucket(tdb, nb_off);
343                         break;
344                 }
345
346                 ecode = remove_from_list(tdb, nb_off, end, &rec);
347                 if (ecode != TDB_SUCCESS) {
348                         tdb_unlock_free_bucket(tdb, nb_off);
349                         goto err;
350                 }
351
352                 end += sizeof(struct tdb_used_record) + frec_len(&rec);
353                 tdb_unlock_free_bucket(tdb, nb_off);
354                 add_stat(tdb, alloc_coalesce_num_merged, 1);
355         }
356
357         /* Didn't find any adjacent free? */
358         if (end == off + sizeof(struct tdb_used_record) + data_len)
359                 return false;
360
361         /* OK, expand initial record */
362         ecode = tdb_read_convert(tdb, off, &rec, sizeof(rec));
363         if (ecode != TDB_SUCCESS) {
364                 goto err;
365         }
366
367         if (frec_len(&rec) != data_len) {
368                 ecode = tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
369                                    "coalesce: expected data len %zu not %zu",
370                                    (size_t)data_len, (size_t)frec_len(&rec));
371                 goto err;
372         }
373
374         ecode = remove_from_list(tdb, b_off, off, &rec);
375         if (ecode != TDB_SUCCESS) {
376                 goto err;
377         }
378
379         /* We have to drop this to avoid deadlocks, so make sure record
380          * doesn't get coalesced by someone else! */
381         rec.ftable_and_len = (TDB_FTABLE_NONE << (64 - TDB_OFF_UPPER_STEAL))
382                 | (end - off - sizeof(struct tdb_used_record));
383         ecode = tdb_write_off(tdb, off + offsetof(struct tdb_free_record,
384                                                   ftable_and_len),
385                               rec.ftable_and_len);
386         if (ecode != TDB_SUCCESS) {
387                 goto err;
388         }
389
390         add_stat(tdb, alloc_coalesce_succeeded, 1);
391         tdb_unlock_free_bucket(tdb, b_off);
392
393         ecode = add_free_record(tdb, off, end - off);
394         if (ecode != TDB_SUCCESS) {
395                 tdb->ecode = ecode;
396                 return ecode;
397         }
398         return true;
399
400 err:
401         /* To unify error paths, we *always* unlock bucket on error. */
402         tdb_unlock_free_bucket(tdb, b_off);
403         return ecode;
404 }
405
406 /* We need size bytes to put our key and data in. */
407 static tdb_off_t lock_and_alloc(struct tdb_context *tdb,
408                                 tdb_off_t ftable_off,
409                                 tdb_off_t bucket,
410                                 size_t keylen, size_t datalen,
411                                 bool want_extra,
412                                 unsigned magic,
413                                 unsigned hashlow)
414 {
415         tdb_off_t off, b_off,best_off;
416         struct tdb_free_record best = { 0 };
417         double multiplier;
418         size_t size = adjust_size(keylen, datalen);
419         enum TDB_ERROR ecode;
420
421         add_stat(tdb, allocs, 1);
422 again:
423         b_off = bucket_off(ftable_off, bucket);
424
425         /* FIXME: Try non-blocking wait first, to measure contention. */
426         /* Lock this bucket. */
427         ecode = tdb_lock_free_bucket(tdb, b_off, TDB_LOCK_WAIT);
428         if (ecode != TDB_SUCCESS) {
429                 return ecode;
430         }
431
432         best.ftable_and_len = -1ULL;
433         best_off = 0;
434
435         /* Get slack if we're after extra. */
436         if (want_extra)
437                 multiplier = 1.5;
438         else
439                 multiplier = 1.0;
440
441         /* Walk the list to see if any are large enough, getting less fussy
442          * as we go. */
443         off = tdb_read_off(tdb, b_off);
444         if (TDB_OFF_IS_ERR(off)) {
445                 ecode = off;
446                 goto unlock_err;
447         }
448
449         while (off) {
450                 const struct tdb_free_record *r;
451                 tdb_len_t len;
452                 tdb_off_t next;
453                 int coal;
454
455                 r = tdb_access_read(tdb, off, sizeof(*r), true);
456                 if (TDB_PTR_IS_ERR(r)) {
457                         ecode = TDB_PTR_ERR(r);
458                         goto unlock_err;
459                 }
460
461                 if (frec_magic(r) != TDB_FREE_MAGIC) {
462                         tdb_access_release(tdb, r);
463                         ecode = tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
464                                            "lock_and_alloc:"
465                                            " %llu non-free 0x%llx",
466                                            (long long)off,
467                                            (long long)r->magic_and_prev);
468                         goto unlock_err;
469                 }
470
471                 if (frec_len(r) >= size && frec_len(r) < frec_len(&best)) {
472                         best_off = off;
473                         best = *r;
474                 }
475
476                 if (frec_len(&best) < size * multiplier && best_off) {
477                         tdb_access_release(tdb, r);
478                         break;
479                 }
480
481                 multiplier *= 1.01;
482
483                 next = r->next;
484                 len = frec_len(r);
485                 tdb_access_release(tdb, r);
486
487                 /* Since we're going slow anyway, try coalescing here. */
488                 coal = coalesce(tdb, off, b_off, len);
489                 if (coal == 1) {
490                         /* This has unlocked list, restart. */
491                         goto again;
492                 }
493                 if (coal < 0) {
494                         /* This has already unlocked on error. */
495                         return coal;
496                 }
497                 off = next;
498         }
499
500         /* If we found anything at all, use it. */
501         if (best_off) {
502                 struct tdb_used_record rec;
503                 size_t leftover;
504
505                 /* We're happy with this size: take it. */
506                 ecode = remove_from_list(tdb, b_off, best_off, &best);
507                 if (ecode != TDB_SUCCESS) {
508                         goto unlock_err;
509                 }
510
511                 leftover = record_leftover(keylen, datalen, want_extra,
512                                            frec_len(&best));
513
514                 assert(keylen + datalen + leftover <= frec_len(&best));
515                 /* We need to mark non-free before we drop lock, otherwise
516                  * coalesce() could try to merge it! */
517                 ecode = set_header(tdb, &rec, magic, keylen, datalen,
518                                    frec_len(&best) - leftover, hashlow);
519                 if (ecode != TDB_SUCCESS) {
520                         goto unlock_err;
521                 }
522
523                 ecode = tdb_write_convert(tdb, best_off, &rec, sizeof(rec));
524                 if (ecode != TDB_SUCCESS) {
525                         goto unlock_err;
526                 }
527
528                 /* Bucket of leftover will be <= current bucket, so nested
529                  * locking is allowed. */
530                 if (leftover) {
531                         add_stat(tdb, alloc_leftover, 1);
532                         ecode = add_free_record(tdb,
533                                                 best_off + sizeof(rec)
534                                                 + frec_len(&best) - leftover,
535                                                 leftover);
536                         if (ecode != TDB_SUCCESS) {
537                                 best_off = ecode;
538                         }
539                 }
540                 tdb_unlock_free_bucket(tdb, b_off);
541
542                 return best_off;
543         }
544
545         tdb_unlock_free_bucket(tdb, b_off);
546         return 0;
547
548 unlock_err:
549         tdb_unlock_free_bucket(tdb, b_off);
550         return ecode;
551 }
552
553 /* Get a free block from current free list, or 0 if none, -ve on error. */
554 static tdb_off_t get_free(struct tdb_context *tdb,
555                           size_t keylen, size_t datalen, bool want_extra,
556                           unsigned magic, unsigned hashlow)
557 {
558         tdb_off_t off, ftable_off;
559         tdb_off_t start_b, b, ftable;
560         bool wrapped = false;
561
562         /* If they are growing, add 50% to get to higher bucket. */
563         if (want_extra)
564                 start_b = size_to_bucket(adjust_size(keylen,
565                                                      datalen + datalen / 2));
566         else
567                 start_b = size_to_bucket(adjust_size(keylen, datalen));
568
569         ftable_off = tdb->ftable_off;
570         ftable = tdb->ftable;
571         while (!wrapped || ftable_off != tdb->ftable_off) {
572                 /* Start at exact size bucket, and search up... */
573                 for (b = find_free_head(tdb, ftable_off, start_b);
574                      b < TDB_FREE_BUCKETS;
575                      b = find_free_head(tdb, ftable_off, b + 1)) {
576                         /* Try getting one from list. */
577                         off = lock_and_alloc(tdb, ftable_off,
578                                              b, keylen, datalen, want_extra,
579                                              magic, hashlow);
580                         if (TDB_OFF_IS_ERR(off))
581                                 return off;
582                         if (off != 0) {
583                                 if (b == start_b)
584                                         add_stat(tdb, alloc_bucket_exact, 1);
585                                 if (b == TDB_FREE_BUCKETS - 1)
586                                         add_stat(tdb, alloc_bucket_max, 1);
587                                 /* Worked?  Stay using this list. */
588                                 tdb->ftable_off = ftable_off;
589                                 tdb->ftable = ftable;
590                                 return off;
591                         }
592                         /* Didn't work.  Try next bucket. */
593                 }
594
595                 if (TDB_OFF_IS_ERR(b)) {
596                         return b;
597                 }
598
599                 /* Hmm, try next table. */
600                 ftable_off = next_ftable(tdb, ftable_off);
601                 if (TDB_OFF_IS_ERR(ftable_off)) {
602                         return ftable_off;
603                 }
604                 ftable++;
605
606                 if (ftable_off == 0) {
607                         wrapped = true;
608                         ftable_off = first_ftable(tdb);
609                         if (TDB_OFF_IS_ERR(ftable_off)) {
610                                 return ftable_off;
611                         }
612                         ftable = 0;
613                 }
614         }
615
616         return 0;
617 }
618
619 enum TDB_ERROR set_header(struct tdb_context *tdb,
620                           struct tdb_used_record *rec,
621                           unsigned magic, uint64_t keylen, uint64_t datalen,
622                           uint64_t actuallen, unsigned hashlow)
623 {
624         uint64_t keybits = (fls64(keylen) + 1) / 2;
625
626         /* Use bottom bits of hash, so it's independent of hash table size. */
627         rec->magic_and_meta = (hashlow & ((1 << 11)-1))
628                 | ((actuallen - (keylen + datalen)) << 11)
629                 | (keybits << 43)
630                 | ((uint64_t)magic << 48);
631         rec->key_and_data_len = (keylen | (datalen << (keybits*2)));
632
633         /* Encoding can fail on big values. */
634         if (rec_key_length(rec) != keylen
635             || rec_data_length(rec) != datalen
636             || rec_extra_padding(rec) != actuallen - (keylen + datalen)) {
637                 return tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
638                                   "Could not encode k=%llu,d=%llu,a=%llu",
639                                   (long long)keylen, (long long)datalen,
640                                   (long long)actuallen);
641         }
642         return TDB_SUCCESS;
643 }
644
645 /* Expand the database. */
646 static enum TDB_ERROR tdb_expand(struct tdb_context *tdb, tdb_len_t size)
647 {
648         uint64_t old_size;
649         tdb_len_t wanted;
650         enum TDB_ERROR ecode;
651
652         /* We need room for the record header too. */
653         wanted = sizeof(struct tdb_used_record) + size;
654
655         /* Need to hold a hash lock to expand DB: transactions rely on it. */
656         if (!(tdb->flags & TDB_NOLOCK)
657             && !tdb->allrecord_lock.count && !tdb_has_hash_locks(tdb)) {
658                 return tdb_logerr(tdb, TDB_ERR_LOCK, TDB_LOG_ERROR,
659                                   "tdb_expand: must hold lock during expand");
660         }
661
662         /* always make room for at least 100 more records, and at
663            least 25% more space. */
664         if (size * TDB_EXTENSION_FACTOR > tdb->map_size / 4)
665                 wanted = size * TDB_EXTENSION_FACTOR;
666         else
667                 wanted = tdb->map_size / 4;
668         wanted = adjust_size(0, wanted);
669
670         /* Only one person can expand file at a time. */
671         ecode = tdb_lock_expand(tdb, F_WRLCK);
672         if (ecode != TDB_SUCCESS) {
673                 return ecode;
674         }
675
676         /* Someone else may have expanded the file, so retry. */
677         old_size = tdb->map_size;
678         tdb->methods->oob(tdb, tdb->map_size + 1, true);
679         if (tdb->map_size != old_size) {
680                 tdb_unlock_expand(tdb, F_WRLCK);
681                 return TDB_SUCCESS;
682         }
683
684         ecode = tdb->methods->expand_file(tdb, wanted);
685         if (ecode != TDB_SUCCESS) {
686                 tdb_unlock_expand(tdb, F_WRLCK);
687                 return ecode;
688         }
689
690         /* We need to drop this lock before adding free record. */
691         tdb_unlock_expand(tdb, F_WRLCK);
692
693         add_stat(tdb, expands, 1);
694         return add_free_record(tdb, old_size, wanted);
695 }
696
697 /* This won't fail: it will expand the database if it has to. */
698 tdb_off_t alloc(struct tdb_context *tdb, size_t keylen, size_t datalen,
699                 uint64_t hash, unsigned magic, bool growing)
700 {
701         tdb_off_t off;
702
703         /* We can't hold pointers during this: we could unmap! */
704         assert(!tdb->direct_access);
705
706         for (;;) {
707                 enum TDB_ERROR ecode;
708                 off = get_free(tdb, keylen, datalen, growing, magic, hash);
709                 if (likely(off != 0))
710                         break;
711
712                 ecode = tdb_expand(tdb, adjust_size(keylen, datalen));
713                 if (ecode != TDB_SUCCESS) {
714                         return ecode;
715                 }
716         }
717
718         return off;
719 }