[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