[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