A small set of updates for debug objects:
- Make all debug object descriptors constant. There is no reason to have them writeable. - Free the per CPU object pool after CPU unplug to avoid memory waste. -----BEGIN PGP SIGNATURE----- iQJHBAABCgAxFiEEQp8+kY+LLUocC4bMphj1TA10mKEFAl+EMM8THHRnbHhAbGlu dXRyb25peC5kZQAKCRCmGPVMDXSYobvLD/95P1eqk5Hku2uHeHowj9t4PVqk68Gq 71rJTj/x32JnGVsNFfwoqm0u8CueAitT1Id5aIjiMAGK2eH83StwdfqFjdHsitwl 4zH6qywjjgq86jOSXXUQ2TSyYjlL7l2Pr8jwEZkTXUrShZyHAOvD9oW3KwlyV88H QXiTGFAm4aAaFctgGlbVafxtp1IJkS+FzFT1/cyPV064d3uGjX6maKwKjssO/8Bv WLzPuyOKh7IoEMfyFEXw3Ks3GK3Fo9Rkm4+CNLxjWy7DX7tY2Xvu4kuPqQ0dyn31 zzxJHOESLOjtw8w0vSEKpuNyIfL/66/MF8p4CXzkUWQTa9h26yos+mDnSzxth++d ZERCpx7udTG3BbteJ8ZEf3/QyH6kJw9RccDET180/CvhBTHELEsroy9qOfDMJkgt RODtwh+2+O0zqUGjbqEd+PTmkU5p0UwIWAI9t7pic5Dntse7stRwotDtI0FGNnF1 aj/4ZkTb+lq3EF/x9xh6Hw/SfcVGtmySeMaPlaj9fgq39dtTPIspYeI5GieZlE0s 1ZfoRSgWA+/K9+4iTsuGvTwXnLhsRYVZl+GIkzeG2FL3euK0t+vaIvIbE9IDHdsS mgEFaUXwIosHOfn+8f9KWl6YupBtT/4PyPVu5DseREl4up0W6s26aamM1Ml16A8x JUNS/oa+cGpI4A== =BP3+ -----END PGP SIGNATURE----- Merge tag 'core-debugobjects-2020-10-12' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip Pull debugobjects updates from Thomas Gleixner: "A small set of updates for debug objects: - Make all debug object descriptors constant. There is no reason to have them writeable. - Free the per CPU object pool after CPU unplug to avoid memory waste" * tag 'core-debugobjects-2020-10-12' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: debugobjects: Free per CPU pool after CPU unplug treewide: Make all debug_obj_descriptors const debugobjects: Allow debug_obj_descr to be const
This commit is contained in:
commit
20d49bfcc3
|
@ -81,7 +81,7 @@ static void *active_debug_hint(void *addr)
|
|||
return (void *)ref->active ?: (void *)ref->retire ?: (void *)ref;
|
||||
}
|
||||
|
||||
static struct debug_obj_descr active_debug_desc = {
|
||||
static const struct debug_obj_descr active_debug_desc = {
|
||||
.name = "i915_active",
|
||||
.debug_hint = active_debug_hint,
|
||||
};
|
||||
|
|
|
@ -34,7 +34,7 @@ static void *i915_sw_fence_debug_hint(void *addr)
|
|||
|
||||
#ifdef CONFIG_DRM_I915_SW_FENCE_DEBUG_OBJECTS
|
||||
|
||||
static struct debug_obj_descr i915_sw_fence_debug_descr = {
|
||||
static const struct debug_obj_descr i915_sw_fence_debug_descr = {
|
||||
.name = "i915_sw_fence",
|
||||
.debug_hint = i915_sw_fence_debug_hint,
|
||||
};
|
||||
|
|
|
@ -36,6 +36,7 @@ enum cpuhp_state {
|
|||
CPUHP_X86_MCE_DEAD,
|
||||
CPUHP_VIRT_NET_DEAD,
|
||||
CPUHP_SLUB_DEAD,
|
||||
CPUHP_DEBUG_OBJ_DEAD,
|
||||
CPUHP_MM_WRITEBACK_DEAD,
|
||||
CPUHP_MM_VMSTAT_DEAD,
|
||||
CPUHP_SOFTIRQ_DEAD,
|
||||
|
|
|
@ -30,7 +30,7 @@ struct debug_obj {
|
|||
enum debug_obj_state state;
|
||||
unsigned int astate;
|
||||
void *object;
|
||||
struct debug_obj_descr *descr;
|
||||
const struct debug_obj_descr *descr;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -64,14 +64,14 @@ struct debug_obj_descr {
|
|||
};
|
||||
|
||||
#ifdef CONFIG_DEBUG_OBJECTS
|
||||
extern void debug_object_init (void *addr, struct debug_obj_descr *descr);
|
||||
extern void debug_object_init (void *addr, const struct debug_obj_descr *descr);
|
||||
extern void
|
||||
debug_object_init_on_stack(void *addr, struct debug_obj_descr *descr);
|
||||
extern int debug_object_activate (void *addr, struct debug_obj_descr *descr);
|
||||
extern void debug_object_deactivate(void *addr, struct debug_obj_descr *descr);
|
||||
extern void debug_object_destroy (void *addr, struct debug_obj_descr *descr);
|
||||
extern void debug_object_free (void *addr, struct debug_obj_descr *descr);
|
||||
extern void debug_object_assert_init(void *addr, struct debug_obj_descr *descr);
|
||||
debug_object_init_on_stack(void *addr, const struct debug_obj_descr *descr);
|
||||
extern int debug_object_activate (void *addr, const struct debug_obj_descr *descr);
|
||||
extern void debug_object_deactivate(void *addr, const struct debug_obj_descr *descr);
|
||||
extern void debug_object_destroy (void *addr, const struct debug_obj_descr *descr);
|
||||
extern void debug_object_free (void *addr, const struct debug_obj_descr *descr);
|
||||
extern void debug_object_assert_init(void *addr, const struct debug_obj_descr *descr);
|
||||
|
||||
/*
|
||||
* Active state:
|
||||
|
@ -79,26 +79,26 @@ extern void debug_object_assert_init(void *addr, struct debug_obj_descr *descr);
|
|||
* - Must return to 0 before deactivation.
|
||||
*/
|
||||
extern void
|
||||
debug_object_active_state(void *addr, struct debug_obj_descr *descr,
|
||||
debug_object_active_state(void *addr, const struct debug_obj_descr *descr,
|
||||
unsigned int expect, unsigned int next);
|
||||
|
||||
extern void debug_objects_early_init(void);
|
||||
extern void debug_objects_mem_init(void);
|
||||
#else
|
||||
static inline void
|
||||
debug_object_init (void *addr, struct debug_obj_descr *descr) { }
|
||||
debug_object_init (void *addr, const struct debug_obj_descr *descr) { }
|
||||
static inline void
|
||||
debug_object_init_on_stack(void *addr, struct debug_obj_descr *descr) { }
|
||||
debug_object_init_on_stack(void *addr, const struct debug_obj_descr *descr) { }
|
||||
static inline int
|
||||
debug_object_activate (void *addr, struct debug_obj_descr *descr) { return 0; }
|
||||
debug_object_activate (void *addr, const struct debug_obj_descr *descr) { return 0; }
|
||||
static inline void
|
||||
debug_object_deactivate(void *addr, struct debug_obj_descr *descr) { }
|
||||
debug_object_deactivate(void *addr, const struct debug_obj_descr *descr) { }
|
||||
static inline void
|
||||
debug_object_destroy (void *addr, struct debug_obj_descr *descr) { }
|
||||
debug_object_destroy (void *addr, const struct debug_obj_descr *descr) { }
|
||||
static inline void
|
||||
debug_object_free (void *addr, struct debug_obj_descr *descr) { }
|
||||
debug_object_free (void *addr, const struct debug_obj_descr *descr) { }
|
||||
static inline void
|
||||
debug_object_assert_init(void *addr, struct debug_obj_descr *descr) { }
|
||||
debug_object_assert_init(void *addr, const struct debug_obj_descr *descr) { }
|
||||
|
||||
static inline void debug_objects_early_init(void) { }
|
||||
static inline void debug_objects_mem_init(void) { }
|
||||
|
|
|
@ -167,7 +167,7 @@ static inline unsigned long rcu_seq_diff(unsigned long new, unsigned long old)
|
|||
# define STATE_RCU_HEAD_READY 0
|
||||
# define STATE_RCU_HEAD_QUEUED 1
|
||||
|
||||
extern struct debug_obj_descr rcuhead_debug_descr;
|
||||
extern const struct debug_obj_descr rcuhead_debug_descr;
|
||||
|
||||
static inline int debug_rcu_head_queue(struct rcu_head *head)
|
||||
{
|
||||
|
|
|
@ -469,7 +469,7 @@ void destroy_rcu_head_on_stack(struct rcu_head *head)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(destroy_rcu_head_on_stack);
|
||||
|
||||
struct debug_obj_descr rcuhead_debug_descr = {
|
||||
const struct debug_obj_descr rcuhead_debug_descr = {
|
||||
.name = "rcu_head",
|
||||
.is_static_object = rcuhead_is_static_object,
|
||||
};
|
||||
|
|
|
@ -342,7 +342,7 @@ EXPORT_SYMBOL_GPL(ktime_add_safe);
|
|||
|
||||
#ifdef CONFIG_DEBUG_OBJECTS_TIMERS
|
||||
|
||||
static struct debug_obj_descr hrtimer_debug_descr;
|
||||
static const struct debug_obj_descr hrtimer_debug_descr;
|
||||
|
||||
static void *hrtimer_debug_hint(void *addr)
|
||||
{
|
||||
|
@ -401,7 +401,7 @@ static bool hrtimer_fixup_free(void *addr, enum debug_obj_state state)
|
|||
}
|
||||
}
|
||||
|
||||
static struct debug_obj_descr hrtimer_debug_descr = {
|
||||
static const struct debug_obj_descr hrtimer_debug_descr = {
|
||||
.name = "hrtimer",
|
||||
.debug_hint = hrtimer_debug_hint,
|
||||
.fixup_init = hrtimer_fixup_init,
|
||||
|
|
|
@ -611,7 +611,7 @@ static void internal_add_timer(struct timer_base *base, struct timer_list *timer
|
|||
|
||||
#ifdef CONFIG_DEBUG_OBJECTS_TIMERS
|
||||
|
||||
static struct debug_obj_descr timer_debug_descr;
|
||||
static const struct debug_obj_descr timer_debug_descr;
|
||||
|
||||
static void *timer_debug_hint(void *addr)
|
||||
{
|
||||
|
@ -707,7 +707,7 @@ static bool timer_fixup_assert_init(void *addr, enum debug_obj_state state)
|
|||
}
|
||||
}
|
||||
|
||||
static struct debug_obj_descr timer_debug_descr = {
|
||||
static const struct debug_obj_descr timer_debug_descr = {
|
||||
.name = "timer_list",
|
||||
.debug_hint = timer_debug_hint,
|
||||
.is_static_object = timer_is_static_object,
|
||||
|
|
|
@ -427,7 +427,7 @@ static void show_pwq(struct pool_workqueue *pwq);
|
|||
|
||||
#ifdef CONFIG_DEBUG_OBJECTS_WORK
|
||||
|
||||
static struct debug_obj_descr work_debug_descr;
|
||||
static const struct debug_obj_descr work_debug_descr;
|
||||
|
||||
static void *work_debug_hint(void *addr)
|
||||
{
|
||||
|
@ -477,7 +477,7 @@ static bool work_fixup_free(void *addr, enum debug_obj_state state)
|
|||
}
|
||||
}
|
||||
|
||||
static struct debug_obj_descr work_debug_descr = {
|
||||
static const struct debug_obj_descr work_debug_descr = {
|
||||
.name = "work_struct",
|
||||
.debug_hint = work_debug_hint,
|
||||
.is_static_object = work_is_static_object,
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/hash.h>
|
||||
#include <linux/kmemleak.h>
|
||||
#include <linux/cpu.h>
|
||||
|
||||
#define ODEBUG_HASH_BITS 14
|
||||
#define ODEBUG_HASH_SIZE (1 << ODEBUG_HASH_BITS)
|
||||
|
@ -90,7 +91,7 @@ static int debug_objects_pool_size __read_mostly
|
|||
= ODEBUG_POOL_SIZE;
|
||||
static int debug_objects_pool_min_level __read_mostly
|
||||
= ODEBUG_POOL_MIN_LEVEL;
|
||||
static struct debug_obj_descr *descr_test __read_mostly;
|
||||
static const struct debug_obj_descr *descr_test __read_mostly;
|
||||
static struct kmem_cache *obj_cache __read_mostly;
|
||||
|
||||
/*
|
||||
|
@ -223,7 +224,7 @@ static struct debug_obj *__alloc_object(struct hlist_head *list)
|
|||
* Must be called with interrupts disabled.
|
||||
*/
|
||||
static struct debug_obj *
|
||||
alloc_object(void *addr, struct debug_bucket *b, struct debug_obj_descr *descr)
|
||||
alloc_object(void *addr, struct debug_bucket *b, const struct debug_obj_descr *descr)
|
||||
{
|
||||
struct debug_percpu_free *percpu_pool = this_cpu_ptr(&percpu_obj_pool);
|
||||
struct debug_obj *obj;
|
||||
|
@ -433,6 +434,25 @@ static void free_object(struct debug_obj *obj)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
static int object_cpu_offline(unsigned int cpu)
|
||||
{
|
||||
struct debug_percpu_free *percpu_pool;
|
||||
struct hlist_node *tmp;
|
||||
struct debug_obj *obj;
|
||||
|
||||
/* Remote access is safe as the CPU is dead already */
|
||||
percpu_pool = per_cpu_ptr(&percpu_obj_pool, cpu);
|
||||
hlist_for_each_entry_safe(obj, tmp, &percpu_pool->free_objs, node) {
|
||||
hlist_del(&obj->node);
|
||||
kmem_cache_free(obj_cache, obj);
|
||||
}
|
||||
percpu_pool->obj_free = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We run out of memory. That means we probably have tons of objects
|
||||
* allocated.
|
||||
|
@ -475,7 +495,7 @@ static struct debug_bucket *get_bucket(unsigned long addr)
|
|||
|
||||
static void debug_print_object(struct debug_obj *obj, char *msg)
|
||||
{
|
||||
struct debug_obj_descr *descr = obj->descr;
|
||||
const struct debug_obj_descr *descr = obj->descr;
|
||||
static int limit;
|
||||
|
||||
if (limit < 5 && descr != descr_test) {
|
||||
|
@ -529,7 +549,7 @@ static void debug_object_is_on_stack(void *addr, int onstack)
|
|||
}
|
||||
|
||||
static void
|
||||
__debug_object_init(void *addr, struct debug_obj_descr *descr, int onstack)
|
||||
__debug_object_init(void *addr, const struct debug_obj_descr *descr, int onstack)
|
||||
{
|
||||
enum debug_obj_state state;
|
||||
bool check_stack = false;
|
||||
|
@ -587,7 +607,7 @@ __debug_object_init(void *addr, struct debug_obj_descr *descr, int onstack)
|
|||
* @addr: address of the object
|
||||
* @descr: pointer to an object specific debug description structure
|
||||
*/
|
||||
void debug_object_init(void *addr, struct debug_obj_descr *descr)
|
||||
void debug_object_init(void *addr, const struct debug_obj_descr *descr)
|
||||
{
|
||||
if (!debug_objects_enabled)
|
||||
return;
|
||||
|
@ -602,7 +622,7 @@ EXPORT_SYMBOL_GPL(debug_object_init);
|
|||
* @addr: address of the object
|
||||
* @descr: pointer to an object specific debug description structure
|
||||
*/
|
||||
void debug_object_init_on_stack(void *addr, struct debug_obj_descr *descr)
|
||||
void debug_object_init_on_stack(void *addr, const struct debug_obj_descr *descr)
|
||||
{
|
||||
if (!debug_objects_enabled)
|
||||
return;
|
||||
|
@ -617,7 +637,7 @@ EXPORT_SYMBOL_GPL(debug_object_init_on_stack);
|
|||
* @descr: pointer to an object specific debug description structure
|
||||
* Returns 0 for success, -EINVAL for check failed.
|
||||
*/
|
||||
int debug_object_activate(void *addr, struct debug_obj_descr *descr)
|
||||
int debug_object_activate(void *addr, const struct debug_obj_descr *descr)
|
||||
{
|
||||
enum debug_obj_state state;
|
||||
struct debug_bucket *db;
|
||||
|
@ -695,7 +715,7 @@ EXPORT_SYMBOL_GPL(debug_object_activate);
|
|||
* @addr: address of the object
|
||||
* @descr: pointer to an object specific debug description structure
|
||||
*/
|
||||
void debug_object_deactivate(void *addr, struct debug_obj_descr *descr)
|
||||
void debug_object_deactivate(void *addr, const struct debug_obj_descr *descr)
|
||||
{
|
||||
struct debug_bucket *db;
|
||||
struct debug_obj *obj;
|
||||
|
@ -747,7 +767,7 @@ EXPORT_SYMBOL_GPL(debug_object_deactivate);
|
|||
* @addr: address of the object
|
||||
* @descr: pointer to an object specific debug description structure
|
||||
*/
|
||||
void debug_object_destroy(void *addr, struct debug_obj_descr *descr)
|
||||
void debug_object_destroy(void *addr, const struct debug_obj_descr *descr)
|
||||
{
|
||||
enum debug_obj_state state;
|
||||
struct debug_bucket *db;
|
||||
|
@ -797,7 +817,7 @@ EXPORT_SYMBOL_GPL(debug_object_destroy);
|
|||
* @addr: address of the object
|
||||
* @descr: pointer to an object specific debug description structure
|
||||
*/
|
||||
void debug_object_free(void *addr, struct debug_obj_descr *descr)
|
||||
void debug_object_free(void *addr, const struct debug_obj_descr *descr)
|
||||
{
|
||||
enum debug_obj_state state;
|
||||
struct debug_bucket *db;
|
||||
|
@ -838,7 +858,7 @@ EXPORT_SYMBOL_GPL(debug_object_free);
|
|||
* @addr: address of the object
|
||||
* @descr: pointer to an object specific debug description structure
|
||||
*/
|
||||
void debug_object_assert_init(void *addr, struct debug_obj_descr *descr)
|
||||
void debug_object_assert_init(void *addr, const struct debug_obj_descr *descr)
|
||||
{
|
||||
struct debug_bucket *db;
|
||||
struct debug_obj *obj;
|
||||
|
@ -886,7 +906,7 @@ EXPORT_SYMBOL_GPL(debug_object_assert_init);
|
|||
* @next: state to move to if expected state is found
|
||||
*/
|
||||
void
|
||||
debug_object_active_state(void *addr, struct debug_obj_descr *descr,
|
||||
debug_object_active_state(void *addr, const struct debug_obj_descr *descr,
|
||||
unsigned int expect, unsigned int next)
|
||||
{
|
||||
struct debug_bucket *db;
|
||||
|
@ -934,7 +954,7 @@ EXPORT_SYMBOL_GPL(debug_object_active_state);
|
|||
static void __debug_check_no_obj_freed(const void *address, unsigned long size)
|
||||
{
|
||||
unsigned long flags, oaddr, saddr, eaddr, paddr, chunks;
|
||||
struct debug_obj_descr *descr;
|
||||
const struct debug_obj_descr *descr;
|
||||
enum debug_obj_state state;
|
||||
struct debug_bucket *db;
|
||||
struct hlist_node *tmp;
|
||||
|
@ -1052,7 +1072,7 @@ struct self_test {
|
|||
unsigned long dummy2[3];
|
||||
};
|
||||
|
||||
static __initdata struct debug_obj_descr descr_type_test;
|
||||
static __initconst const struct debug_obj_descr descr_type_test;
|
||||
|
||||
static bool __init is_static_object(void *addr)
|
||||
{
|
||||
|
@ -1177,7 +1197,7 @@ out:
|
|||
return res;
|
||||
}
|
||||
|
||||
static __initdata struct debug_obj_descr descr_type_test = {
|
||||
static __initconst const struct debug_obj_descr descr_type_test = {
|
||||
.name = "selftest",
|
||||
.is_static_object = is_static_object,
|
||||
.fixup_init = fixup_init,
|
||||
|
@ -1367,6 +1387,11 @@ void __init debug_objects_mem_init(void)
|
|||
} else
|
||||
debug_objects_selftest();
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
cpuhp_setup_state_nocalls(CPUHP_DEBUG_OBJ_DEAD, "object:offline", NULL,
|
||||
object_cpu_offline);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Increase the thresholds for allocating and freeing objects
|
||||
* according to the number of possible CPUs available in the system.
|
||||
|
|
|
@ -17,7 +17,7 @@ static DEFINE_SPINLOCK(percpu_counters_lock);
|
|||
|
||||
#ifdef CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER
|
||||
|
||||
static struct debug_obj_descr percpu_counter_debug_descr;
|
||||
static const struct debug_obj_descr percpu_counter_debug_descr;
|
||||
|
||||
static bool percpu_counter_fixup_free(void *addr, enum debug_obj_state state)
|
||||
{
|
||||
|
@ -33,7 +33,7 @@ static bool percpu_counter_fixup_free(void *addr, enum debug_obj_state state)
|
|||
}
|
||||
}
|
||||
|
||||
static struct debug_obj_descr percpu_counter_debug_descr = {
|
||||
static const struct debug_obj_descr percpu_counter_debug_descr = {
|
||||
.name = "percpu_counter",
|
||||
.fixup_free = percpu_counter_fixup_free,
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue