From 6820ae9279eb56def95f694f9a1ac921eeffcb08 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 24 Nov 2019 08:31:42 +0100 Subject: [PATCH] tdb: Only create dead records under freelist contention When TDB_VOLATILE was invented, even looking at the freelist in a nonblocking fashion created an expensive fcntl lock. So we always create dead records, to avoid even the nonblocking freelist lock. Doing a nonblocking mutex lock is much cheaper. With this patch records are moved to the freelist without creating dead records. This shrinks the database size on lightly loaded systems significantly. Signed-off-by: Volker Lendecke --- lib/tdb/common/tdb.c | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/lib/tdb/common/tdb.c b/lib/tdb/common/tdb.c index c56b37be5ca..6c1b1f0f2b4 100644 --- a/lib/tdb/common/tdb.c +++ b/lib/tdb/common/tdb.c @@ -418,6 +418,17 @@ int tdb_trim_dead(struct tdb_context *tdb, uint32_t hash) return -1; } + /* + * Try to lock the freelist in a nonblocking way. In the loop + * below this means that if the freelist is not contended, we + * directly free all dead records. + */ + + ret = tdb_lock_nonblock(tdb, -1, F_WRLCK); + if (ret == 0) { + locked_freelist = true; + } + while (rec_ptr != 0) { bool deleted = false; uint32_t next; @@ -438,20 +449,20 @@ int tdb_trim_dead(struct tdb_context *tdb, uint32_t hash) if (rec.magic == TDB_DEAD_MAGIC) { num_dead += 1; - if (num_dead > tdb->max_dead_records) { - - if (!locked_freelist) { - /* - * Lock the freelist only if - * it's really required. - */ - ret = tdb_lock(tdb, -1, F_WRLCK); - if (ret == -1) { - goto fail; - }; - locked_freelist = true; - } + if ((num_dead > tdb->max_dead_records) && + !locked_freelist) { + /* + * Lock the freelist only if it's + * really required. + */ + ret = tdb_lock(tdb, -1, F_WRLCK); + if (ret == -1) { + goto fail; + }; + locked_freelist = true; + } + if (locked_freelist) { ret = tdb_del_dead( tdb, last_ptr, -- 2.20.1