assert(keylen + datalen + leftover <= best.data_len);
/* We need to mark non-free before we drop lock, otherwise
* coalesce() could try to merge it! */
- if (set_header(tdb, &rec, keylen, datalen,
- best.data_len - leftover,
- hashlow) != 0)
+ if (set_used_header(tdb, &rec, keylen, datalen,
+ best.data_len - leftover,
+ hashlow) != 0)
goto unlock_err;
if (tdb_write_convert(tdb, best_off, &rec, sizeof(rec)) != 0)
return 0;
}
-int set_header(struct tdb_context *tdb,
- struct tdb_used_record *rec,
- uint64_t keylen, uint64_t datalen,
- uint64_t actuallen, unsigned hashlow)
+int set_used_header(struct tdb_context *tdb,
+ struct tdb_used_record *rec,
+ uint64_t keylen, uint64_t datalen,
+ uint64_t actuallen, unsigned hashlow)
{
uint64_t keybits = (fls64(keylen) + 1) / 2;
/* We need room for the record header too. */
wanted = sizeof(struct tdb_used_record) + size;
+ /* Need to hold a hash lock to expand DB: transactions rely on it. */
+ if (!(tdb->flags & TDB_NOLOCK)
+ && !tdb->allrecord_lock.count && !tdb_has_hash_locks(tdb)) {
+ tdb->log(tdb, TDB_DEBUG_FATAL, tdb->log_priv,
+ "tdb_expand: must hold lock during expand\n");
+ return -1;
+ }
+
/* Only one person can expand file at a time. */
if (tdb_lock_expand(tdb, F_WRLCK) != 0)
return -1;