Re: [PATCH v5 2/4] apparmor: exponential backoff on cache buffer contention

From: John Johansen
Date: Tue Oct 17 2023 - 05:24:32 EST


Reduce contention on the global buffers lock by using an exponential
back off strategy where the amount tries to hold is doubled when
contention is encoutered and backed off linearly when there isn't
contention.

Signed-off-by: John Johansen <john.johansen@xxxxxxxxxxxxx>
---
security/apparmor/lsm.c | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index ce4f3e7a784d..fd6779ff0da4 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -50,6 +50,7 @@ union aa_buffer {
};
struct aa_local_cache {
+ unsigned int contention;
unsigned int hold;
unsigned int count;
struct list_head head;
@@ -1793,6 +1794,14 @@ static int param_set_mode(const char *val, const struct kernel_param *kp)
return 0;
}
+static void update_contention(struct aa_local_cache *cache)
+{
+ cache->contention += 1;
+ if (cache->contention > 9)
+ cache->contention = 9;
+ cache->hold += 1 << cache->contention; /* 2, 4, 8, ... */
+}
+
char *aa_get_buffer(bool in_atomic)
{
union aa_buffer *aa_buf;
@@ -1814,11 +1823,13 @@ char *aa_get_buffer(bool in_atomic)
if (!spin_trylock(&aa_buffers_lock)) {
cache = get_cpu_ptr(&aa_local_buffers);
- cache->hold += 1;
+ update_contention(cache);
put_cpu_ptr(&aa_local_buffers);
spin_lock(&aa_buffers_lock);
} else {
cache = get_cpu_ptr(&aa_local_buffers);
+ if (cache->contention)
+ cache->contention--;
put_cpu_ptr(&aa_local_buffers);
}
retry:
@@ -1875,12 +1886,14 @@ void aa_put_buffer(char *buf)
buffer_count++;
spin_unlock(&aa_buffers_lock);
cache = get_cpu_ptr(&aa_local_buffers);
+ if (cache->contention)
+ cache->contention--;
put_cpu_ptr(&aa_local_buffers);
return;
}
/* contention on global list, fallback to percpu */
cache = get_cpu_ptr(&aa_local_buffers);
- cache->hold += 1;
+ update_contention(cache);
}
/* cache in percpu list */
@@ -1933,6 +1946,7 @@ static int __init alloc_buffers(void)
* lock contention
*/
for_each_possible_cpu(i) {
+ per_cpu(aa_local_buffers, i).contention = 0;
per_cpu(aa_local_buffers, i).hold = 0;
per_cpu(aa_local_buffers, i).count = 0;
INIT_LIST_HEAD(&per_cpu(aa_local_buffers, i).head);
--
2.34.1