mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-31 06:15:24 +00:00
mm: Split mm parts from task core image
The mm_xxx bits are per-mm_struct, not per-task_struct in kernel. Thus, when we support CLONE_VM we'd better have these bits in a separate image file. Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
61
cr-dump.c
61
cr-dump.c
@@ -683,20 +683,22 @@ static int dump_task_creds(pid_t pid, const struct parasite_dump_misc *misc,
|
||||
#define assign_reg(dst, src, e) dst.e = (__typeof__(dst.e))src.e
|
||||
#define assign_array(dst, src, e) memcpy(&dst.e, &src.e, sizeof(dst.e))
|
||||
|
||||
static int get_task_auxv(pid_t pid, struct core_entry *core)
|
||||
static int get_task_auxv(pid_t pid, struct mm_entry *mm)
|
||||
{
|
||||
int fd = open_proc(pid, "auxv");
|
||||
int ret, i;
|
||||
int fd, ret, i;
|
||||
|
||||
pr_info("Obtainting task auvx ... ");
|
||||
|
||||
fd = open_proc(pid, "auxv");
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < AT_VECTOR_SIZE; i++) {
|
||||
ret = read(fd, &core->tc.mm_saved_auxv[i],
|
||||
sizeof(core->tc.mm_saved_auxv[0]));
|
||||
ret = read(fd, &mm->mm_saved_auxv[i],
|
||||
sizeof(mm->mm_saved_auxv[0]));
|
||||
if (ret == 0)
|
||||
break;
|
||||
else if (ret != sizeof(core->tc.mm_saved_auxv[0])) {
|
||||
else if (ret != sizeof(mm->mm_saved_auxv[0])) {
|
||||
ret = -1;
|
||||
pr_perror("Error readind %d's auxv[%d]",
|
||||
pid, i);
|
||||
@@ -705,12 +707,36 @@ static int get_task_auxv(pid_t pid, struct core_entry *core)
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
err:
|
||||
close_safe(&fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dump_task_mm(pid_t pid, const struct proc_pid_stat *stat,
|
||||
const struct parasite_dump_misc *misc, const struct cr_fdset *fdset)
|
||||
{
|
||||
struct mm_entry mme;
|
||||
|
||||
mme.mm_start_code = stat->start_code;
|
||||
mme.mm_end_code = stat->end_code;
|
||||
mme.mm_start_data = stat->start_data;
|
||||
mme.mm_end_data = stat->end_data;
|
||||
mme.mm_start_stack = stat->start_stack;
|
||||
mme.mm_start_brk = stat->start_brk;
|
||||
|
||||
mme.mm_arg_start = stat->arg_start;
|
||||
mme.mm_arg_end = stat->arg_end;
|
||||
mme.mm_env_start = stat->env_start;
|
||||
mme.mm_env_end = stat->env_end;
|
||||
|
||||
mme.mm_brk = misc->brk;
|
||||
|
||||
if (get_task_auxv(pid, &mme))
|
||||
return -1;
|
||||
|
||||
return write_img(fdset_fd(fdset, CR_FD_MM), &mme);
|
||||
}
|
||||
|
||||
static int get_task_personality(pid_t pid, u32 *personality)
|
||||
{
|
||||
FILE *file = NULL;
|
||||
@@ -860,29 +886,14 @@ static int dump_task_core_all(pid_t pid, const struct proc_pid_stat *stat,
|
||||
|
||||
strncpy((char *)core->tc.comm, stat->comm, TASK_COMM_LEN);
|
||||
core->tc.flags = stat->flags;
|
||||
core->tc.mm_start_code = stat->start_code;
|
||||
core->tc.mm_end_code = stat->end_code;
|
||||
core->tc.mm_start_data = stat->start_data;
|
||||
core->tc.mm_end_data = stat->end_data;
|
||||
core->tc.mm_start_stack = stat->start_stack;
|
||||
core->tc.mm_start_brk = stat->start_brk;
|
||||
|
||||
core->tc.mm_arg_start = stat->arg_start;
|
||||
core->tc.mm_arg_end = stat->arg_end;
|
||||
core->tc.mm_env_start = stat->env_start;
|
||||
core->tc.mm_env_end = stat->env_end;
|
||||
|
||||
core->tc.mm_brk = misc->brk;
|
||||
ret = dump_task_mm(pid, stat, misc, cr_fdset);
|
||||
if (ret)
|
||||
goto err_free;
|
||||
|
||||
BUILD_BUG_ON(sizeof(core->tc.blk_sigset) != sizeof(k_rtsigset_t));
|
||||
memcpy(&core->tc.blk_sigset, &misc->blocked, sizeof(k_rtsigset_t));
|
||||
|
||||
pr_info("Obtainting task auvx ... ");
|
||||
ret = get_task_auxv(pid, core);
|
||||
if (ret)
|
||||
goto err_free;
|
||||
pr_info("OK\n");
|
||||
|
||||
core->tc.task_state = TASK_ALIVE;
|
||||
core->tc.exit_code = 0;
|
||||
|
||||
|
19
cr-restore.c
19
cr-restore.c
@@ -1026,6 +1026,21 @@ static struct vma_entry *vma_list_remap(void *addr, unsigned long len, struct li
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int prepare_mm(pid_t pid, struct task_restore_core_args *args)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = open_image_ro(CR_FD_MM, pid);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
if (read_img(fd, &args->mm) < 0)
|
||||
return -1;
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sigreturn_restore(pid_t pid, struct list_head *tgt_vmas, int nr_vmas)
|
||||
{
|
||||
long restore_code_len, restore_task_vma_len;
|
||||
@@ -1205,6 +1220,10 @@ static int sigreturn_restore(pid_t pid, struct list_head *tgt_vmas, int nr_vmas)
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
ret = prepare_mm(pid, task_args);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
mutex_init(&task_args->rst_lock);
|
||||
|
||||
/*
|
||||
|
37
cr-show.c
37
cr-show.c
@@ -473,18 +473,7 @@ static void show_core_rest(int fd_core)
|
||||
pr_msg("\t Exit code: %u\n",
|
||||
(unsigned int)tc.exit_code);
|
||||
|
||||
pr_msg("\tBrk: %lx\n", tc.mm_brk);
|
||||
pr_msg("\tStart code: %lx\n", tc.mm_start_code);
|
||||
pr_msg("\tEnd code: %lx\n", tc.mm_end_code);
|
||||
pr_msg("\tStart stack: %lx\n", tc.mm_start_stack);
|
||||
pr_msg("\tStart data: %lx\n", tc.mm_start_data);
|
||||
pr_msg("\tEnd data: %lx\n", tc.mm_end_data);
|
||||
pr_msg("\tStart brk: %lx\n", tc.mm_start_brk);
|
||||
pr_msg("\tArg start: %lx\n", tc.mm_arg_start);
|
||||
pr_msg("\tArg end: %lx\n", tc.mm_arg_end);
|
||||
pr_msg("\tEnv start: %lx\n", tc.mm_env_start);
|
||||
pr_msg("\tEnv end: %lx\n", tc.mm_env_end);
|
||||
pr_msg("\n\tBlkSig: %lx\n", tc.blk_sigset);
|
||||
pr_msg("\tBlkSig: %lx\n", tc.blk_sigset);
|
||||
pr_msg("\n");
|
||||
|
||||
err:
|
||||
@@ -514,6 +503,30 @@ out:
|
||||
pr_img_tail(CR_FD_CORE);
|
||||
}
|
||||
|
||||
void show_mm(int fd_mm, struct cr_options *o)
|
||||
{
|
||||
struct mm_entry mme;
|
||||
|
||||
pr_img_head(CR_FD_MM);
|
||||
|
||||
if (read_img(fd_mm, &mme) < 0)
|
||||
goto out;
|
||||
|
||||
pr_msg("\tBrk: %lx\n", mme.mm_brk);
|
||||
pr_msg("\tStart code: %lx\n", mme.mm_start_code);
|
||||
pr_msg("\tEnd code: %lx\n", mme.mm_end_code);
|
||||
pr_msg("\tStart stack: %lx\n", mme.mm_start_stack);
|
||||
pr_msg("\tStart data: %lx\n", mme.mm_start_data);
|
||||
pr_msg("\tEnd data: %lx\n", mme.mm_end_data);
|
||||
pr_msg("\tStart brk: %lx\n", mme.mm_start_brk);
|
||||
pr_msg("\tArg start: %lx\n", mme.mm_arg_start);
|
||||
pr_msg("\tArg end: %lx\n", mme.mm_arg_end);
|
||||
pr_msg("\tEnv start: %lx\n", mme.mm_env_start);
|
||||
pr_msg("\tEnv end: %lx\n", mme.mm_env_end);
|
||||
out:
|
||||
pr_img_tail(CR_FD_MM);
|
||||
}
|
||||
|
||||
static int cr_parse_file(struct cr_options *opts)
|
||||
{
|
||||
u32 magic;
|
||||
|
@@ -68,6 +68,12 @@ struct cr_fd_desc_tmpl fdset_template[CR_FD_MAX] = {
|
||||
.show = show_core,
|
||||
},
|
||||
|
||||
[CR_FD_MM] = {
|
||||
.fmt = FMT_FNAME_MM,
|
||||
.magic = MM_MAGIC,
|
||||
.show = show_mm,
|
||||
},
|
||||
|
||||
[CR_FD_VMAS] = {
|
||||
.fmt = FMT_FNAME_VMAS,
|
||||
.magic = VMAS_MAGIC,
|
||||
|
@@ -22,6 +22,7 @@ enum {
|
||||
CR_FD_FDINFO,
|
||||
CR_FD_PAGES,
|
||||
CR_FD_CORE,
|
||||
CR_FD_MM,
|
||||
CR_FD_VMAS,
|
||||
CR_FD_SIGACT,
|
||||
CR_FD_ITIMERS,
|
||||
@@ -84,6 +85,7 @@ void show_files(int fd_files, struct cr_options *o);
|
||||
void show_pages(int fd_pages, struct cr_options *o);
|
||||
void show_reg_files(int fd_reg_files, struct cr_options *o);
|
||||
void show_core(int fd_core, struct cr_options *o);
|
||||
void show_mm(int fd_mm, struct cr_options *o);
|
||||
void show_vmas(int fd_vma, struct cr_options *o);
|
||||
void show_pipes(int fd_pipes, struct cr_options *o);
|
||||
void show_pipes_data(int fd_pipes, struct cr_options *o);
|
||||
@@ -100,6 +102,7 @@ extern struct cr_fd_desc_tmpl fdset_template[CR_FD_MAX];
|
||||
#define FMT_FNAME_SHMEM_PAGES "pages-shmem-%ld.img"
|
||||
#define FMT_FNAME_REG_FILES "reg-files.img"
|
||||
#define FMT_FNAME_CORE "core-%d.img"
|
||||
#define FMT_FNAME_MM "mm-%d.img"
|
||||
#define FMT_FNAME_VMAS "vmas-%d.img"
|
||||
#define FMT_FNAME_PIPES "pipes.img"
|
||||
#define FMT_FNAME_PIPES_DATA "pipes-data.img"
|
||||
|
@@ -29,6 +29,7 @@
|
||||
#define IPCNS_SEM_MAGIC 0x59573019 /* St. Petersburg */
|
||||
#define REG_FILES_MAGIC 0x50363636 /* Belgorod */
|
||||
#define FS_MAGIC 0x51403912 /* Voronezh */
|
||||
#define MM_MAGIC 0x57492820 /* Pskov */
|
||||
|
||||
#define PIPEFS_MAGIC 0x50495045
|
||||
|
||||
@@ -353,21 +354,24 @@ struct task_core_entry {
|
||||
u32 personality;
|
||||
u8 comm[TASK_COMM_LEN];
|
||||
u32 flags;
|
||||
u64 mm_start_code;
|
||||
u64 mm_end_code;
|
||||
u64 mm_start_data;
|
||||
u64 mm_end_data;
|
||||
u64 mm_start_stack;
|
||||
u64 mm_start_brk;
|
||||
u64 mm_brk;
|
||||
u64 mm_arg_start;
|
||||
u64 mm_arg_end;
|
||||
u64 mm_env_start;
|
||||
u64 mm_env_end;
|
||||
u64 blk_sigset;
|
||||
u64 mm_saved_auxv[AT_VECTOR_SIZE];
|
||||
};
|
||||
|
||||
struct mm_entry {
|
||||
u64 mm_start_code;
|
||||
u64 mm_end_code;
|
||||
u64 mm_start_data;
|
||||
u64 mm_end_data;
|
||||
u64 mm_start_stack;
|
||||
u64 mm_start_brk;
|
||||
u64 mm_brk;
|
||||
u64 mm_arg_start;
|
||||
u64 mm_arg_end;
|
||||
u64 mm_env_start;
|
||||
u64 mm_env_end;
|
||||
u64 mm_saved_auxv[AT_VECTOR_SIZE];
|
||||
} __packed;
|
||||
|
||||
struct core_entry {
|
||||
union {
|
||||
struct {
|
||||
|
@@ -84,6 +84,7 @@ struct task_restore_core_args {
|
||||
struct itimerval itimers[3];
|
||||
|
||||
struct creds_entry creds;
|
||||
struct mm_entry mm;
|
||||
} __aligned(sizeof(long));
|
||||
|
||||
struct pt_regs {
|
||||
|
27
restorer.c
27
restorer.c
@@ -428,19 +428,20 @@ long restore_task(struct task_restore_core_args *args)
|
||||
* Tune up the task fields.
|
||||
*/
|
||||
ret |= sys_prctl_safe(PR_SET_NAME, (long)core_entry->tc.comm, 0, 0);
|
||||
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_CODE, (long)core_entry->tc.mm_start_code, 0);
|
||||
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_END_CODE, (long)core_entry->tc.mm_end_code, 0);
|
||||
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_DATA, (long)core_entry->tc.mm_start_data, 0);
|
||||
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_END_DATA, (long)core_entry->tc.mm_end_data, 0);
|
||||
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_STACK,(long)core_entry->tc.mm_start_stack, 0);
|
||||
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_BRK, (long)core_entry->tc.mm_start_brk, 0);
|
||||
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_BRK, (long)core_entry->tc.mm_brk, 0);
|
||||
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ARG_START, (long)core_entry->tc.mm_arg_start, 0);
|
||||
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ARG_END, (long)core_entry->tc.mm_arg_end, 0);
|
||||
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ENV_START, (long)core_entry->tc.mm_env_start, 0);
|
||||
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ENV_END, (long)core_entry->tc.mm_env_end, 0);
|
||||
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_AUXV, (long)core_entry->tc.mm_saved_auxv,
|
||||
sizeof(core_entry->tc.mm_saved_auxv));
|
||||
|
||||
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_CODE, (long)args->mm.mm_start_code, 0);
|
||||
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_END_CODE, (long)args->mm.mm_end_code, 0);
|
||||
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_DATA, (long)args->mm.mm_start_data, 0);
|
||||
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_END_DATA, (long)args->mm.mm_end_data, 0);
|
||||
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_STACK, (long)args->mm.mm_start_stack, 0);
|
||||
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_BRK, (long)args->mm.mm_start_brk, 0);
|
||||
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_BRK, (long)args->mm.mm_brk, 0);
|
||||
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ARG_START, (long)args->mm.mm_arg_start, 0);
|
||||
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ARG_END, (long)args->mm.mm_arg_end, 0);
|
||||
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ENV_START, (long)args->mm.mm_env_start, 0);
|
||||
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ENV_END, (long)args->mm.mm_env_end, 0);
|
||||
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_AUXV, (long)args->mm.mm_saved_auxv,
|
||||
sizeof(args->mm.mm_saved_auxv));
|
||||
if (ret)
|
||||
goto core_restore_end;
|
||||
|
||||
|
Reference in New Issue
Block a user