scx_sub_enable_workfn() has several failure paths that only return an errno (e.g. -ENOMEM from an allocation) and jump to err_disable without calling scx_error(). scx_flush_disable_work() runs the disable, and thus ops.exit(), only when an error has been recorded, so an errno-only failure leaves the half-initialized sub-scheduler linked. Record an error at the err_disable sink so every errno-only failure runs the disable path.
Unified · Split
| @@ -7746,6 +7746,12 @@ err_unlock_and_disable: · 7745 unmodified lines | |||
| 7746 | percpu_up_write(&scx_fork_rwsem); | 7746 | percpu_up_write(&scx_fork_rwsem); |
| 7747 | err_disable: | 7747 | err_disable: |
| 7748 | mutex_unlock(&scx_enable_mutex); | 7748 | mutex_unlock(&scx_enable_mutex); |
| 7749 | /* | ||
| 7750 | * Some enable failures only return an errno (e.g. -ENOMEM from an | ||
| 7751 | * allocation) without calling scx_error(). Record it so | ||
| 7752 | * scx_flush_disable_work() runs the disable and ops.exit() fires. | ||
| 7753 | */ | ||
| 7754 | scx_error(sch, "scx_sub_enable() failed (%d)", ret); | ||
| 7749 | scx_flush_disable_work(sch); | 7755 | scx_flush_disable_work(sch); |
| 7750 | cmd->ret = 0; | 7756 | cmd->ret = 0; |
| 7751 | } | 7757 | } |