git: 23b46b2bbf0a - main - audit: convert audit event class lookup to lockless
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 27 Oct 2025 14:15:09 UTC
The branch main has been updated by gallatin:
URL: https://cgit.FreeBSD.org/src/commit/?id=23b46b2bbf0a8f3a740b6e5baf0767816afc339e
commit 23b46b2bbf0a8f3a740b6e5baf0767816afc339e
Author: Andrew Gallatin <gallatin@FreeBSD.org>
AuthorDate: 2025-10-27 14:05:49 +0000
Commit: Andrew Gallatin <gallatin@FreeBSD.org>
CommitDate: 2025-10-27 14:15:01 +0000
audit: convert audit event class lookup to lockless
When system call auditing is enabled, every audited call
does a lookup in the evclass hash table. This table
appears to be insert only (eg, nothing can be removed)
and protecting it with an rwlock is overkill. Using
an rwlock causes just the atomic operations to maintain
uncontended rwlock state to be responsible for measurable
overhead on high core count servers making lots of system calls.
Given that the evclass hash table can never have items removed,
only added, using a mutex to serialize additions and converting
to ck_list allows sufficient protection for lockless lookups.
In a contrived example of 64 cores, all reading 1 byte from their
own file, this change increases performance from 5M reads/sec
to 70M reads/sec on an AMD 7502P.
Reviewed by: markj, mjg, glebius (privately)
Sponsored by: Netflix
Differential Revision: https://reviews.freebsd.org/D53176
---
sys/security/audit/audit_bsm_db.c | 28 +++++++++++++++-------------
1 file changed, 15 insertions(+), 13 deletions(-)
diff --git a/sys/security/audit/audit_bsm_db.c b/sys/security/audit/audit_bsm_db.c
index c9f3d5c8a549..358162544287 100644
--- a/sys/security/audit/audit_bsm_db.c
+++ b/sys/security/audit/audit_bsm_db.c
@@ -56,6 +56,8 @@
#include <security/audit/audit.h>
#include <security/audit/audit_private.h>
+#include <contrib/ck/include/ck_queue.h>
+
/*
* Hash table functions for the audit event number to event class mask
* mapping.
@@ -64,21 +66,21 @@
struct evclass_elem {
au_event_t event;
au_class_t class;
- LIST_ENTRY(evclass_elem) entry;
+ CK_LIST_ENTRY(evclass_elem) entry;
};
struct evclass_list {
- LIST_HEAD(, evclass_elem) head;
+ CK_LIST_HEAD(, evclass_elem) head;
};
static MALLOC_DEFINE(M_AUDITEVCLASS, "audit_evclass", "Audit event class");
-static struct rwlock evclass_lock;
static struct evclass_list evclass_hash[EVCLASSMAP_HASH_TABLE_SIZE];
-
-#define EVCLASS_LOCK_INIT() rw_init(&evclass_lock, "evclass_lock")
-#define EVCLASS_RLOCK() rw_rlock(&evclass_lock)
-#define EVCLASS_RUNLOCK() rw_runlock(&evclass_lock)
-#define EVCLASS_WLOCK() rw_wlock(&evclass_lock)
-#define EVCLASS_WUNLOCK() rw_wunlock(&evclass_lock)
+static struct mtx evclass_mtx;
+#define EVCLASS_LOCK_INIT() mtx_init(&evclass_mtx, "evclass_lock", NULL, MTX_DEF)
+#define EVCLASS_WLOCK() mtx_lock(&evclass_mtx);
+#define EVCLASS_WUNLOCK() mtx_unlock(&evclass_mtx);
+/* make these do something if we ever remove entries from the hash */
+#define EVCLASS_RLOCK() {}
+#define EVCLASS_RUNLOCK() {}
/*
* Hash table maintaining a mapping from audit event numbers to audit event
@@ -118,7 +120,7 @@ au_event_class(au_event_t event)
EVCLASS_RLOCK();
evcl = &evclass_hash[event % EVCLASSMAP_HASH_TABLE_SIZE];
class = 0;
- LIST_FOREACH(evc, &evcl->head, entry) {
+ CK_LIST_FOREACH(evc, &evcl->head, entry) {
if (evc->event == event) {
class = evc->class;
goto out;
@@ -150,7 +152,7 @@ au_evclassmap_insert(au_event_t event, au_class_t class)
EVCLASS_WLOCK();
evcl = &evclass_hash[event % EVCLASSMAP_HASH_TABLE_SIZE];
- LIST_FOREACH(evc, &evcl->head, entry) {
+ CK_LIST_FOREACH(evc, &evcl->head, entry) {
if (evc->event == event) {
evc->class = class;
EVCLASS_WUNLOCK();
@@ -161,7 +163,7 @@ au_evclassmap_insert(au_event_t event, au_class_t class)
evc = evc_new;
evc->event = event;
evc->class = class;
- LIST_INSERT_HEAD(&evcl->head, evc, entry);
+ CK_LIST_INSERT_HEAD(&evcl->head, evc, entry);
EVCLASS_WUNLOCK();
}
@@ -172,7 +174,7 @@ au_evclassmap_init(void)
EVCLASS_LOCK_INIT();
for (i = 0; i < EVCLASSMAP_HASH_TABLE_SIZE; i++)
- LIST_INIT(&evclass_hash[i].head);
+ CK_LIST_INIT(&evclass_hash[i].head);
/*
* Set up the initial event to class mapping for system calls.