diff options
Diffstat (limited to 'lib/stackdepot.c')
| -rw-r--r-- | lib/stackdepot.c | 29 | 
1 files changed, 24 insertions, 5 deletions
| diff --git a/lib/stackdepot.c b/lib/stackdepot.c index e73fda23388d..79e894cf8406 100644 --- a/lib/stackdepot.c +++ b/lib/stackdepot.c @@ -43,7 +43,8 @@  #define STACK_ALLOC_OFFSET_BITS (STACK_ALLOC_ORDER + PAGE_SHIFT - \  					STACK_ALLOC_ALIGN)  #define STACK_ALLOC_INDEX_BITS (DEPOT_STACK_BITS - \ -		STACK_ALLOC_NULL_PROTECTION_BITS - STACK_ALLOC_OFFSET_BITS) +		STACK_ALLOC_NULL_PROTECTION_BITS - \ +		STACK_ALLOC_OFFSET_BITS - STACK_DEPOT_EXTRA_BITS)  #define STACK_ALLOC_SLABS_CAP 8192  #define STACK_ALLOC_MAX_SLABS \  	(((1LL << (STACK_ALLOC_INDEX_BITS)) < STACK_ALLOC_SLABS_CAP) ? \ @@ -56,6 +57,7 @@ union handle_parts {  		u32 slabindex : STACK_ALLOC_INDEX_BITS;  		u32 offset : STACK_ALLOC_OFFSET_BITS;  		u32 valid : STACK_ALLOC_NULL_PROTECTION_BITS; +		u32 extra : STACK_DEPOT_EXTRA_BITS;  	};  }; @@ -77,6 +79,14 @@ static int next_slab_inited;  static size_t depot_offset;  static DEFINE_RAW_SPINLOCK(depot_lock); +unsigned int stack_depot_get_extra_bits(depot_stack_handle_t handle) +{ +	union handle_parts parts = { .handle = handle }; + +	return parts.extra; +} +EXPORT_SYMBOL(stack_depot_get_extra_bits); +  static bool init_stack_slab(void **prealloc)  {  	if (!*prealloc) @@ -140,6 +150,7 @@ depot_alloc_stack(unsigned long *entries, int size, u32 hash, void **prealloc)  	stack->handle.slabindex = depot_index;  	stack->handle.offset = depot_offset >> STACK_ALLOC_ALIGN;  	stack->handle.valid = 1; +	stack->handle.extra = 0;  	memcpy(stack->entries, entries, flex_array_size(stack, entries, size));  	depot_offset += required_size; @@ -382,6 +393,7 @@ EXPORT_SYMBOL_GPL(stack_depot_fetch);   *   * @entries:		Pointer to storage array   * @nr_entries:		Size of the storage array + * @extra_bits:		Flags to store in unused bits of depot_stack_handle_t   * @alloc_flags:	Allocation gfp flags   * @can_alloc:		Allocate stack slabs (increased chance of failure if false)   * @@ -393,6 +405,10 @@ EXPORT_SYMBOL_GPL(stack_depot_fetch);   * If the stack trace in @entries is from an interrupt, only the portion up to   * interrupt entry is saved.   * + * Additional opaque flags can be passed in @extra_bits, stored in the unused + * bits of the stack handle, and retrieved using stack_depot_get_extra_bits() + * without calling stack_depot_fetch(). + *   * 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 @@ -402,10 +418,11 @@ EXPORT_SYMBOL_GPL(stack_depot_fetch);   */  depot_stack_handle_t __stack_depot_save(unsigned long *entries,  					unsigned int nr_entries, +					unsigned int extra_bits,  					gfp_t alloc_flags, bool can_alloc)  {  	struct stack_record *found = NULL, **bucket; -	depot_stack_handle_t retval = 0; +	union handle_parts retval = { .handle = 0 };  	struct page *page = NULL;  	void *prealloc = NULL;  	unsigned long flags; @@ -489,9 +506,11 @@ exit:  		free_pages((unsigned long)prealloc, STACK_ALLOC_ORDER);  	}  	if (found) -		retval = found->handle.handle; +		retval.handle = found->handle.handle;  fast_exit: -	return retval; +	retval.extra = extra_bits; + +	return retval.handle;  }  EXPORT_SYMBOL_GPL(__stack_depot_save); @@ -511,6 +530,6 @@ 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); +	return __stack_depot_save(entries, nr_entries, 0, alloc_flags, true);  }  EXPORT_SYMBOL_GPL(stack_depot_save); | 
