mirror of
https://github.com/checkpoint-restore/criu
synced 2025-09-04 00:05:26 +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;
|
struct pstree_item *me;
|
||||||
|
|
||||||
static int restore_task_with_children(void *);
|
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)
|
static void show_saved_shmems(void)
|
||||||
{
|
{
|
||||||
@@ -532,60 +532,67 @@ static int get_shmem_fd(int pid, struct vma_entry *vi)
|
|||||||
return f;
|
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) {
|
while (1) {
|
||||||
struct vma_entry vi;
|
struct vma_area *vma;
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
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)
|
if (ret <= 0)
|
||||||
return ret;
|
break;
|
||||||
|
|
||||||
if (!(vma_entry_is(&vi, VMA_AREA_REGULAR)))
|
if (!(vma_entry_is(&vma->vma, VMA_AREA_REGULAR)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
pr_info("%d: Fixing %016lx-%016lx %016lx vma\n",
|
pr_info("%d: Opening %016lx-%016lx %016lx vma\n",
|
||||||
pid, vi.start, vi.end, vi.pgoff);
|
pid, vma->vma.start, vma->vma.end, vma->vma.pgoff);
|
||||||
|
|
||||||
if (vma_entry_is(&vi, VMA_AREA_SYSVIPC))
|
if (vma_entry_is(&vma->vma, VMA_AREA_SYSVIPC))
|
||||||
ret = vi.shmid;
|
ret = vma->vma.shmid;
|
||||||
else if (vma_entry_is(&vi, VMA_ANON_SHARED))
|
else if (vma_entry_is(&vma->vma, VMA_ANON_SHARED))
|
||||||
ret = get_shmem_fd(pid, &vi);
|
ret = get_shmem_fd(pid, &vma->vma);
|
||||||
else if (vma_entry_is(&vi, VMA_FILE_PRIVATE) ||
|
else if (vma_entry_is(&vma->vma, VMA_FILE_PRIVATE) ||
|
||||||
vma_entry_is(&vi, VMA_FILE_SHARED))
|
vma_entry_is(&vma->vma, VMA_FILE_SHARED))
|
||||||
ret = get_filemap_fd(pid, &vi);
|
ret = get_filemap_fd(pid, &vma->vma);
|
||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
pr_err("Can't fixup fd\n");
|
pr_err("Can't fixup fd\n");
|
||||||
return ret;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
lseek(fd, -sizeof(vi), SEEK_CUR);
|
vma->vma.fd = ret;
|
||||||
vi.fd = ret;
|
|
||||||
ret = write_img(fd, &vi);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int prepare_and_sigreturn(int pid)
|
static int prepare_and_sigreturn(int pid)
|
||||||
{
|
{
|
||||||
int fd, err;
|
int err, nr_vmas;
|
||||||
|
LIST_HEAD(vma_list);
|
||||||
fd = open_image(CR_FD_VMAS, O_RDWR, pid);
|
|
||||||
if (fd < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
err = fixup_vma_fds(pid, fd);
|
|
||||||
close_safe(&fd);
|
|
||||||
|
|
||||||
|
err = read_and_open_vmas(pid, &vma_list, &nr_vmas);
|
||||||
if (err)
|
if (err)
|
||||||
return 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)
|
#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;
|
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_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 *mem = MAP_FAILED;
|
||||||
void *restore_thread_exec_start;
|
void *restore_thread_exec_start;
|
||||||
@@ -1500,7 +1507,6 @@ static int sigreturn_restore(pid_t pid)
|
|||||||
LIST_HEAD(self_vma_list);
|
LIST_HEAD(self_vma_list);
|
||||||
int fd_core = -1;
|
int fd_core = -1;
|
||||||
int fd_pages = -1;
|
int fd_pages = -1;
|
||||||
int fd_vmas = -1;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
int *fd_core_threads;
|
int *fd_core_threads;
|
||||||
@@ -1517,6 +1523,7 @@ static int sigreturn_restore(pid_t pid)
|
|||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
self_vmas_len = round_up((ret + 1) * sizeof(struct vma_entry), PAGE_SIZE);
|
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); */
|
/* pr_info_vma_list(&self_vma_list); */
|
||||||
|
|
||||||
@@ -1537,12 +1544,6 @@ static int sigreturn_restore(pid_t pid)
|
|||||||
goto err;
|
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 = sizeof(restorer_blob);
|
||||||
restore_code_len = round_up(restore_code_len, 16);
|
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)
|
if (!task_args->self_vmas)
|
||||||
goto err;
|
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.
|
* Arguments for task restoration.
|
||||||
*/
|
*/
|
||||||
task_args->pid = pid;
|
task_args->pid = pid;
|
||||||
task_args->fd_core = fd_core;
|
task_args->fd_core = fd_core;
|
||||||
task_args->fd_vmas = fd_vmas;
|
|
||||||
task_args->logfd = log_get_fd();
|
task_args->logfd = log_get_fd();
|
||||||
task_args->sigchld_act = sigchld_act;
|
task_args->sigchld_act = sigchld_act;
|
||||||
task_args->fd_exe_link = self_exe_fd;
|
task_args->fd_exe_link = self_exe_fd;
|
||||||
|
@@ -65,7 +65,6 @@ struct task_restore_core_args {
|
|||||||
|
|
||||||
int pid; /* task pid */
|
int pid; /* task pid */
|
||||||
int fd_core; /* opened core file */
|
int fd_core; /* opened core file */
|
||||||
int fd_vmas; /* opened vmas file */
|
|
||||||
int fd_exe_link; /* opened self->exe file */
|
int fd_exe_link; /* opened self->exe file */
|
||||||
int fd_pages; /* opened pages dump file */
|
int fd_pages; /* opened pages dump file */
|
||||||
int logfd;
|
int logfd;
|
||||||
@@ -79,6 +78,7 @@ struct task_restore_core_args {
|
|||||||
struct shmems *shmems;
|
struct shmems *shmems;
|
||||||
struct task_entries *task_entries;
|
struct task_entries *task_entries;
|
||||||
struct vma_entry *self_vmas;
|
struct vma_entry *self_vmas;
|
||||||
|
struct vma_entry *tgt_vmas;
|
||||||
rt_sigaction_t sigchld_act;
|
rt_sigaction_t sigchld_act;
|
||||||
|
|
||||||
struct itimerval itimers[3];
|
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.
|
* OK, lets try to map new one.
|
||||||
*/
|
*/
|
||||||
vma_entry = next_on_heap(vma_entry, core_entry);
|
for (vma_entry = args->tgt_vmas; vma_entry->start != 0; vma_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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!vma_entry_is(vma_entry, VMA_AREA_REGULAR))
|
if (!vma_entry_is(vma_entry, VMA_AREA_REGULAR))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -402,17 +392,7 @@ long restore_task(struct task_restore_core_args *args)
|
|||||||
* Walk though all VMAs again to drop PROT_WRITE
|
* Walk though all VMAs again to drop PROT_WRITE
|
||||||
* if it was not there.
|
* if it was not there.
|
||||||
*/
|
*/
|
||||||
sys_lseek(args->fd_vmas, MAGIC_OFFSET, SEEK_SET);
|
for (vma_entry = args->tgt_vmas; vma_entry->start != 0; vma_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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(vma_entry_is(vma_entry, VMA_AREA_REGULAR)))
|
if (!(vma_entry_is(vma_entry, VMA_AREA_REGULAR)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -434,7 +414,8 @@ long restore_task(struct task_restore_core_args *args)
|
|||||||
vma_entry->prot);
|
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);
|
sys_close(args->fd_core);
|
||||||
|
|
||||||
ret = sys_munmap(args->shmems, SHMEMS_SIZE);
|
ret = sys_munmap(args->shmems, SHMEMS_SIZE);
|
||||||
|
Reference in New Issue
Block a user