Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

sched_ext: Allow p->scx.disallow only while loading

From 1232da7eced620537a78f19c8cf3d4a3508e2419 Mon Sep 17 00:00:00 2001
From: Tejun Heo <tj@kernel.org>
Date: Wed, 31 Jul 2024 09:14:52 -1000

p->scx.disallow provides a way for the BPF scheduler to reject certain tasks
from attaching. It's currently allowed for both the load and fork paths;
however, the latter doesn't actually work as p->sched_class is already set
by the time scx_ops_init_task() is called during fork.

This is a convenience feature which is mostly useful from the load path
anyway. Allow it only from the load path.

v2: Trigger scx_ops_error() iff @p->policy == SCHED_EXT to make it a bit
easier for the BPF scheduler (David).

Signed-off-by: Tejun Heo <tj@kernel.org>
Reported-by: "Zhangqiao (2012 lab)" <zhangqiao22@huawei.com>
Link: http://lkml.kernel.org/r/20240711110720.1285-1-zhangqiao22@huawei.com
Fixes: 7bb6f0810ecf ("sched_ext: Allow BPF schedulers to disallow specific tasks from joining SCHED_EXT")
Acked-by: David Vernet <void@manifault.com>
Signed-off-by: Tejun Heo <tj@kernel.org>

+26 -20
+6 -5
include/linux/sched/ext.h
··· 179 179 * If set, reject future sched_setscheduler(2) calls updating the policy 180 180 * to %SCHED_EXT with -%EACCES. 181 181 * 182 - * If set from ops.init_task() and the task's policy is already 183 - * %SCHED_EXT, which can happen while the BPF scheduler is being loaded 184 - * or by inhering the parent's policy during fork, the task's policy is 185 - * rejected and forcefully reverted to %SCHED_NORMAL. The number of 186 - * such events are reported through /sys/kernel/debug/sched_ext::nr_rejected. 182 + * Can be set from ops.init_task() while the BPF scheduler is being 183 + * loaded (!scx_init_task_args->fork). If set and the task's policy is 184 + * already %SCHED_EXT, the task's policy is rejected and forcefully 185 + * reverted to %SCHED_NORMAL. The number of such events are reported 186 + * through /sys/kernel/debug/sched_ext::nr_rejected. Setting this flag 187 + * during fork is not allowed. 187 188 */ 188 189 bool disallow; /* reject switching into SCX */ 189 190
+20 -15
kernel/sched/ext.c
··· 3396 3396 scx_set_task_state(p, SCX_TASK_INIT); 3397 3397 3398 3398 if (p->scx.disallow) { 3399 - struct rq *rq; 3400 - struct rq_flags rf; 3399 + if (!fork) { 3400 + struct rq *rq; 3401 + struct rq_flags rf; 3401 3402 3402 - rq = task_rq_lock(p, &rf); 3403 + rq = task_rq_lock(p, &rf); 3403 3404 3404 - /* 3405 - * We're either in fork or load path and @p->policy will be 3406 - * applied right after. Reverting @p->policy here and rejecting 3407 - * %SCHED_EXT transitions from scx_check_setscheduler() 3408 - * guarantees that if ops.init_task() sets @p->disallow, @p can 3409 - * never be in SCX. 3410 - */ 3411 - if (p->policy == SCHED_EXT) { 3412 - p->policy = SCHED_NORMAL; 3413 - atomic_long_inc(&scx_nr_rejected); 3405 + /* 3406 + * We're in the load path and @p->policy will be applied 3407 + * right after. Reverting @p->policy here and rejecting 3408 + * %SCHED_EXT transitions from scx_check_setscheduler() 3409 + * guarantees that if ops.init_task() sets @p->disallow, 3410 + * @p can never be in SCX. 3411 + */ 3412 + if (p->policy == SCHED_EXT) { 3413 + p->policy = SCHED_NORMAL; 3414 + atomic_long_inc(&scx_nr_rejected); 3415 + } 3416 + 3417 + task_rq_unlock(rq, p, &rf); 3418 + } else if (p->policy == SCHED_EXT) { 3419 + scx_ops_error("ops.init_task() set task->scx.disallow for %s[%d] during fork", 3420 + p->comm, p->pid); 3414 3421 } 3415 - 3416 - task_rq_unlock(rq, p, &rf); 3417 3422 } 3418 3423 3419 3424 p->scx.flags |= SCX_TASK_RESET_RUNNABLE_AT;