Skip to content

Commit daa9f66

Browse files
committed
Merge tag 'sched_ext-for-6.12-rc5-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/sched_ext
Pull sched_ext fixes from Tejun Heo: - Instances of scx_ops_bypass() could race each other leading to misbehavior. Fix by protecting the operation with a spinlock. - selftest and userspace header fixes * tag 'sched_ext-for-6.12-rc5-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/sched_ext: sched_ext: Fix enq_last_no_enq_fails selftest sched_ext: Make cast_mask() inline scx: Fix raciness in scx_ops_bypass() scx: Fix exit selftest to use custom DSQ sched_ext: Fix function pointer type mismatches in BPF selftests selftests/sched_ext: add order-only dependency of runner.o on BPFOBJ
2 parents 7fbaaca + c31f2ee commit daa9f66

24 files changed

+119
-100
lines changed

kernel/sched/ext.c

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -862,7 +862,8 @@ static DEFINE_MUTEX(scx_ops_enable_mutex);
862862
DEFINE_STATIC_KEY_FALSE(__scx_ops_enabled);
863863
DEFINE_STATIC_PERCPU_RWSEM(scx_fork_rwsem);
864864
static atomic_t scx_ops_enable_state_var = ATOMIC_INIT(SCX_OPS_DISABLED);
865-
static atomic_t scx_ops_bypass_depth = ATOMIC_INIT(0);
865+
static int scx_ops_bypass_depth;
866+
static DEFINE_RAW_SPINLOCK(__scx_ops_bypass_lock);
866867
static bool scx_ops_init_task_enabled;
867868
static bool scx_switching_all;
868869
DEFINE_STATIC_KEY_FALSE(__scx_switched_all);
@@ -4298,18 +4299,20 @@ bool task_should_scx(struct task_struct *p)
42984299
*/
42994300
static void scx_ops_bypass(bool bypass)
43004301
{
4301-
int depth, cpu;
4302+
int cpu;
4303+
unsigned long flags;
43024304

4305+
raw_spin_lock_irqsave(&__scx_ops_bypass_lock, flags);
43034306
if (bypass) {
4304-
depth = atomic_inc_return(&scx_ops_bypass_depth);
4305-
WARN_ON_ONCE(depth <= 0);
4306-
if (depth != 1)
4307-
return;
4307+
scx_ops_bypass_depth++;
4308+
WARN_ON_ONCE(scx_ops_bypass_depth <= 0);
4309+
if (scx_ops_bypass_depth != 1)
4310+
goto unlock;
43084311
} else {
4309-
depth = atomic_dec_return(&scx_ops_bypass_depth);
4310-
WARN_ON_ONCE(depth < 0);
4311-
if (depth != 0)
4312-
return;
4312+
scx_ops_bypass_depth--;
4313+
WARN_ON_ONCE(scx_ops_bypass_depth < 0);
4314+
if (scx_ops_bypass_depth != 0)
4315+
goto unlock;
43134316
}
43144317

43154318
/*
@@ -4326,7 +4329,7 @@ static void scx_ops_bypass(bool bypass)
43264329
struct rq_flags rf;
43274330
struct task_struct *p, *n;
43284331

4329-
rq_lock_irqsave(rq, &rf);
4332+
rq_lock(rq, &rf);
43304333

43314334
if (bypass) {
43324335
WARN_ON_ONCE(rq->scx.flags & SCX_RQ_BYPASSING);
@@ -4362,11 +4365,13 @@ static void scx_ops_bypass(bool bypass)
43624365
sched_enq_and_set_task(&ctx);
43634366
}
43644367

4365-
rq_unlock_irqrestore(rq, &rf);
4368+
rq_unlock(rq, &rf);
43664369

43674370
/* resched to restore ticks and idle state */
43684371
resched_cpu(cpu);
43694372
}
4373+
unlock:
4374+
raw_spin_unlock_irqrestore(&__scx_ops_bypass_lock, flags);
43704375
}
43714376

43724377
static void free_exit_info(struct scx_exit_info *ei)

tools/sched_ext/include/scx/common.bpf.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ u32 bpf_cpumask_weight(const struct cpumask *cpumask) __ksym;
320320
/*
321321
* Access a cpumask in read-only mode (typically to check bits).
322322
*/
323-
const struct cpumask *cast_mask(struct bpf_cpumask *mask)
323+
static __always_inline const struct cpumask *cast_mask(struct bpf_cpumask *mask)
324324
{
325325
return (const struct cpumask *)mask;
326326
}

tools/testing/selftests/sched_ext/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ auto-test-targets := \
184184

185185
testcase-targets := $(addsuffix .o,$(addprefix $(SCXOBJ_DIR)/,$(auto-test-targets)))
186186

187-
$(SCXOBJ_DIR)/runner.o: runner.c | $(SCXOBJ_DIR)
187+
$(SCXOBJ_DIR)/runner.o: runner.c | $(SCXOBJ_DIR) $(BPFOBJ)
188188
$(CC) $(CFLAGS) -c $< -o $@
189189

190190
# Create all of the test targets object files, whose testcase objects will be

tools/testing/selftests/sched_ext/create_dsq.bpf.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ s32 BPF_STRUCT_OPS_SLEEPABLE(create_dsq_init)
5151

5252
SEC(".struct_ops.link")
5353
struct sched_ext_ops create_dsq_ops = {
54-
.init_task = create_dsq_init_task,
55-
.exit_task = create_dsq_exit_task,
56-
.init = create_dsq_init,
54+
.init_task = (void *) create_dsq_init_task,
55+
.exit_task = (void *) create_dsq_exit_task,
56+
.init = (void *) create_dsq_init,
5757
.name = "create_dsq",
5858
};

