Skip to content

Commit

Permalink
criu: move timers dump/restore code into separate file
Browse files Browse the repository at this point in the history
Fixes: #335

Signed-off-by: ccccrrrr <zcr1006@gmail.com>
  • Loading branch information
ccccrrrr authored and avagin committed Mar 25, 2024
1 parent 2355a2a commit 6182876
Show file tree
Hide file tree
Showing 7 changed files with 419 additions and 396 deletions.
1 change: 1 addition & 0 deletions criu/Makefile.crtools
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ obj-y += servicefd.o
obj-y += pie-util-vdso.o
obj-y += vdso.o
obj-y += timens.o
obj-y += timer.o
obj-$(CONFIG_HAS_LIBBPF) += bpfmap.o
obj-$(CONFIG_COMPAT) += pie-util-vdso-elf32.o
CFLAGS_pie-util-vdso-elf32.o += -DCONFIG_VDSO_32
Expand Down
1 change: 1 addition & 0 deletions criu/cr-dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
#include "pidfd-store.h"
#include "apparmor.h"
#include "asm/dump.h"
#include "timer.h"

/*
* Architectures can overwrite this function to restore register sets that
Expand Down
242 changes: 1 addition & 241 deletions criu/cr-restore.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
#include "restore.h"

#include "cr-errno.h"
#include "timer.h"

#ifndef arch_export_restore_thread
#define arch_export_restore_thread __export_restore_thread
Expand All @@ -118,7 +119,6 @@ static int restore_task_with_children(void *);
static int sigreturn_restore(pid_t pid, struct task_restore_args *ta, unsigned long alen, CoreEntry *core);
static int prepare_restorer_blob(void);
static int prepare_rlimits(int pid, struct task_restore_args *, CoreEntry *core);
static int prepare_posix_timers(int pid, struct task_restore_args *ta, CoreEntry *core);
static int prepare_signals(int pid, struct task_restore_args *, CoreEntry *core);

/*
Expand Down Expand Up @@ -882,7 +882,6 @@ static int prepare_proc_misc(pid_t pid, TaskCoreEntry *tc, struct task_restore_a
return 0;
}

static int prepare_itimers(int pid, struct task_restore_args *args, CoreEntry *core);
static int prepare_mm(pid_t pid, struct task_restore_args *args);

static int restore_one_alive_task(int pid, CoreEntry *core)
Expand Down Expand Up @@ -2719,245 +2718,6 @@ static long restorer_get_vma_hint(struct list_head *tgt_vma_list, struct list_he
return -1;
}

static inline int timeval_valid(struct timeval *tv)
{
return (tv->tv_sec >= 0) && ((unsigned long)tv->tv_usec < USEC_PER_SEC);
}

static inline int decode_itimer(char *n, ItimerEntry *ie, struct itimerval *val)
{
if (ie->isec == 0 && ie->iusec == 0) {
memzero_p(val);
return 0;
}

val->it_interval.tv_sec = ie->isec;
val->it_interval.tv_usec = ie->iusec;

if (!timeval_valid(&val->it_interval)) {
pr_err("Invalid timer interval\n");
return -1;
}

if (ie->vsec == 0 && ie->vusec == 0) {
/*
* Remaining time was too short. Set it to
* interval to make the timer armed and work.
*/
val->it_value.tv_sec = ie->isec;
val->it_value.tv_usec = ie->iusec;
} else {
val->it_value.tv_sec = ie->vsec;
val->it_value.tv_usec = ie->vusec;
}

if (!timeval_valid(&val->it_value)) {
pr_err("Invalid timer value\n");
return -1;
}

pr_info("Restored %s timer to %ld.%ld -> %ld.%ld\n", n, val->it_value.tv_sec, val->it_value.tv_usec,
val->it_interval.tv_sec, val->it_interval.tv_usec);

return 0;
}

/*
* Legacy itimers restore from CR_FD_ITIMERS
*/

static int prepare_itimers_from_fd(int pid, struct task_restore_args *args)
{
int ret = -1;
struct cr_img *img;
ItimerEntry *ie;

if (!deprecated_ok("Itimers"))
return -1;

img = open_image(CR_FD_ITIMERS, O_RSTR, pid);
if (!img)
return -1;

ret = pb_read_one(img, &ie, PB_ITIMER);
if (ret < 0)
goto out;
ret = decode_itimer("real", ie, &args->itimers[0]);
itimer_entry__free_unpacked(ie, NULL);
if (ret < 0)
goto out;

ret = pb_read_one(img, &ie, PB_ITIMER);
if (ret < 0)
goto out;
ret = decode_itimer("virt", ie, &args->itimers[1]);
itimer_entry__free_unpacked(ie, NULL);
if (ret < 0)
goto out;

ret = pb_read_one(img, &ie, PB_ITIMER);
if (ret < 0)
goto out;
ret = decode_itimer("prof", ie, &args->itimers[2]);
itimer_entry__free_unpacked(ie, NULL);
if (ret < 0)
goto out;
out:
close_image(img);
return ret;
}

static int prepare_itimers(int pid, struct task_restore_args *args, CoreEntry *core)
{
int ret = 0;
TaskTimersEntry *tte = core->tc->timers;

if (!tte)
return prepare_itimers_from_fd(pid, args);

ret |= decode_itimer("real", tte->real, &args->itimers[0]);
ret |= decode_itimer("virt", tte->virt, &args->itimers[1]);
ret |= decode_itimer("prof", tte->prof, &args->itimers[2]);

return ret;
}

static inline int timespec_valid(struct timespec *ts)
{
return (ts->tv_sec >= 0) && ((unsigned long)ts->tv_nsec < NSEC_PER_SEC);
}

