[CRIU] [PATCH 4/4] posix-timer: Add restore functionality and structures.
Pavel Tikhomirov
snorcht at gmail.com
Sun May 19 18:24:27 EDT 2013
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;
+ }
+ }
+
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
More information about the CRIU
mailing list