]> Git Repo - linux.git/commitdiff
lib/stackdepot: introduce __stack_depot_save()
authorMarco Elver <[email protected]>
Fri, 5 Nov 2021 20:35:39 +0000 (13:35 -0700)
committerLinus Torvalds <[email protected]>
Sat, 6 Nov 2021 20:30:33 +0000 (13:30 -0700)
Add __stack_depot_save(), which provides more fine-grained control over
stackdepot's memory allocation behaviour, in case stackdepot runs out of
"stack slabs".

Normally stackdepot uses alloc_pages() in case it runs out of space;
passing can_alloc==false to __stack_depot_save() prohibits this, at the
cost of more likely failure to record a stack trace.

Link: https://lkml.kernel.org/r/[email protected]
Signed-off-by: Marco Elver <[email protected]>
Tested-by: Shuah Khan <[email protected]>
Acked-by: Sebastian Andrzej Siewior <[email protected]>
Reviewed-by: Andrey Konovalov <[email protected]>
Cc: Alexander Potapenko <[email protected]>
Cc: Andrey Ryabinin <[email protected]>
Cc: Dmitry Vyukov <[email protected]>
Cc: "Gustavo A. R. Silva" <[email protected]>
Cc: Lai Jiangshan <[email protected]>
Cc: Taras Madan <[email protected]>
Cc: Tejun Heo <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Vijayanand Jitta <[email protected]>
Cc: Vinayak Menon <[email protected]>
Cc: Walter Wu <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
include/linux/stackdepot.h
lib/stackdepot.c

index 97b36dc53301d39e7ed4b6daa024b6aabdac5177..b2f7e7c6ba54d57c4953da0f03a2dc7d8c2c852f 100644 (file)
 
 typedef u32 depot_stack_handle_t;
 
+depot_stack_handle_t __stack_depot_save(unsigned long *entries,
+                                       unsigned int nr_entries,
+                                       gfp_t gfp_flags, bool can_alloc);
+
 depot_stack_handle_t stack_depot_save(unsigned long *entries,
                                      unsigned int nr_entries, gfp_t gfp_flags);
 
index c80a9f7342537e3b35dba9d2fe6553673bdd0382..bda58597e3756d30122f9d1ea6a5f7e16a27bba5 100644 (file)
@@ -248,17 +248,28 @@ unsigned int stack_depot_fetch(depot_stack_handle_t handle,
 EXPORT_SYMBOL_GPL(stack_depot_fetch);
 
 /**
- * stack_depot_save - Save a stack trace from an array
+ * __stack_depot_save - Save a stack trace from an array
  *
  * @entries:           Pointer to storage array
  * @nr_entries:                Size of the storage array
  * @alloc_flags:       Allocation gfp flags
+ * @can_alloc:         Allocate stack slabs (increased chance of failure if false)
+ *
+ * Saves a stack trace from @entries array of size @nr_entries. If @can_alloc is
+ * %true, is allowed to replenish the stack slab pool in case no space is left
+ * (allocates using GFP flags of @alloc_flags). If @can_alloc is %false, avoids
+ * any allocations and will fail if no space is left to store the stack trace.
+ *
+ * Context: Any context, but setting @can_alloc to %false is required if
+ *          alloc_pages() cannot be used from the current context. Currently
+ *          this is the case from contexts where neither %GFP_ATOMIC nor
+ *          %GFP_NOWAIT can be used (NMI, raw_spin_lock).
  *
- * Return: The handle of the stack struct stored in depot
+ * Return: The handle of the stack struct stored in depot, 0 on failure.
  */
-depot_stack_handle_t stack_depot_save(unsigned long *entries,
-                                     unsigned int nr_entries,
-                                     gfp_t alloc_flags)
+depot_stack_handle_t __stack_depot_save(unsigned long *entries,
+                                       unsigned int nr_entries,
+                                       gfp_t alloc_flags, bool can_alloc)
 {
        struct stack_record *found = NULL, **bucket;
        depot_stack_handle_t retval = 0;
@@ -291,7 +302,7 @@ depot_stack_handle_t stack_depot_save(unsigned long *entries,
         * The smp_load_acquire() here pairs with smp_store_release() to
         * |next_slab_inited| in depot_alloc_stack() and init_stack_slab().
         */
-       if (unlikely(!smp_load_acquire(&next_slab_inited))) {
+       if (unlikely(can_alloc && !smp_load_acquire(&next_slab_inited))) {
                /*
                 * Zero out zone modifiers, as we don't have specific zone
                 * requirements. Keep the flags related to allocation in atomic
@@ -339,6 +350,26 @@ exit:
 fast_exit:
        return retval;
 }
+EXPORT_SYMBOL_GPL(__stack_depot_save);
+
+/**
+ * stack_depot_save - Save a stack trace from an array
+ *
+ * @entries:           Pointer to storage array
+ * @nr_entries:                Size of the storage array
+ * @alloc_flags:       Allocation gfp flags
+ *
+ * Context: Contexts where allocations via alloc_pages() are allowed.
+ *          See __stack_depot_save() for more details.
+ *
+ * Return: The handle of the stack struct stored in depot, 0 on failure.
+ */
+depot_stack_handle_t stack_depot_save(unsigned long *entries,
+                                     unsigned int nr_entries,
+                                     gfp_t alloc_flags)
+{
+       return __stack_depot_save(entries, nr_entries, alloc_flags, true);
+}
 EXPORT_SYMBOL_GPL(stack_depot_save);
 
 static inline int in_irqentry_text(unsigned long ptr)
This page took 0.067907 seconds and 4 git commands to generate.