From 2b175282fb831facb230634a1d885d581f01657e Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Tue, 27 Mar 2012 16:34:00 +0400 Subject: [PATCH] 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 --- cr-restore.c | 87 ++++++++++++++++++++++++---------------------- include/restorer.h | 2 +- restorer.c | 27 +++----------- 3 files changed, 51 insertions(+), 65 deletions(-) diff --git a/cr-restore.c b/cr-restore.c index 3a0a26742..cf32cdb8c 100644 --- a/cr-restore.c +++ b/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; diff --git a/include/restorer.h b/include/restorer.h index 14c7dd047..d38cd3126 100644 --- a/include/restorer.h +++ b/include/restorer.h @@ -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]; diff --git a/restorer.c b/restorer.c index 6cc9b6026..18e5b6cd3 100644 --- a/restorer.c +++ b/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);