mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-31 22:35:33 +00:00
restore: Don't write to vma image on restore
This is not good to update images while restoring. Thus, read vma_entry-es once into a list, put opened (when required) fds in there and make restorer walk the entries in mem, not those read from the image file. Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
87
cr-restore.c
87
cr-restore.c
@@ -103,7 +103,7 @@ pid_t pstree_pid;
|
||||
struct pstree_item *me;
|
||||
|
||||
static int restore_task_with_children(void *);
|
||||
static int sigreturn_restore(pid_t pid);
|
||||
static int sigreturn_restore(pid_t pid, struct list_head *vmas, int nr_vmas);
|
||||
|
||||
static void show_saved_shmems(void)
|
||||
{
|
||||
@@ -532,60 +532,67 @@ static int get_shmem_fd(int pid, struct vma_entry *vi)
|
||||
return f;
|
||||
}
|
||||
|
||||
static int fixup_vma_fds(int pid, int fd)
|
||||
static int read_and_open_vmas(int pid, struct list_head *vmas, int *nr_vmas)
|
||||
{
|
||||
int fd, ret = -1;
|
||||
|
||||
fd = open_image_ro(CR_FD_VMAS, pid);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
*nr_vmas = 0;
|
||||
while (1) {
|
||||
struct vma_entry vi;
|
||||
int ret = 0;
|
||||
struct vma_area *vma;
|
||||
|
||||
ret = read_img_eof(fd, &vi);
|
||||
ret = -1;
|
||||
vma = alloc_vma_area();
|
||||
if (!vma)
|
||||
break;
|
||||
|
||||
(*nr_vmas)++;
|
||||
list_add_tail(&vma->list, vmas);
|
||||
ret = read_img_eof(fd, &vma->vma);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
break;
|
||||
|
||||
if (!(vma_entry_is(&vi, VMA_AREA_REGULAR)))
|
||||
if (!(vma_entry_is(&vma->vma, VMA_AREA_REGULAR)))
|
||||
continue;
|
||||
|
||||
pr_info("%d: Fixing %016lx-%016lx %016lx vma\n",
|
||||
pid, vi.start, vi.end, vi.pgoff);
|
||||
pr_info("%d: Opening %016lx-%016lx %016lx vma\n",
|
||||
pid, vma->vma.start, vma->vma.end, vma->vma.pgoff);
|
||||
|
||||
if (vma_entry_is(&vi, VMA_AREA_SYSVIPC))
|
||||
ret = vi.shmid;
|
||||
else if (vma_entry_is(&vi, VMA_ANON_SHARED))
|
||||
ret = get_shmem_fd(pid, &vi);
|
||||
else if (vma_entry_is(&vi, VMA_FILE_PRIVATE) ||
|
||||
vma_entry_is(&vi, VMA_FILE_SHARED))
|
||||
ret = get_filemap_fd(pid, &vi);
|
||||
if (vma_entry_is(&vma->vma, VMA_AREA_SYSVIPC))
|
||||
ret = vma->vma.shmid;
|
||||
else if (vma_entry_is(&vma->vma, VMA_ANON_SHARED))
|
||||
ret = get_shmem_fd(pid, &vma->vma);
|
||||
else if (vma_entry_is(&vma->vma, VMA_FILE_PRIVATE) ||
|
||||
vma_entry_is(&vma->vma, VMA_FILE_SHARED))
|
||||
ret = get_filemap_fd(pid, &vma->vma);
|
||||
else
|
||||
continue;
|
||||
|
||||
if (ret < 0) {
|
||||
pr_err("Can't fixup fd\n");
|
||||
return ret;
|
||||
break;
|
||||
}
|
||||
|
||||
lseek(fd, -sizeof(vi), SEEK_CUR);
|
||||
vi.fd = ret;
|
||||
ret = write_img(fd, &vi);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
vma->vma.fd = ret;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int prepare_and_sigreturn(int pid)
|
||||
{
|
||||
int fd, err;
|
||||
|
||||
fd = open_image(CR_FD_VMAS, O_RDWR, pid);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
err = fixup_vma_fds(pid, fd);
|
||||
close_safe(&fd);
|
||||
int err, nr_vmas;
|
||||
LIST_HEAD(vma_list);
|
||||
|
||||
err = read_and_open_vmas(pid, &vma_list, &nr_vmas);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return sigreturn_restore(pid);
|
||||
return sigreturn_restore(pid, &vma_list, nr_vmas);
|
||||
}
|
||||
|
||||
#define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | O_DIRECT | O_NOATIME)
|
||||
@@ -1481,10 +1488,10 @@ static struct vma_entry *vma_list_remap(void *addr, unsigned long len, struct li
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sigreturn_restore(pid_t pid)
|
||||
static int sigreturn_restore(pid_t pid, struct list_head *tgt_vmas, int nr_vmas)
|
||||
{
|
||||
long restore_code_len, restore_task_vma_len;
|
||||
long restore_thread_vma_len, self_vmas_len;
|
||||
long restore_thread_vma_len, self_vmas_len, vmas_len;
|
||||
|
||||
void *mem = MAP_FAILED;
|
||||
void *restore_thread_exec_start;
|
||||
@@ -1500,7 +1507,6 @@ static int sigreturn_restore(pid_t pid)
|
||||
LIST_HEAD(self_vma_list);
|
||||
int fd_core = -1;
|
||||
int fd_pages = -1;
|
||||
int fd_vmas = -1;
|
||||
int i;
|
||||
|
||||
int *fd_core_threads;
|
||||
@@ -1517,6 +1523,7 @@ static int sigreturn_restore(pid_t pid)
|
||||
goto err;
|
||||
|
||||
self_vmas_len = round_up((ret + 1) * sizeof(struct vma_entry), PAGE_SIZE);
|
||||
vmas_len = round_up((nr_vmas + 1) * sizeof(struct vma_entry), PAGE_SIZE);
|
||||
|
||||
/* pr_info_vma_list(&self_vma_list); */
|
||||
|
||||
@@ -1537,12 +1544,6 @@ static int sigreturn_restore(pid_t pid)
|
||||
goto err;
|
||||
}
|
||||
|
||||
fd_vmas = open_image_ro(CR_FD_VMAS, pid);
|
||||
if (fd_vmas < 0) {
|
||||
pr_perror("Can't open vmas-%d", pid);
|
||||
goto err;
|
||||
}
|
||||
|
||||
restore_code_len = sizeof(restorer_blob);
|
||||
restore_code_len = round_up(restore_code_len, 16);
|
||||
|
||||
@@ -1643,12 +1644,16 @@ static int sigreturn_restore(pid_t pid)
|
||||
if (!task_args->self_vmas)
|
||||
goto err;
|
||||
|
||||
mem += self_vmas_len;
|
||||
task_args->tgt_vmas = vma_list_remap(mem, vmas_len, tgt_vmas);
|
||||
if (!task_args->tgt_vmas)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* Arguments for task restoration.
|
||||
*/
|
||||
task_args->pid = pid;
|
||||
task_args->fd_core = fd_core;
|
||||
task_args->fd_vmas = fd_vmas;
|
||||
task_args->logfd = log_get_fd();
|
||||
task_args->sigchld_act = sigchld_act;
|
||||
task_args->fd_exe_link = self_exe_fd;
|
||||
|
@@ -65,7 +65,6 @@ struct task_restore_core_args {
|
||||
|
||||
int pid; /* task pid */
|
||||
int fd_core; /* opened core file */
|
||||
int fd_vmas; /* opened vmas file */
|
||||
int fd_exe_link; /* opened self->exe file */
|
||||
int fd_pages; /* opened pages dump file */
|
||||
int logfd;
|
||||
@@ -79,6 +78,7 @@ struct task_restore_core_args {
|
||||
struct shmems *shmems;
|
||||
struct task_entries *task_entries;
|
||||
struct vma_entry *self_vmas;
|
||||
struct vma_entry *tgt_vmas;
|
||||
rt_sigaction_t sigchld_act;
|
||||
|
||||
struct itimerval itimers[3];
|
||||
|
27
restorer.c
27
restorer.c
@@ -344,17 +344,7 @@ long restore_task(struct task_restore_core_args *args)
|
||||
/*
|
||||
* OK, lets try to map new one.
|
||||
*/
|
||||
vma_entry = next_on_heap(vma_entry, core_entry);
|
||||
while (1) {
|
||||
ret = sys_read(args->fd_vmas, vma_entry, sizeof(*vma_entry));
|
||||
if (!ret)
|
||||
break;
|
||||
if (ret != sizeof(*vma_entry)) {
|
||||
write_num_n(__LINE__);
|
||||
write_num_n(ret);
|
||||
goto core_restore_end;
|
||||
}
|
||||
|
||||
for (vma_entry = args->tgt_vmas; vma_entry->start != 0; vma_entry++) {
|
||||
if (!vma_entry_is(vma_entry, VMA_AREA_REGULAR))
|
||||
continue;
|
||||
|
||||
@@ -402,17 +392,7 @@ long restore_task(struct task_restore_core_args *args)
|
||||
* Walk though all VMAs again to drop PROT_WRITE
|
||||
* if it was not there.
|
||||
*/
|
||||
sys_lseek(args->fd_vmas, MAGIC_OFFSET, SEEK_SET);
|
||||
while (1) {
|
||||
ret = sys_read(args->fd_vmas, vma_entry, sizeof(*vma_entry));
|
||||
if (!ret)
|
||||
break;
|
||||
if (ret != sizeof(*vma_entry)) {
|
||||
write_num_n(__LINE__);
|
||||
write_num_n(ret);
|
||||
goto core_restore_end;
|
||||
}
|
||||
|
||||
for (vma_entry = args->tgt_vmas; vma_entry->start != 0; vma_entry++) {
|
||||
if (!(vma_entry_is(vma_entry, VMA_AREA_REGULAR)))
|
||||
continue;
|
||||
|
||||
@@ -434,7 +414,8 @@ long restore_task(struct task_restore_core_args *args)
|
||||
vma_entry->prot);
|
||||
}
|
||||
|
||||
sys_close(args->fd_vmas);
|
||||
sys_munmap(args->tgt_vmas,
|
||||
((void *)(vma_entry + 1) - ((void *)args->tgt_vmas)));
|
||||
sys_close(args->fd_core);
|
||||
|
||||
ret = sys_munmap(args->shmems, SHMEMS_SIZE);
|
||||
|
Reference in New Issue
Block a user