static inline int decode_posix_timer(PosixTimerEntry *pte, struct restore_posix_timer *pt)
{
pt->val.it_interval.tv_sec = pte->isec;
pt->val.it_interval.tv_nsec = pte->insec;

if (!timespec_valid(&pt->val.it_interval)) {
pr_err("Invalid timer interval(posix)\n");
return -1;
}

if (pte->vsec == 0 && pte->vnsec == 0) {
/*
* Remaining time was too short. Set it to
* interval to make the timer armed and work.
*/
pt->val.it_value.tv_sec = pte->isec;
pt->val.it_value.tv_nsec = pte->insec;
} else {
pt->val.it_value.tv_sec = pte->vsec;
pt->val.it_value.tv_nsec = pte->vnsec;
}

if (!timespec_valid(&pt->val.it_value)) {
pr_err("Invalid timer value(posix)\n");
return -1;
}

pt->spt.it_id = pte->it_id;
pt->spt.clock_id = pte->clock_id;
pt->spt.si_signo = pte->si_signo;
pt->spt.it_sigev_notify = pte->it_sigev_notify;
pt->spt.sival_ptr = decode_pointer(pte->sival_ptr);
pt->spt.notify_thread_id = pte->notify_thread_id;
pt->overrun = pte->overrun;

return 0;
}

static int cmp_posix_timer_proc_id(const void *p1, const void *p2)
{
return ((struct restore_posix_timer *)p1)->spt.it_id - ((struct restore_posix_timer *)p2)->spt.it_id;
}

static void sort_posix_timers(struct task_restore_args *ta)
{
void *tmem;

/*
* This is required for restorer's create_posix_timers(),
* it will probe them one-by-one for the desired ID, since
* kernel doesn't provide another API for timer creation
* with given ID.
*/

if (ta->posix_timers_n > 0) {
tmem = rst_mem_remap_ptr((unsigned long)ta->posix_timers, RM_PRIVATE);
qsort(tmem, ta->posix_timers_n, sizeof(struct restore_posix_timer), cmp_posix_timer_proc_id);
}
}

/*
* Legacy posix timers restoration from CR_FD_POSIX_TIMERS
*/

static int prepare_posix_timers_from_fd(int pid, struct task_restore_args *ta)
{
struct cr_img *img;
int ret = -1;
struct restore_posix_timer *t;

if (!deprecated_ok("Posix timers"))
return -1;

img = open_image(CR_FD_POSIX_TIMERS, O_RSTR, pid);
if (!img)
return -1;

ta->posix_timers_n = 0;
while (1) {
PosixTimerEntry *pte;

ret = pb_read_one_eof(img, &pte, PB_POSIX_TIMER);
if (ret <= 0)
break;

t = rst_mem_alloc(sizeof(struct restore_posix_timer), RM_PRIVATE);
if (!t)
break;

ret = decode_posix_timer(pte, t);
if (ret < 0)
break;

posix_timer_entry__free_unpacked(pte, NULL);
ta->posix_timers_n++;
}

close_image(img);
if (!ret)
sort_posix_timers(ta);

return ret;
}

static int prepare_posix_timers(int pid, struct task_restore_args *ta, CoreEntry *core)
{
int i, ret = -1;
TaskTimersEntry *tte = core->tc->timers;
struct restore_posix_timer *t;

ta->posix_timers = (struct restore_posix_timer *)rst_mem_align_cpos(RM_PRIVATE);

if (!tte)
return prepare_posix_timers_from_fd(pid, ta);

ta->posix_timers_n = tte->n_posix;
for (i = 0; i < ta->posix_timers_n; i++) {
t = rst_mem_alloc(sizeof(struct restore_posix_timer), RM_PRIVATE);
if (!t)
goto out;

if (decode_posix_timer(tte->posix[i], t))
goto out;
}

ret = 0;
sort_posix_timers(ta);
out:
return ret;
}

static int prepare_mm(pid_t pid, struct task_restore_args *args)
{
int exe_fd, i, ret = -1;
Expand Down
5 changes: 0 additions & 5 deletions criu/include/parasite-syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,6 @@ struct parasite_ctl;
struct parasite_thread_ctl;

extern int parasite_dump_sigacts_seized(struct parasite_ctl *ctl, struct pstree_item *);
extern int parasite_dump_itimers_seized(struct parasite_ctl *ctl, struct pstree_item *);

struct proc_posix_timers_stat;
extern int parasite_dump_posix_timers_seized(struct proc_posix_timers_stat *proc_args, struct parasite_ctl *ctl,
struct pstree_item *);

extern int parasite_dump_misc_seized(struct parasite_ctl *ctl, struct parasite_dump_misc *misc);
extern int parasite_dump_creds(struct parasite_ctl *ctl, CredsEntry *ce);
Expand Down
17 changes: 17 additions & 0 deletions criu/include/timer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#ifndef __CR_TIMER_H__
#define __CR_TIMER_H__

#include "images/core.pb-c.h"

struct task_restore_args;
struct pstree_item;
struct parasite_ctl;
struct proc_posix_timers_stat;

extern int prepare_itimers(int pid, struct task_restore_args *args, CoreEntry *core);
extern int prepare_posix_timers(int pid, struct task_restore_args *ta, CoreEntry *core);

extern int parasite_dump_itimers_seized(struct parasite_ctl *ctl, struct pstree_item *item);
extern int parasite_dump_posix_timers_seized(struct proc_posix_timers_stat *proc_args, struct parasite_ctl *ctl,
struct pstree_item *item);

Check warning on line 16 in criu/include/timer.h

View workflow job for this annotation

GitHub Actions / build

#endif
Loading

0 comments on commit 6182876

Please sign in to comment.