• Tejun Heo's avatar
    sched_ext: Decouple locks in scx_ops_enable() · efe231d9
    Tejun Heo authored
    The enable path uses three big locks - scx_fork_rwsem, scx_cgroup_rwsem and
    cpus_read_lock. Currently, the locks are grabbed together which is prone to
    locking order problems.
    
    For example, currently, there is a possible deadlock involving
    scx_fork_rwsem and cpus_read_lock. cpus_read_lock has to nest inside
    scx_fork_rwsem due to locking order existing in other subsystems. However,
    there exists a dependency in the other direction during hotplug if hotplug
    needs to fork a new task, which happens in some cases. This leads to the
    following deadlock:
    
           scx_ops_enable()                               hotplug
    
                                              percpu_down_write(&cpu_hotplug_lock)
       percpu_down_write(&scx_fork_rwsem)
       block on cpu_hotplug_lock
                                              kthread_create() waits for kthreadd
    					  kthreadd blocks on scx_fork_rwsem
    
    Note that this doesn't trigger lockdep because the hotplug side dependency
    bounces through kthreadd.
    
    With the preceding scx_cgroup_enabled change, this can be solved by
    decoupling cpus_read_lock, which is needed for static_key manipulations,
    from the other two locks.
    
    - Move the first block of static_key manipulations outside of scx_fork_rwsem
      and scx_cgroup_rwsem. This is now safe with the preceding
      scx_cgroup_enabled change.
    
    - Drop scx_cgroup_rwsem and scx_fork_rwsem between the two task iteration
      blocks so that __scx_ops_enabled static_key enabling is outside the two
      rwsems.
    Signed-off-by: default avatarTejun Heo <tj@kernel.org>
    Reported-and-tested-by: default avatarAboorva Devarajan <aboorvad@linux.ibm.com>
    Link: http://lkml.kernel.org/r/8cd0ec0c4c7c1bc0119e61fbef0bee9d5e24022d.camel@linux.ibm.com
    efe231d9
ext.c 204 KB