criu: restore timer_slack_ns per thread

During restore, set the per-thread timer_slack_ns value via
PR_SET_TIMERSLACK if the image contains it. This completes the
checkpoint/restore cycle for the timer slack property.

The restore is skipped for images that do not contain the field,
maintaining backward compatibility with older image formats.

Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
This commit is contained in:
Ahmed Elaidy 2026-03-03 00:18:14 +02:00 committed by Andrei Vagin
parent dfed6f0730
commit b258d64546
3 changed files with 29 additions and 0 deletions

View file

@ -3466,6 +3466,11 @@ static int sigreturn_restore(pid_t pid, struct task_restore_args *task_args, uns
goto err;
}
if (tcore->thread_core->has_timerslack_ns) {
thread_args[i].has_timerslack_ns = true;
thread_args[i].timerslack_ns = tcore->thread_core->timerslack_ns;
}
ret = prep_sched_info(&thread_args[i].sp, tcore->thread_core);
if (ret)
goto err;

View file

@ -114,6 +114,8 @@ struct thread_restore_args {
unsigned int siginfo_n;
int pdeath_sig;
bool has_timerslack_ns;
unsigned long timerslack_ns;
struct thread_creds_args *creds_args;

View file

@ -66,6 +66,10 @@
#define PR_SET_PDEATHSIG 1
#endif
#ifndef PR_SET_TIMERSLACK
#define PR_SET_TIMERSLACK 29
#endif
#ifndef PR_SET_CHILD_SUBREAPER
#define PR_SET_CHILD_SUBREAPER 36
#endif
@ -417,6 +421,22 @@ static inline int restore_pdeath_sig(struct thread_restore_args *ta)
return 0;
}
static inline int restore_timerslack(struct thread_restore_args *ta)
{
int ret;
if (!ta->has_timerslack_ns)
return 0;
ret = sys_prctl(PR_SET_TIMERSLACK, ta->timerslack_ns, 0, 0, 0);
if (ret) {
pr_err("Unable to set PR_SET_TIMERSLACK(%lu): %d\n", ta->timerslack_ns, ret);
return -1;
}
return 0;
}
static int restore_dumpable_flag(MmEntry *mme)
{
int current_dumpable;
@ -830,6 +850,7 @@ __visible long __export_restore_thread(struct thread_restore_args *args)
ret = restore_creds(args->creds_args, args->ta->proc_fd, args->ta->lsm_type, args->ta->uid);
ret = ret || restore_dumpable_flag(&args->ta->mm);
ret = ret || restore_pdeath_sig(args);
ret = ret || restore_timerslack(args);
if (ret)
BUG();
@ -2303,6 +2324,7 @@ __visible long __export_restore_task(struct task_restore_args *args)
ret = restore_creds(args->t->creds_args, args->proc_fd, args->lsm_type, args->uid);
ret = ret || restore_dumpable_flag(&args->mm);
ret = ret || restore_pdeath_sig(args->t);
ret = ret || restore_timerslack(args->t);
ret = ret || restore_child_subreaper(args->child_subreaper);
atomic_set(&thread_inprogress, args->nr_threads);