tools/testing/selftests/sched_ext/ddsp_bogus_dsq_fail.bpf.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ void BPF_STRUCT_OPS(ddsp_bogus_dsq_fail_exit, struct scx_exit_info *ei)
3535

3636
SEC(".struct_ops.link")
3737
struct sched_ext_ops ddsp_bogus_dsq_fail_ops = {
38-
.select_cpu = ddsp_bogus_dsq_fail_select_cpu,
39-
.exit = ddsp_bogus_dsq_fail_exit,
38+
.select_cpu = (void *) ddsp_bogus_dsq_fail_select_cpu,
39+
.exit = (void *) ddsp_bogus_dsq_fail_exit,
4040
.name = "ddsp_bogus_dsq_fail",
4141
.timeout_ms = 1000U,
4242
};

tools/testing/selftests/sched_ext/ddsp_vtimelocal_fail.bpf.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ void BPF_STRUCT_OPS(ddsp_vtimelocal_fail_exit, struct scx_exit_info *ei)
3232

3333
SEC(".struct_ops.link")
3434
struct sched_ext_ops ddsp_vtimelocal_fail_ops = {
35-
.select_cpu = ddsp_vtimelocal_fail_select_cpu,
36-
.exit = ddsp_vtimelocal_fail_exit,
35+
.select_cpu = (void *) ddsp_vtimelocal_fail_select_cpu,
36+
.exit = (void *) ddsp_vtimelocal_fail_exit,
3737
.name = "ddsp_vtimelocal_fail",
3838
.timeout_ms = 1000U,
3939
};

tools/testing/selftests/sched_ext/dsp_local_on.bpf.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,10 @@ void BPF_STRUCT_OPS(dsp_local_on_exit, struct scx_exit_info *ei)
5656

5757
SEC(".struct_ops.link")
5858
struct sched_ext_ops dsp_local_on_ops = {
59-
.select_cpu = dsp_local_on_select_cpu,
60-
.enqueue = dsp_local_on_enqueue,
61-
.dispatch = dsp_local_on_dispatch,
62-
.exit = dsp_local_on_exit,
59+
.select_cpu = (void *) dsp_local_on_select_cpu,
60+
.enqueue = (void *) dsp_local_on_enqueue,
61+
.dispatch = (void *) dsp_local_on_dispatch,
62+
.exit = (void *) dsp_local_on_exit,
6363
.name = "dsp_local_on",
6464
.timeout_ms = 1000U,
6565
};

tools/testing/selftests/sched_ext/enq_last_no_enq_fails.bpf.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,18 @@
1212

1313
char _license[] SEC("license") = "GPL";
1414

15+
u32 exit_kind;
16+
17+
void BPF_STRUCT_OPS_SLEEPABLE(enq_last_no_enq_fails_exit, struct scx_exit_info *info)
18+
{
19+
exit_kind = info->kind;
20+
}
21+
1522
SEC(".struct_ops.link")
1623
struct sched_ext_ops enq_last_no_enq_fails_ops = {
1724
.name = "enq_last_no_enq_fails",
1825
/* Need to define ops.enqueue() with SCX_OPS_ENQ_LAST */
1926
.flags = SCX_OPS_ENQ_LAST,
27+
.exit = (void *) enq_last_no_enq_fails_exit,
2028
.timeout_ms = 1000U,
2129
};

tools/testing/selftests/sched_ext/enq_last_no_enq_fails.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,12 @@ static enum scx_test_status run(void *ctx)
3131
struct bpf_link *link;
3232

3333
link = bpf_map__attach_struct_ops(skel->maps.enq_last_no_enq_fails_ops);
34-
if (link) {
35-
SCX_ERR("Incorrectly succeeded in to attaching scheduler");
34+
if (!link) {
35+
SCX_ERR("Incorrectly failed at attaching scheduler");
36+
return SCX_TEST_FAIL;
37+
}
38+
if (!skel->bss->exit_kind) {
39+
SCX_ERR("Incorrectly stayed loaded");
3640
return SCX_TEST_FAIL;
3741
}
3842

@@ -50,7 +54,7 @@ static void cleanup(void *ctx)
5054

5155
struct scx_test enq_last_no_enq_fails = {
5256
.name = "enq_last_no_enq_fails",
53-
.description = "Verify we fail to load a scheduler if we specify "
57+
.description = "Verify we eject a scheduler if we specify "
5458
"the SCX_OPS_ENQ_LAST flag without defining "
5559
"ops.enqueue()",
5660
.setup = setup,

tools/testing/selftests/sched_ext/enq_select_cpu_fails.bpf.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ void BPF_STRUCT_OPS(enq_select_cpu_fails_enqueue, struct task_struct *p,
3636

3737
SEC(".struct_ops.link")
3838
struct sched_ext_ops enq_select_cpu_fails_ops = {
39-
.select_cpu = enq_select_cpu_fails_select_cpu,
40-
.enqueue = enq_select_cpu_fails_enqueue,
39+
.select_cpu = (void *) enq_select_cpu_fails_select_cpu,
40+
.enqueue = (void *) enq_select_cpu_fails_enqueue,
4141
.name = "enq_select_cpu_fails",
4242
.timeout_ms = 1000U,
4343
};

0 commit comments

Comments
 (0)