Skip to content

Commit 410b764

Browse files
xairyakpm00
authored andcommitted
lib/stackdepot: add refcount for records
Add a reference counter for how many times a stack records has been added to stack depot. Add a new STACK_DEPOT_FLAG_GET flag to stack_depot_save_flags that instructs the stack depot to increment the refcount. Do not yet decrement the refcount; this is implemented in one of the following patches. Do not yet enable any users to use the flag to avoid overflowing the refcount. This is preparatory patch for implementing the eviction of stack records from the stack depot. Link: https://lkml.kernel.org/r/a3fc14a2359d019d2a008d4ff8b46a665371ffee.1700502145.git.andreyknvl@google.com Signed-off-by: Andrey Konovalov <[email protected]> Reviewed-by: Alexander Potapenko <[email protected]> Cc: Dmitry Vyukov <[email protected]> Cc: Evgenii Stepanov <[email protected]> Cc: Marco Elver <[email protected]> Cc: Oscar Salvador <[email protected]> Cc: Vlastimil Babka <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 022012d commit 410b764

File tree

2 files changed

+20
-5
lines changed

2 files changed

+20
-5
lines changed

include/linux/stackdepot.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,9 @@ typedef u32 depot_flags_t;
3939
* to its declaration for more details.
4040
*/
4141
#define STACK_DEPOT_FLAG_CAN_ALLOC ((depot_flags_t)0x0001)
42+
#define STACK_DEPOT_FLAG_GET ((depot_flags_t)0x0002)
4243

43-
#define STACK_DEPOT_FLAGS_NUM 1
44+
#define STACK_DEPOT_FLAGS_NUM 2
4445
#define STACK_DEPOT_FLAGS_MASK ((depot_flags_t)((1 << STACK_DEPOT_FLAGS_NUM) - 1))
4546

4647
/*
@@ -94,6 +95,9 @@ static inline int stack_depot_early_init(void) { return 0; }
9495
* flags of @alloc_flags). Otherwise, stack depot avoids any allocations and
9596
* fails if no space is left to store the stack trace.
9697
*
98+
* If STACK_DEPOT_FLAG_GET is set in @depot_flags, stack depot will increment
99+
* the refcount on the saved stack trace if it already exists in stack depot.
100+
*
97101
* If the provided stack trace comes from the interrupt context, only the part
98102
* up to the interrupt entry is saved.
99103
*
@@ -116,8 +120,11 @@ depot_stack_handle_t stack_depot_save_flags(unsigned long *entries,
116120
* @nr_entries: Number of frames in the stack
117121
* @alloc_flags: Allocation GFP flags
118122
*
119-
* Context: Contexts where allocations via alloc_pages() are allowed.
120-
* See stack_depot_save_flags() for more details.
123+
* Does not increment the refcount on the saved stack trace; see
124+
* stack_depot_save_flags() for more details.
125+
*
126+
* Context: Contexts where allocations via alloc_pages() are allowed;
127+
* see stack_depot_save_flags() for more details.
121128
*
122129
* Return: Handle of the stack trace stored in depot, 0 on failure
123130
*/

lib/stackdepot.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <linux/mutex.h>
2424
#include <linux/percpu.h>
2525
#include <linux/printk.h>
26+
#include <linux/refcount.h>
2627
#include <linux/slab.h>
2728
#include <linux/spinlock.h>
2829
#include <linux/stacktrace.h>
@@ -60,6 +61,7 @@ struct stack_record {
6061
u32 hash; /* Hash in hash table */
6162
u32 size; /* Number of stored frames */
6263
union handle_parts handle;
64+
refcount_t count;
6365
unsigned long entries[CONFIG_STACKDEPOT_MAX_FRAMES]; /* Frames */
6466
};
6567

@@ -373,6 +375,7 @@ depot_alloc_stack(unsigned long *entries, int size, u32 hash, void **prealloc)
373375
stack->hash = hash;
374376
stack->size = size;
375377
/* stack->handle is already filled in by depot_init_pool(). */
378+
refcount_set(&stack->count, 1);
376379
memcpy(stack->entries, entries, flex_array_size(stack, entries, size));
377380

378381
/*
@@ -489,6 +492,8 @@ depot_stack_handle_t stack_depot_save_flags(unsigned long *entries,
489492
/* Fast path: look the stack trace up without full locking. */
490493
found = find_stack(bucket, entries, nr_entries, hash);
491494
if (found) {
495+
if (depot_flags & STACK_DEPOT_FLAG_GET)
496+
refcount_inc(&found->count);
492497
read_unlock_irqrestore(&pool_rwlock, flags);
493498
goto exit;
494499
}
@@ -528,12 +533,15 @@ depot_stack_handle_t stack_depot_save_flags(unsigned long *entries,
528533
list_add(&new->list, bucket);
529534
found = new;
530535
}
531-
} else if (prealloc) {
536+
} else {
537+
if (depot_flags & STACK_DEPOT_FLAG_GET)
538+
refcount_inc(&found->count);
532539
/*
533540
* Stack depot already contains this stack trace, but let's
534541
* keep the preallocated memory for future.
535542
*/
536-
depot_keep_new_pool(&prealloc);
543+
if (prealloc)
544+
depot_keep_new_pool(&prealloc);
537545
}
538546

539547
write_unlock_irqrestore(&pool_rwlock, flags);

0 commit comments

Comments
 (0)