diff options
author | Volker Lendecke <vl@samba.org> | 2021-12-13 17:42:12 +0100 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2021-12-15 00:15:33 +0000 |
commit | b9f06ab3472352d064082a44f7d5077c8c13931c (patch) | |
tree | 8b35db050632ef94bd9c9e89c5d65e99787f49fe /lib/tdb | |
parent | 62dab3921b335d47a0c9c419714d0e2ea2320f74 (diff) | |
download | samba-b9f06ab3472352d064082a44f7d5077c8c13931c.tar.gz |
tdb: Use atomic operations for tdb_[increment|get]_seqnum
With locking.tdb now based on g_lock.c code, we change locking.tdb a
lot more often. I have a customer case where LDX tortures smbd very
hard with 800+ concurrent connections, which now completely falls over
where 4.12 still worked fine. Some debugging showed a thundering herd
on fcntl locking.tdb index 48 (TDB_SEQNUM_OFS). We still use fcntl for
the seqnum, back when we converted the chainlocks to mutexes we did
not consider it to be a problem. Now it is, but all we need to do with
the SEQNUM is to increment it, so an __atomic_add_fetch() of one is
sufficient.
I've taken a look at the C11 standard atomics, but I could not figure
out how to use them properly, to me they seem more general to be
initialized first etc. All we need is a X86 "lock incl 48(%rax)" to be
emitted, and the gcc __atomic_add_fetch seems to do this.
Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
Diffstat (limited to 'lib/tdb')
-rw-r--r-- | lib/tdb/common/tdb.c | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/lib/tdb/common/tdb.c b/lib/tdb/common/tdb.c index c56b37be5ca..de829bb48c4 100644 --- a/lib/tdb/common/tdb.c +++ b/lib/tdb/common/tdb.c @@ -64,6 +64,15 @@ static void tdb_increment_seqnum(struct tdb_context *tdb) return; } +#if defined(HAVE___ATOMIC_ADD_FETCH) && defined(HAVE___ATOMIC_ADD_LOAD) + if (tdb->map_ptr != NULL) { + uint32_t *pseqnum = (uint32_t *)( + TDB_SEQNUM_OFS + (char *)tdb->map_ptr); + __atomic_add_fetch(pseqnum, 1, __ATOMIC_SEQ_CST); + return; + } +#endif + if (tdb_nest_lock(tdb, TDB_SEQNUM_OFS, F_WRLCK, TDB_LOCK_WAIT|TDB_LOCK_PROBE) != 0) { return; @@ -838,6 +847,21 @@ _PUBLIC_ int tdb_get_seqnum(struct tdb_context *tdb) { tdb_off_t seqnum=0; + if (tdb->transaction != NULL) { + tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum); + return seqnum; + } + +#if defined(HAVE___ATOMIC_ADD_FETCH) && defined(HAVE___ATOMIC_ADD_LOAD) + if (tdb->map_ptr != NULL) { + uint32_t *pseqnum = (uint32_t *)( + TDB_SEQNUM_OFS + (char *)tdb->map_ptr); + uint32_t ret; + __atomic_load(pseqnum, &ret,__ATOMIC_SEQ_CST); + return ret; + } +#endif + tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum); return seqnum; } |