lib/stackdepot: allow users to evict stack traces
Add stack_depot_put, a function that decrements the reference counter on a stack record and removes it from the stack depot once the counter reaches 0. Internally, when removing a stack record, the function unlinks it from the hash table bucket and returns to the freelist. With this change, the users of stack depot can call stack_depot_put when keeping a stack trace in the stack depot is not needed anymore. This allows avoiding polluting the stack depot with irrelevant stack traces and thus have more space to store the relevant ones before the stack depot reaches its capacity. Link: https://lkml.kernel.org/r/1d1ad5692ee43d4fc2b3fd9d221331d30b36123f.1700502145.git.andreyknvl@google.com Signed-off-by: Andrey Konovalov <andreyknvl@google.com> Cc: Alexander Potapenko <glider@google.com> Cc: Dmitry Vyukov <dvyukov@google.com> Cc: Evgenii Stepanov <eugenis@google.com> Cc: Marco Elver <elver@google.com> Cc: Oscar Salvador <osalvador@suse.de> Cc: Vlastimil Babka <vbabka@suse.cz> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
committed by
Andrew Morton
parent
410b764f89
commit
108be8def4
@@ -394,7 +394,7 @@ static struct stack_record *depot_fetch_stack(depot_stack_handle_t handle)
|
||||
size_t offset = parts.offset << DEPOT_STACK_ALIGN;
|
||||
struct stack_record *stack;
|
||||
|
||||
lockdep_assert_held_read(&pool_rwlock);
|
||||
lockdep_assert_held(&pool_rwlock);
|
||||
|
||||
if (parts.pool_index > pools_num) {
|
||||
WARN(1, "pool index %d out of bounds (%d) for stack id %08x\n",
|
||||
@@ -410,6 +410,14 @@ static struct stack_record *depot_fetch_stack(depot_stack_handle_t handle)
|
||||
return stack;
|
||||
}
|
||||
|
||||
/* Links stack into the freelist. */
|
||||
static void depot_free_stack(struct stack_record *stack)
|
||||
{
|
||||
lockdep_assert_held_write(&pool_rwlock);
|
||||
|
||||
list_add(&stack->list, &free_stacks);
|
||||
}
|
||||
|
||||
/* Calculates the hash for a stack. */
|
||||
static inline u32 hash_stack(unsigned long *entries, unsigned int size)
|
||||
{
|
||||
@@ -592,6 +600,33 @@ unsigned int stack_depot_fetch(depot_stack_handle_t handle,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(stack_depot_fetch);
|
||||
|
||||
void stack_depot_put(depot_stack_handle_t handle)
|
||||
{
|
||||
struct stack_record *stack;
|
||||
unsigned long flags;
|
||||
|
||||
if (!handle || stack_depot_disabled)
|
||||
return;
|
||||
|
||||
write_lock_irqsave(&pool_rwlock, flags);
|
||||
|
||||
stack = depot_fetch_stack(handle);
|
||||
if (WARN_ON(!stack))
|
||||
goto out;
|
||||
|
||||
if (refcount_dec_and_test(&stack->count)) {
|
||||
/* Unlink stack from the hash table. */
|
||||
list_del(&stack->list);
|
||||
|
||||
/* Free stack. */
|
||||
depot_free_stack(stack);
|
||||
}
|
||||
|
||||
out:
|
||||
write_unlock_irqrestore(&pool_rwlock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(stack_depot_put);
|
||||
|
||||
void stack_depot_print(depot_stack_handle_t stack)
|
||||
{
|
||||
unsigned long *entries;
|
||||
|
||||
Reference in New Issue
Block a user