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

John Johansen john.johansen at canonical.com
Tue Oct 17 09:24:21 UTC 2023


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 at canonical.com>
---
  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




More information about the Linux-security-module-archive mailing list