summaryrefslogtreecommitdiff
path: root/lib/tdb
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2021-12-13 17:42:12 +0100
committerJeremy Allison <jra@samba.org>2021-12-15 00:15:33 +0000
commitb9f06ab3472352d064082a44f7d5077c8c13931c (patch)
tree8b35db050632ef94bd9c9e89c5d65e99787f49fe /lib/tdb
parent62dab3921b335d47a0c9c419714d0e2ea2320f74 (diff)
downloadsamba-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.c24
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;
}