* [PATCH v2 0/2] sched/core: Handle unavailable pointer hash in PR_SCHED_CORE_GET
@ 2026-09-13 14:10 Hui Su
2026-09-13 14:10 ` [PATCH v2 1/2] sched/core: Propagate pointer hash errors from PR_SCHED_CORE_GET Hui Su
2026-09-13 14:10 ` [PATCH v2 2/2] selftests/sched: Retry PR_SCHED_CORE_GET on EBUSY Hui Su
0 siblings, 2 replies; 3+ messages in thread
From: Hui Su @ 2026-09-13 14:10 UTC (permalink / raw)
To: peterz
Cc: mingo, juri.lelli, vincent.guittot, dietmar.eggemann, shuah,
linux-kernel, linux-kselftest, Hui Su
PR_SCHED_CORE_GET converts the internal core scheduling cookie to an
opaque userspace value with ptr_to_hashval().
When the pointer hash key is not initialized yet, ptr_to_hashval()
returns -EBUSY without storing a hash. PR_SCHED_CORE_GET currently
ignores this error and returns the zero-initialized id instead. Since
cookie 0 denotes the default core scheduling cookie, this reports
incorrect state to userspace.
Propagate the hashing error and make the scheduler selftest retry the
transient EBUSY. Do not wait for RNG initialization in
PR_SCHED_CORE_GET; ptr_to_hashval() already reports an unavailable
pointer hash key as -EBUSY, so propagate that condition through the
prctl interface.
Testing on x86_64:
- An entropy-starved early-boot QEMU reproducer observed on the
unfixed kernel:
CREATE ret=0 errno=0 (Success)
GET ret=0 errno=0 (Success) cookie=0x0000000000000000
With patch 1, the same probe returned:
GET ret=-1 errno=16 (Device or resource busy)
- The selftest built successfully with:
make -C tools/testing/selftests/sched -j12
- With PR_SCHED_CORE_GET fault-injected to return EBUSY, the v1
selftest continued evaluating cookie assertions using the error
sentinel and finished with 5 failures. The v2 selftest instead
aborted without evaluating cookie assertions after the failed GET.
- The v2 selftest passed with normal random initialization:
SUCCESS !!!
Changes since v1:
- Patch 1 is unchanged.
- Keep the PR_SCHED_CORE_GET status separate from the returned cookie.
- Abort after an unrecoverable or timed-out GET instead of comparing an
error sentinel as a valid cookie.
- Return cookie values directly from the fatal error helper to keep the
selftest comparisons compact.
- Avoid sleeping after the final retry.
- Rebased onto 2f0c1cf72f46.
v1: https://lore.kernel.org/all/20260913063439.1513107-1-sh_def@163.com/
Hui Su (2):
sched/core: Propagate pointer hash errors from PR_SCHED_CORE_GET
selftests/sched: Retry PR_SCHED_CORE_GET on EBUSY
kernel/sched/core_sched.c | 5 +-
tools/testing/selftests/sched/cs_prctl_test.c | 93 +++++++++++++------
2 files changed, 66 insertions(+), 32 deletions(-)
base-commit: 2f0c1cf72f4682178506f513bbf015e591b1aa4a
--
2.55.0
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH v2 1/2] sched/core: Propagate pointer hash errors from PR_SCHED_CORE_GET
2026-09-13 14:10 [PATCH v2 0/2] sched/core: Handle unavailable pointer hash in PR_SCHED_CORE_GET Hui Su
@ 2026-09-13 14:10 ` Hui Su
2026-09-13 14:10 ` [PATCH v2 2/2] selftests/sched: Retry PR_SCHED_CORE_GET on EBUSY Hui Su
1 sibling, 0 replies; 3+ messages in thread
From: Hui Su @ 2026-09-13 14:10 UTC (permalink / raw)
To: peterz
Cc: mingo, juri.lelli, vincent.guittot, dietmar.eggemann, shuah,
linux-kernel, linux-kselftest, Hui Su, stable
PR_SCHED_CORE_GET hashes the internal core scheduling cookie before
returning an opaque identifier to userspace.
ptr_to_hashval() returns -EBUSY until the random key used for pointer
hashing has been initialized. However, PR_SCHED_CORE_GET currently
ignores that return value.
Since id is initialized to zero, a failed hash is therefore reported
as a successful GET with cookie 0. Cookie 0 represents the default
core scheduling cookie, so a task which already has a core scheduling
cookie can temporarily appear to have the default cookie during early
boot.
Propagate errors from ptr_to_hashval() instead. In particular, this
allows userspace to retry PR_SCHED_CORE_GET when pointer hashing is
temporarily unavailable.
An early-boot x86_64 QEMU reproducer observed the following before the
fix:
CREATE ret=0 errno=0 (Success)
GET ret=0 errno=0 (Success) cookie=0x0000000000000000
With this fix, the same GET correctly returned:
GET ret=-1 errno=16 (Device or resource busy)
The full cs_prctl_test also failed seven cookie assertions on the
unfixed kernel after PR_SCHED_CORE_CREATE succeeded but subsequent GETs
continued to report cookie 0.
Fixes: 7ac592aa35a6 ("sched: prctl() core-scheduling interface")
Cc: stable@vger.kernel.org
Signed-off-by: Hui Su <sh_def@163.com>
---
v2:
- No changes.
kernel/sched/core_sched.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/kernel/sched/core_sched.c b/kernel/sched/core_sched.c
index 43e0bde3038e..f119a2973ca8 100644
--- a/kernel/sched/core_sched.c
+++ b/kernel/sched/core_sched.c
@@ -177,8 +177,9 @@ int sched_core_share_pid(unsigned int cmd, pid_t pid, enum pid_type type,
}
cookie = sched_core_clone_cookie(task);
if (cookie) {
- /* XXX improve ? */
- ptr_to_hashval((void *)cookie, &id);
+ err = ptr_to_hashval((void *)cookie, &id);
+ if (err)
+ goto out;
}
err = put_user(id, (u64 __user *)uaddr);
goto out;
--
2.55.0
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH v2 2/2] selftests/sched: Retry PR_SCHED_CORE_GET on EBUSY
2026-09-13 14:10 [PATCH v2 0/2] sched/core: Handle unavailable pointer hash in PR_SCHED_CORE_GET Hui Su
2026-09-13 14:10 ` [PATCH v2 1/2] sched/core: Propagate pointer hash errors from PR_SCHED_CORE_GET Hui Su
@ 2026-09-13 14:10 ` Hui Su
1 sibling, 0 replies; 3+ messages in thread
From: Hui Su @ 2026-09-13 14:10 UTC (permalink / raw)
To: peterz
Cc: mingo, juri.lelli, vincent.guittot, dietmar.eggemann, shuah,
linux-kernel, linux-kselftest, Hui Su
During early boot, the pointer hash key may not be initialized when
PR_SCHED_CORE_GET is called. With the preceding kernel fix, GET reports
EBUSY until the pointer hash key becomes available.
Retry the operation for up to one second when it returns EBUSY. Keep the
syscall status separate from the returned cookie and abort the test if
the GET still fails, so an error value cannot be compared as a valid
cookie. Report other errors immediately instead of describing every
failed GET as an unsupported core scheduling system.
cs_prctl_test passes on x86_64 with normal random initialization.
Signed-off-by: Hui Su <sh_def@163.com>
---
v2:
- Return cookie values directly from the fatal error helper to keep the
selftest comparisons compact.
- Avoid sleeping after the final retry.
tools/testing/selftests/sched/cs_prctl_test.c | 93 +++++++++++++------
1 file changed, 63 insertions(+), 30 deletions(-)
diff --git a/tools/testing/selftests/sched/cs_prctl_test.c b/tools/testing/selftests/sched/cs_prctl_test.c
index 52d97fae4dbd..7bd0bc262a6b 100644
--- a/tools/testing/selftests/sched/cs_prctl_test.c
+++ b/tools/testing/selftests/sched/cs_prctl_test.c
@@ -51,6 +51,8 @@ static pid_t gettid(void)
#define MAX_PROCESSES 128
#define MAX_THREADS 128
+#define CORE_COOKIE_RETRIES 100
+#define CORE_COOKIE_RETRY_US 10000
static const char USAGE[] = "cs_prctl_test [options]\n"
" options:\n"
@@ -109,19 +111,43 @@ static void handle_usage(int rc, char *msg)
exit(rc);
}
-static unsigned long get_cs_cookie(int pid)
+static int get_cs_cookie(int pid, unsigned long long *cookie)
{
- unsigned long long cookie;
- int ret;
+ int i, ret, err = 0;
- ret = prctl(PR_SCHED_CORE, PR_SCHED_CORE_GET, pid, PIDTYPE_PID,
- (unsigned long)&cookie);
- if (ret) {
- printf("Not a core sched system\n");
- return -1UL;
+ for (i = 0; i < CORE_COOKIE_RETRIES; i++) {
+ ret = prctl(PR_SCHED_CORE, PR_SCHED_CORE_GET, pid, PIDTYPE_PID,
+ (unsigned long)cookie);
+ if (!ret)
+ return 0;
+
+ err = errno;
+ if (err != EBUSY || i == CORE_COOKIE_RETRIES - 1)
+ break;
+
+ usleep(CORE_COOKIE_RETRY_US);
}
- return cookie;
+ if (err == EBUSY)
+ printf("Timed out waiting for core sched cookie\n");
+ else
+ printf("Failed to get core sched cookie: %s\n", strerror(err));
+
+ return err;
+}
+
+static unsigned long long get_cs_cookie_or_die(int pid)
+{
+ unsigned long long cookie;
+ int err;
+
+ err = get_cs_cookie(pid, &cookie);
+ if (!err)
+ return cookie;
+
+ errno = err;
+ handle_error("get core sched cookie");
+ __builtin_unreachable();
}
static int child_func_thread(void __attribute__((unused))*arg)
@@ -202,15 +228,16 @@ void disp_processes(int num_processes, struct child_args proc[])
{
int i, j;
- printf("tid=%d, / tgid=%d / pgid=%d: %lx\n", gettid(), getpid(), getpgid(0),
- get_cs_cookie(getpid()));
+ printf("tid=%d, / tgid=%d / pgid=%d: %llx\n", gettid(), getpid(), getpgid(0),
+ get_cs_cookie_or_die(getpid()));
for (i = 0; i < num_processes; ++i) {
- printf(" tid=%d, / tgid=%d / pgid=%d: %lx\n", proc[i].cpid, proc[i].cpid,
- getpgid(proc[i].cpid), get_cs_cookie(proc[i].cpid));
+ printf(" tid=%d, / tgid=%d / pgid=%d: %llx\n", proc[i].cpid, proc[i].cpid,
+ getpgid(proc[i].cpid), get_cs_cookie_or_die(proc[i].cpid));
for (j = 0; j < proc[i].num_threads; ++j) {
- printf(" tid=%d, / tgid=%d / pgid=%d: %lx\n", proc[i].thr_tids[j],
- proc[i].cpid, getpgid(0), get_cs_cookie(proc[i].thr_tids[j]));
+ printf(" tid=%d, / tgid=%d / pgid=%d: %llx\n", proc[i].thr_tids[j],
+ proc[i].cpid, getpgid(0),
+ get_cs_cookie_or_die(proc[i].thr_tids[j]));
}
}
puts("\n");
@@ -280,30 +307,32 @@ int main(int argc, char *argv[])
create_processes(num_processes, num_threads, procs);
need_cleanup = 1;
disp_processes(num_processes, procs);
- validate(get_cs_cookie(0) == 0);
+ validate(get_cs_cookie_or_die(0) == 0);
printf("\n## Set a cookie on entire process group\n");
if (_prctl(PR_SCHED_CORE, PR_SCHED_CORE_CREATE, 0, PIDTYPE_PGID, 0) < 0)
handle_error("core_sched create failed -- PGID");
disp_processes(num_processes, procs);
- validate(get_cs_cookie(0) != 0);
+ validate(get_cs_cookie_or_die(0) != 0);
/* get a random process pid */
pidx = rand() % num_processes;
pid = procs[pidx].cpid;
- validate(get_cs_cookie(0) == get_cs_cookie(pid));
- validate(get_cs_cookie(0) == get_cs_cookie(procs[pidx].thr_tids[0]));
+ validate(get_cs_cookie_or_die(0) == get_cs_cookie_or_die(pid));
+ validate(get_cs_cookie_or_die(0) ==
+ get_cs_cookie_or_die(procs[pidx].thr_tids[0]));
printf("\n## Set a new cookie on entire process/TGID [%d]\n", pid);
if (_prctl(PR_SCHED_CORE, PR_SCHED_CORE_CREATE, pid, PIDTYPE_TGID, 0) < 0)
handle_error("core_sched create failed -- TGID");
disp_processes(num_processes, procs);
- validate(get_cs_cookie(0) != get_cs_cookie(pid));
- validate(get_cs_cookie(pid) != 0);
- validate(get_cs_cookie(pid) == get_cs_cookie(procs[pidx].thr_tids[0]));
+ validate(get_cs_cookie_or_die(0) != get_cs_cookie_or_die(pid));
+ validate(get_cs_cookie_or_die(pid) != 0);
+ validate(get_cs_cookie_or_die(pid) ==
+ get_cs_cookie_or_die(procs[pidx].thr_tids[0]));
printf("\n## Copy the cookie of current/PGID[%d], to pid [%d] as PIDTYPE_PID\n",
getpid(), pid);
@@ -311,9 +340,10 @@ int main(int argc, char *argv[])
handle_error("core_sched share to itself failed -- PID");
disp_processes(num_processes, procs);
- validate(get_cs_cookie(0) == get_cs_cookie(pid));
- validate(get_cs_cookie(pid) != 0);
- validate(get_cs_cookie(pid) != get_cs_cookie(procs[pidx].thr_tids[0]));
+ validate(get_cs_cookie_or_die(0) == get_cs_cookie_or_die(pid));
+ validate(get_cs_cookie_or_die(pid) != 0);
+ validate(get_cs_cookie_or_die(pid) !=
+ get_cs_cookie_or_die(procs[pidx].thr_tids[0]));
printf("\n## Copy cookie from a thread [%d] to current/PGID [%d] as PIDTYPE_PID\n",
procs[pidx].thr_tids[0], getpid());
@@ -322,17 +352,20 @@ int main(int argc, char *argv[])
handle_error("core_sched share from thread failed -- PID");
disp_processes(num_processes, procs);
- validate(get_cs_cookie(0) == get_cs_cookie(procs[pidx].thr_tids[0]));
- validate(get_cs_cookie(pid) != get_cs_cookie(procs[pidx].thr_tids[0]));
+ validate(get_cs_cookie_or_die(0) ==
+ get_cs_cookie_or_die(procs[pidx].thr_tids[0]));
+ validate(get_cs_cookie_or_die(pid) !=
+ get_cs_cookie_or_die(procs[pidx].thr_tids[0]));
printf("\n## Copy cookie from current [%d] to current as pidtype PGID\n", getpid());
if (_prctl(PR_SCHED_CORE, PR_SCHED_CORE_SHARE_TO, 0, PIDTYPE_PGID, 0) < 0)
handle_error("core_sched share to self failed -- PGID");
disp_processes(num_processes, procs);
- validate(get_cs_cookie(0) == get_cs_cookie(pid));
- validate(get_cs_cookie(pid) != 0);
- validate(get_cs_cookie(pid) == get_cs_cookie(procs[pidx].thr_tids[0]));
+ validate(get_cs_cookie_or_die(0) == get_cs_cookie_or_die(pid));
+ validate(get_cs_cookie_or_die(pid) != 0);
+ validate(get_cs_cookie_or_die(pid) ==
+ get_cs_cookie_or_die(procs[pidx].thr_tids[0]));
validate(_prctl(PR_SCHED_CORE, PR_SCHED_CORE_MAX, 0, PIDTYPE_PGID, 0) < 0
&& errno == EINVAL);
--
2.55.0
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-09-13 14:11 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-13 14:10 [PATCH v2 0/2] sched/core: Handle unavailable pointer hash in PR_SCHED_CORE_GET Hui Su
2026-09-13 14:10 ` [PATCH v2 1/2] sched/core: Propagate pointer hash errors from PR_SCHED_CORE_GET Hui Su
2026-09-13 14:10 ` [PATCH v2 2/2] selftests/sched: Retry PR_SCHED_CORE_GET on EBUSY Hui Su
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®