Developers manage to overwrite states blindly without thought. That's fatal and hard to debug. Add sanity checks to make it fail. Signed-off-by: Thomas Gleixner --- kernel/cpu.c | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -1432,23 +1432,29 @@ static int cpuhp_cb_check(enum cpuhp_sta return 0; } -static void cpuhp_store_callbacks(enum cpuhp_state state, - const char *name, - int (*startup)(unsigned int cpu), - int (*teardown)(unsigned int cpu), - bool multi_instance) +static int cpuhp_store_callbacks(enum cpuhp_state state, const char *name, + int (*startup)(unsigned int cpu), + int (*teardown)(unsigned int cpu), + bool multi_instance) { /* (Un)Install the callbacks for further cpu hotplug operations */ struct cpuhp_step *sp; + int ret = 0; mutex_lock(&cpuhp_state_mutex); sp = cpuhp_get_step(state); + if (name && sp->name) { + ret = -EBUSY; + goto out; + } sp->startup.single = startup; sp->teardown.single = teardown; sp->name = name; sp->multi_instance = multi_instance; INIT_HLIST_HEAD(&sp->list); +out: mutex_unlock(&cpuhp_state_mutex); + return ret; } static void *cpuhp_get_teardown_cb(enum cpuhp_state state) @@ -1580,11 +1586,13 @@ EXPORT_SYMBOL_GPL(__cpuhp_state_add_inst /** * __cpuhp_setup_state - Setup the callbacks for an hotplug machine state - * @state: The state to setup - * @invoke: If true, the startup function is invoked for cpus where - * cpu state >= @state - * @startup: startup callback function - * @teardown: teardown callback function + * @state: The state to setup + * @invoke: If true, the startup function is invoked for cpus where + * cpu state >= @state + * @startup: startup callback function + * @teardown: teardown callback function + * @multi_instance: State is set up for multiple instances which get + * added afterwards. * * Returns: * On success: @@ -1615,9 +1623,10 @@ int __cpuhp_setup_state(enum cpuhp_state state = ret; } - cpuhp_store_callbacks(state, name, startup, teardown, multi_instance); + ret = cpuhp_store_callbacks(state, name, startup, teardown, + multi_instance); - if (!invoke || !startup) + if (ret || !invoke || !startup) goto out; /*