[CRIU] [PATCH 4/4] posix-timer: Add restore functionality and structures.
Andrew Vagin
avagin at parallels.com
Mon May 20 06:07:03 EDT 2013
On Mon, May 20, 2013 at 02:24:27AM +0400, Pavel Tikhomirov wrote:
>
> Signed-off-by: Pavel Tikhomirov <snorcht at gmail.com>
> ---
> cr-restore.c | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++-
> include/restorer.h | 21 +++++++++
> include/util.h | 1 +
> pie/restorer.c | 35 +++++++++++++++
> 4 files changed, 177 insertions(+), 2 deletions(-)
>
> diff --git a/cr-restore.c b/cr-restore.c
> index 9afd2ae..b1fa082 100644
> --- a/cr-restore.c
> +++ b/cr-restore.c
> @@ -61,6 +61,7 @@
> #include "protobuf.h"
> #include "protobuf/sa.pb-c.h"
> #include "protobuf/itimer.pb-c.h"
> +#include "protobuf/posix-timer.pb-c.h"
> #include "protobuf/vma.pb-c.h"
> #include "protobuf/rlimit.pb-c.h"
> #include "protobuf/pagemap.pb-c.h"
> @@ -1456,6 +1457,97 @@ out:
> return ret;
> }
>
> +static inline int posix_timer_restore_and_fix(PosixTimerEntry *pte,
> + struct restore_posix_timer *pt)
> +{
> + if (pte->isec == 0 && pte->insec == 0) {
> + memzero_p(pt);
> + return 0;
> + }
> +
> + pt->val.it_interval.tv_sec = pte->isec;
> + pt->val.it_interval.tv_nsec = pte->insec;
> +
> + if (!time_valid((unsigned long) pt->val.it_interval.tv_sec,
> + (unsigned long) pt->val.it_interval.tv_nsec, NSEC_PER_SEC)) {
> + 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 (!time_valid((unsigned long) pt->val.it_value.tv_sec,
> + (unsigned long) pt->val.it_value.tv_nsec, NSEC_PER_SEC)) {
> + pr_err("Invalid timer value(posix)\n");
> + return -1;
> + }
> +
> + pt->it_id = pte->it_id;
> + pt->clock_id = pte->clock_id;
> + pt->si_signo = pte->si_signo;
> + pt->it_sigev_notify = pte->it_sigev_notify;
> + pt->sival_ptr.i = pte->sival_ptr;
> + pt->it_pid = pte->it_pid;
> + pt->it_tid = pte->it_tid;
> + pt->overrun = pte->overrun;
> +
> + return 0;
> +}
> +
> +static int open_posix_timers_image(int pid, struct restore_posix_timer **rpt,
> + unsigned long *size, int *nr)
> +{
> + int fd, ret = -1;
> +
> + fd = open_image(CR_FD_POSIX_TIMERS, O_RSTR, pid);
> + if (fd < 0)
> + return fd;
> +
> + while (1) {
> + PosixTimerEntry *pte;
> + struct restore_posix_timer info;
> +
> + ret = pb_read_one_eof(fd, &pte, PB_POSIX_TIMERS);
> + if (ret <= 0) {
> + goto out;
> + }
> + ret = posix_timer_restore_and_fix(pte, &info);
> + if (ret < 0)
> + goto out;
> +
> + if ((*nr + 1) * sizeof(struct restore_posix_timer) > *size) {
> + unsigned long new_size = *size + PAGE_SIZE;
> +
> + if (*rpt == NULL)
> + *rpt = mmap(NULL, new_size, PROT_READ | PROT_WRITE,
> + MAP_PRIVATE | MAP_ANON, 0, 0);
> + else
> + *rpt = mremap(*rpt, *size, new_size, MREMAP_MAYMOVE);
> + if (*rpt == MAP_FAILED) {
> + pr_perror("Can't allocate memory for posix timers");
> + ret = -1;
> + goto out;
> + }
> +
> + *size = new_size;
> + }
> + memcpy(*rpt + *nr, &info, sizeof(info));
> + posix_timer_entry__free_unpacked(pte, NULL);
> + (*nr)++;
> + }
> +out:
> + close_safe(&fd);
> + return ret;
> +}
> +
> static inline int verify_cap_size(CredsEntry *ce)
> {
> return ((ce->n_cap_inh == CR_CAP_SIZE) && (ce->n_cap_eff == CR_CAP_SIZE) &&
> @@ -1793,6 +1885,10 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core)
> int *siginfo_priv_nr;
> unsigned long siginfo_size = 0;
>
> + struct restore_posix_timer *posix_timers_info_chunk = NULL;
> + int posix_timers_nr = 0;
> + unsigned long posix_timers_size = 0;
> +
> struct vm_area_list self_vmas;
> int i;
>
> @@ -1848,13 +1944,22 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core)
> siginfo_priv_nr[i] = ret;
> }
>
> + ret = open_posix_timers_image(pid, &posix_timers_info_chunk,
> + &posix_timers_size, &posix_timers_nr);
> + if (ret < 0) {
> + if (errno != ENOENT) /* backward compatibility */
> + goto err;
> + ret = 0;
> + }
> +
> restore_bootstrap_len = restorer_len +
> restore_task_vma_len +
> restore_thread_vma_len +
> SHMEMS_SIZE + TASK_ENTRIES_SIZE +
> self_vmas_len + vmas_len +
> rst_tcp_socks_size +
> - siginfo_size;
> + siginfo_size +
> + posix_timers_size;
>
> /*
> * Restorer is a blob (code + args) that will get mapped in some
> @@ -1920,6 +2025,19 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core)
> task_args->siginfo = siginfo_chunk;
> siginfo_chunk += task_args->siginfo_nr;
>
> + mem += siginfo_size;
> + if (posix_timers_info_chunk) {
> + posix_timers_info_chunk = mremap(posix_timers_info_chunk,
> + posix_timers_size, posix_timers_size,
> + MREMAP_FIXED | MREMAP_MAYMOVE, mem);
> + if(posix_timers_info_chunk == MAP_FAILED) {
> + pr_perror("mremap");
> + goto err;
> + }
> + }
> + task_args->timer_n = posix_timers_nr;
> + task_args->posix_timers = posix_timers_info_chunk;
> +
> /*
> * Get a reference to shared memory area which is
> * used to signal if shmem restoration complete
> @@ -1931,7 +2049,7 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core)
> * address.
> */
>
> - mem += siginfo_size;
> + mem += posix_timers_size;
> ret = shmem_remap(rst_shmems, mem, SHMEMS_SIZE);
> if (ret < 0)
> goto err;
> diff --git a/include/restorer.h b/include/restorer.h
> index fa3a76a..5880fe4 100644
> --- a/include/restorer.h
> +++ b/include/restorer.h
> @@ -13,6 +13,8 @@
> #include "util.h"
> #include "crtools.h"
>
> +#include <time.h>
> +
> #include "protobuf/mm.pb-c.h"
> #include "protobuf/vma.pb-c.h"
> #include "protobuf/creds.pb-c.h"
> @@ -57,6 +59,22 @@ struct rst_sched_param {
> int prio;
> };
>
> +struct restore_posix_timer {
> + int it_id;
> + int clock_id;
> + int si_signo;
> + int it_sigev_notify;
> + union{ //need to check if sizeof(int)==sizeof(pointer)
> + void * p;
> + long unsigned int i;
> + } sival_ptr;
> +
> + int it_pid;
> + int it_tid;
> + struct itimerspec val;
> + int overrun;
> +};
> +
> struct task_restore_core_args;
>
> /* Make sure it's pow2 in size */
> @@ -115,6 +133,9 @@ struct task_restore_core_args {
>
> struct itimerval itimers[3];
>
> + int timer_n;
> + struct restore_posix_timer *posix_timers;
> +
> CredsEntry creds;
> uint32_t cap_inh[CR_CAP_SIZE];
> uint32_t cap_prm[CR_CAP_SIZE];
> diff --git a/include/util.h b/include/util.h
> index e08a6fa..3fc8518 100644
> --- a/include/util.h
> +++ b/include/util.h
> @@ -283,5 +283,6 @@ extern int read_fd_link(int lfd, char *buf, size_t size);
> })
>
> #define USEC_PER_SEC 1000000L
> +#define NSEC_PER_SEC 1000000000L
>
> #endif /* __CR_UTIL_H__ */
> diff --git a/pie/restorer.c b/pie/restorer.c
> index 50d08e6..79c6437 100644
> --- a/pie/restorer.c
> +++ b/pie/restorer.c
> @@ -832,8 +832,40 @@ long __export_restore_task(struct task_restore_core_args *args)
> BUG();
>
> /* Wait until children stop to use args->task_entries */
> +
> futex_wait_while_gt(&thread_inprogress, 1);
>
> + if (args->timer_n > 0) {
> + int i, j;
> + int tmp_id = 0;
> + timer_t timeridt[512];
> + timer_t timerid;
> + struct sigevent sev;
> + for (i = 0; i < args->timer_n; i++){
> + for (j = tmp_id; j < args->posix_timers[i].it_id; j++){
> + ret = sys_timer_create(CLOCK_REALTIME, NULL, &timeridt[j]);
> + if (ret == -1)
> + goto core_restore_failed;
> + ret = sys_timer_delete(timeridt[j]);
> + if (ret == -1)
> + goto core_restore_failed;
> + }
> + sev.sigev_notify = args->posix_timers[i].it_sigev_notify;
> + sev.sigev_signo = args->posix_timers[i].si_signo;
> + sev.sigev_value.sival_ptr = args->posix_timers[i].sival_ptr.p;
> +
> + ret = sys_timer_create(args->posix_timers[i].clock_id, &sev, &timerid);
> + if (ret == -1)
> + goto core_restore_failed;
> +
> + ret = sys_timer_settime(timerid, 0, &args->posix_timers[i].val, NULL);
> + if (ret == -1)
> + goto core_restore_failed;
> +
> + tmp_id = args->posix_timers[i].it_id + 1;
> + }
> + }
> +
Could you pack this code in a separate function?
> log_set_fd(-1);
>
> /*
> @@ -852,6 +884,9 @@ long __export_restore_task(struct task_restore_core_args *args)
> if (itimer_armed(args, 2))
> sys_setitimer(ITIMER_PROF, &args->itimers[2], NULL);
>
> + //posix was here
> + //pr_err("T1 Posix restoring was here!\n");
....
> +
> ret = sys_munmap(args->task_entries, TASK_ENTRIES_SIZE);
> if (ret < 0) {
> ret = ((long)__LINE__ << 16) | ((-ret) & 0xffff);
> --
> 1.7.9.5
>
> _______________________________________________
> CRIU mailing list
> CRIU at openvz.org
> https://lists.openvz.org/mailman/listinfo/criu
More information about the CRIU
mailing list