Use kmem_cache to replace kzalloc() calls with kmem_cache_zalloc() for
structs landlock_object, landlock_rule and landlock_hierarchy and
update the related dependencies to improve memory allocation and
deallocation performance. This patch does not change kfree() and
kfree_rcu() calls because according to kernel commit
ae65a5211d90("mm/slab: document kfree() as allowed for
kmem_cache_alloc() objects"), starting from kernel 6.4, kfree() is
safe to use for such objects. Use clang-format to format the code
to the kernel style. /proc/slabinfo shows decrease in
'ext4_inode_cache' and 'dentry' usage suggesting a significant
reduction in file system related object and memory allocations and
increase in kmem_cache and kmalloc usage also indicates more cache
allocation for objects for efficient memory handling.
Signed-off-by: Ayush Tiwari <[email protected]>
---
security/landlock/object.c | 12 +++++++++++-
security/landlock/object.h | 2 ++
security/landlock/ruleset.c | 18 +++++++++++++++---
security/landlock/ruleset.h | 2 ++
security/landlock/setup.c | 4 ++++
5 files changed, 34 insertions(+), 4 deletions(-)
diff --git a/security/landlock/object.c b/security/landlock/object.c
index 1f50612f0185..cfc367725624 100644
--- a/security/landlock/object.c
+++ b/security/landlock/object.c
@@ -17,6 +17,15 @@
#include "object.h"
+static struct kmem_cache *landlock_object_cache;
+
+void __init landlock_object_cache_init(void)
+{
+ landlock_object_cache = kmem_cache_create(
+ "landlock_object_cache", sizeof(struct landlock_object), 0,
+ SLAB_PANIC, NULL);
+}
+
struct landlock_object *
landlock_create_object(const struct landlock_object_underops *const underops,
void *const underobj)
@@ -25,7 +34,8 @@ landlock_create_object(const struct landlock_object_underops *const underops,
if (WARN_ON_ONCE(!underops || !underobj))
return ERR_PTR(-ENOENT);
- new_object = kzalloc(sizeof(*new_object), GFP_KERNEL_ACCOUNT);
+ new_object =
+ kmem_cache_zalloc(landlock_object_cache, GFP_KERNEL_ACCOUNT);
if (!new_object)
return ERR_PTR(-ENOMEM);
refcount_set(&new_object->usage, 1);
diff --git a/security/landlock/object.h b/security/landlock/object.h
index 5f28c35e8aa8..d9967ef16ec1 100644
--- a/security/landlock/object.h
+++ b/security/landlock/object.h
@@ -15,6 +15,8 @@
struct landlock_object;
+void __init landlock_object_cache_init(void);
+
/**
* struct landlock_object_underops - Operations on an underlying object
*/
diff --git a/security/landlock/ruleset.c b/security/landlock/ruleset.c
index e0a5fbf9201a..0f8a9994f5fa 100644
--- a/security/landlock/ruleset.c
+++ b/security/landlock/ruleset.c
@@ -24,6 +24,19 @@
#include "object.h"
#include "ruleset.h"
+static struct kmem_cache *landlock_hierarchy_cache;
+static struct kmem_cache *landlock_rule_cache;
+
+void __init landlock_ruleset_cache_init(void)
+{
+ landlock_hierarchy_cache = kmem_cache_create(
+ "landlock_hierarchy_cache", sizeof(struct landlock_hierarchy),
+ 0, SLAB_PANIC, NULL);
+ landlock_rule_cache = kmem_cache_create("landlock_rule_cache",
+ sizeof(struct landlock_rule), 0,
+ SLAB_PANIC, NULL);
+}
+
static struct landlock_ruleset *create_ruleset(const u32 num_layers)
{
struct landlock_ruleset *new_ruleset;
@@ -112,8 +125,7 @@ create_rule(const struct landlock_id id,
} else {
new_num_layers = num_layers;
}
- new_rule = kzalloc(struct_size(new_rule, layers, new_num_layers),
- GFP_KERNEL_ACCOUNT);
+ new_rule = kmem_cache_zalloc(landlock_rule_cache, GFP_KERNEL_ACCOUNT);
if (!new_rule)
return ERR_PTR(-ENOMEM);
RB_CLEAR_NODE(&new_rule->node);
@@ -559,7 +571,7 @@ landlock_merge_ruleset(struct landlock_ruleset *const parent,
if (IS_ERR(new_dom))
return new_dom;
new_dom->hierarchy =
- kzalloc(sizeof(*new_dom->hierarchy), GFP_KERNEL_ACCOUNT);
+ kmem_cache_zalloc(landlock_hierarchy_cache, GFP_KERNEL_ACCOUNT);
if (!new_dom->hierarchy) {
err = -ENOMEM;
goto out_put_dom;
diff --git a/security/landlock/ruleset.h b/security/landlock/ruleset.h
index c7f1526784fd..f738e8b0cf9b 100644
--- a/security/landlock/ruleset.h
+++ b/security/landlock/ruleset.h
@@ -30,6 +30,8 @@
LANDLOCK_ACCESS_FS_REFER)
/* clang-format on */
+void __init landlock_ruleset_cache_init(void);
+
typedef u16 access_mask_t;
/* Makes sure all filesystem access rights can be stored. */
static_assert(BITS_PER_TYPE(access_mask_t) >= LANDLOCK_NUM_ACCESS_FS);
diff --git a/security/landlock/setup.c b/security/landlock/setup.c
index f6dd33143b7f..a4904d00cbe6 100644
--- a/security/landlock/setup.c
+++ b/security/landlock/setup.c
@@ -16,6 +16,8 @@
#include "net.h"
#include "ptrace.h"
#include "setup.h"
+#include "object.h"
+#include "ruleset.h"
bool landlock_initialized __ro_after_init = false;
@@ -33,6 +35,8 @@ const struct lsm_id landlock_lsmid = {
static int __init landlock_init(void)
{
+ landlock_object_cache_init();
+ landlock_ruleset_cache_init();
landlock_add_cred_hooks();
landlock_add_ptrace_hooks();
landlock_add_fs_hooks();
--
2.40.1