Commit 2b175282 authored by Pavel Emelyanov's avatar Pavel Emelyanov

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: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 65db28ea
...@@ -103,7 +103,7 @@ pid_t pstree_pid; ...@@ -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) ...@@ -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 ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 { ...@@ -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 { ...@@ -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];
......
...@@ -344,17 +344,7 @@ long restore_task(struct task_restore_core_args *args) ...@@ -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) ...@@ -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) ...@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment