mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 12:44:03 +02:00
Merge branch 'for-7.2-fixes' into for-7.3
Pull to receive:477869bfaf("sched_ext: Reject setting disallow from init_task outside the enable path")5f8b69642d("sched_ext: Take cgroup_lock() first in scx_cgroup_lock()")8c13364db9("sched_ext: Skip sub-disable teardown for never-linked sub-schedulers")5cdc928598("sched_ext: Don't enable non-ext tasks in the sub-sched task loops") as dependencies for the upcoming cgroup migration patchset and to resolve the conflicts with the ext.c/sub.c split on for-7.3.5f8b69642dcomments scx_cgroup_lock() which for-7.3 exported for sub.c. Resolved by keeping the exported version with the comment.8c13364db9and5cdc928598patch the pre-split sub-sched enable and disable paths in ext.c which for-7.3 moved to sub.c. Resolved by applying the never-linked teardown skip and the class gates to sub.c. Signed-off-by: Tejun Heo <tj@kernel.org>
This commit is contained in:
commit
7c2cd76770
|
|
@ -265,11 +265,11 @@ struct sched_ext_entity {
|
|||
* to %SCHED_EXT with -%EACCES.
|
||||
*
|
||||
* Can be set from ops.init_task() while the BPF scheduler is being
|
||||
* loaded (!scx_init_task_args->fork). If set and the task's policy is
|
||||
* already %SCHED_EXT, the task's policy is rejected and forcefully
|
||||
* reverted to %SCHED_NORMAL. The number of such events are reported
|
||||
* through /sys/kernel/debug/sched_ext::nr_rejected. Setting this flag
|
||||
* during fork is not allowed.
|
||||
* loaded. If set and the task's policy is already %SCHED_EXT, the
|
||||
* task's policy is rejected and forcefully reverted to %SCHED_NORMAL.
|
||||
* The number of such events are reported through
|
||||
* /sys/kernel/sched_ext/nr_rejected. Setting this flag from any other
|
||||
* ops.init_task() invocation, such as during fork, fails the scheduler.
|
||||
*/
|
||||
bool disallow; /* reject switching into SCX */
|
||||
|
||||
|
|
|
|||
|
|
@ -3511,6 +3511,9 @@ int __scx_init_task(struct scx_sched *sch, struct task_struct *p, bool fork)
|
|||
} else if (unlikely(fork)) {
|
||||
scx_error(sch, "ops.init_task() set task->scx.disallow for %s[%d] during fork",
|
||||
p->comm, p->pid);
|
||||
} else if (unlikely(scx_enable_state() != SCX_ENABLING)) {
|
||||
scx_error(sch, "ops.init_task() set task->scx.disallow for %s[%d] outside the enable path",
|
||||
p->comm, p->pid);
|
||||
} else {
|
||||
struct rq *rq;
|
||||
struct rq_flags rf;
|
||||
|
|
@ -3872,6 +3875,17 @@ static void reweight_task_scx(struct rq *rq, struct task_struct *p,
|
|||
if (task_dead_and_done(p))
|
||||
return;
|
||||
|
||||
/*
|
||||
* When switching sched_class away from SCX, reweight_task_scx()
|
||||
* is called _after_ scx_disable_task(). Skip calling ops.set_weight()
|
||||
* since the BPF scheduler may have already forgotten the task in
|
||||
* ops.disable().
|
||||
* p->scx.weight will be recalculated in scx_enable_task() if the task
|
||||
* ever returns to SCX class.
|
||||
*/
|
||||
if (scx_get_task_state(p) != SCX_TASK_ENABLED)
|
||||
return;
|
||||
|
||||
p->scx.weight = sched_weight_to_cgroup(scale_load_down(lw->weight));
|
||||
if (SCX_HAS_OP(sch, set_weight))
|
||||
SCX_CALL_OP_TASK(sch, set_weight, rq, p, p->scx.weight);
|
||||
|
|
@ -4495,20 +4509,25 @@ static struct cgroup *root_cgroup(void)
|
|||
return &cgrp_dfl_root.cgrp;
|
||||
}
|
||||
|
||||
/*
|
||||
* cgroup_lock() must nest outside the rwsem write side: a writer waiting
|
||||
* for cgroup_mutex deadlocks with cgroup teardown, which holds it while
|
||||
* draining a set_* file write blocked on the rwsem behind the writer.
|
||||
*/
|
||||
void scx_cgroup_lock(void)
|
||||
{
|
||||
cgroup_lock();
|
||||
#ifdef CONFIG_EXT_GROUP_SCHED
|
||||
percpu_down_write(&scx_cgroup_ops_rwsem);
|
||||
#endif
|
||||
cgroup_lock();
|
||||
}
|
||||
|
||||
void scx_cgroup_unlock(void)
|
||||
{
|
||||
cgroup_unlock();
|
||||
#ifdef CONFIG_EXT_GROUP_SCHED
|
||||
percpu_up_write(&scx_cgroup_ops_rwsem);
|
||||
#endif
|
||||
cgroup_unlock();
|
||||
}
|
||||
#else /* CONFIG_EXT_GROUP_SCHED || CONFIG_EXT_SUB_SCHED */
|
||||
static inline struct cgroup *root_cgroup(void) { return NULL; }
|
||||
|
|
|
|||
|
|
@ -812,6 +812,15 @@ void scx_sub_disable(struct scx_sched *sch)
|
|||
percpu_down_write(&scx_fork_rwsem);
|
||||
scx_cgroup_lock();
|
||||
|
||||
/*
|
||||
* An enable that failed before scx_link_sched() never owned a cgroup or
|
||||
* task and won't be waited on by an ancestor's drain_descendants().
|
||||
* Nothing to reparent and walking the tasks can misbehave as the task
|
||||
* ownership invariant (either owned by self or parent) does not hold.
|
||||
*/
|
||||
if (list_empty(&sch->sibling))
|
||||
goto dump;
|
||||
|
||||
set_cgroup_sched(sch_cgroup(sch), parent);
|
||||
|
||||
scx_task_iter_start(&sti, sch->cgrp);
|
||||
|
|
@ -824,8 +833,8 @@ void scx_sub_disable(struct scx_sched *sch)
|
|||
continue;
|
||||
|
||||
/*
|
||||
* By the time control reaches here, all descendant schedulers
|
||||
* should already have been disabled.
|
||||
* By the time control reaches here, all linked descendant
|
||||
* schedulers should have been disabled.
|
||||
*/
|
||||
WARN_ON_ONCE(!scx_task_on_sched(sch, p));
|
||||
|
||||
|
|
@ -876,15 +885,22 @@ void scx_sub_disable(struct scx_sched *sch)
|
|||
/*
|
||||
* $p is initialized for $parent and still attached to
|
||||
* @sch. Disable and exit for @sch, switch over to
|
||||
* $parent, override the state to READY to account for
|
||||
* $p having already been initialized, and then enable.
|
||||
* $parent and override the state to READY to account
|
||||
* for $p having already been initialized.
|
||||
*/
|
||||
scx_disable_and_exit_task(sch, p);
|
||||
scx_set_task_state(p, SCX_TASK_INIT_BEGIN);
|
||||
scx_set_task_state(p, SCX_TASK_INIT);
|
||||
scx_set_task_sched(p, parent);
|
||||
scx_set_task_state(p, SCX_TASK_READY);
|
||||
scx_enable_task(parent, p);
|
||||
|
||||
/*
|
||||
* A task on a non-ext class, possible under an
|
||||
* %SCX_OPS_SWITCH_PARTIAL root, stays READY and is
|
||||
* enabled by switching_to_scx() if it switches over.
|
||||
*/
|
||||
if (p->sched_class == &ext_sched_class)
|
||||
scx_enable_task(parent, p);
|
||||
}
|
||||
|
||||
task_rq_unlock(rq, p, &rf);
|
||||
|
|
@ -892,6 +908,7 @@ void scx_sub_disable(struct scx_sched *sch)
|
|||
}
|
||||
scx_task_iter_stop(&sti);
|
||||
|
||||
dump:
|
||||
scx_disable_dump(sch);
|
||||
|
||||
scx_cgroup_unlock();
|
||||
|
|
@ -1219,10 +1236,14 @@ void scx_sub_enable_workfn(struct kthread_work *work)
|
|||
|
||||
/*
|
||||
* $p is now only initialized for @sch and READY, which
|
||||
* is what we want. Assign it to @sch and enable.
|
||||
* is what we want. Assign it to @sch and, if it's on
|
||||
* the ext class, enable. A non-ext task, possible under
|
||||
* an %SCX_OPS_SWITCH_PARTIAL root, stays READY and is
|
||||
* enabled by switching_to_scx() if it switches over.
|
||||
*/
|
||||
scx_set_task_sched(p, sch);
|
||||
scx_enable_task(sch, p);
|
||||
if (p->sched_class == &ext_sched_class)
|
||||
scx_enable_task(sch, p);
|
||||
|
||||
p->scx.flags &= ~SCX_TASK_SUB_INIT;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user