[CRIU] [PATCH 8/9] vdso: Escape double dumping of rt-vdso if proxy present
Pavel Emelyanov
xemul at parallels.com
Fri May 24 05:32:22 EDT 2013
On 05/24/2013 01:42 AM, Cyrill Gorcunov wrote:
>
> In case if we have created vdso proxy the rt-vdso should
> not be dumped because it will be re-created on next restore
> anyway. Thus with help of parasite service routine find
> the rt-vdso and tear it off from VMAs list.
>
> Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
> ---
> cr-dump.c | 7 +++
> include/parasite-syscall.h | 3 ++
> include/parasite.h | 8 +++
> include/vdso.h | 7 +++
> parasite-syscall.c | 121 +++++++++++++++++++++++++++++++++++++++++++++
> pie/parasite.c | 18 +++++++
> 6 files changed, 164 insertions(+)
>
> +int parasite_fixup_vdso(struct parasite_ctl *ctl, pid_t pid,
> + struct vm_area_list *vma_area_list)
> +{
> + unsigned long proxy_addr = VDSO_BAD_ADDR;
> + struct parasite_vdso_vma_entry *args;
> + struct vma_area *marked = NULL;
> + struct vma_area *vma;
> + int fd, ret = -1;
> + off_t off;
> + u64 pfn;
> +
> + args = parasite_args(ctl, struct parasite_vdso_vma_entry);
> + fd = open_proc(pid, "pagemap");
> + if (fd < 0)
> + return -1;
> +
> + list_for_each_entry(vma, &vma_area_list->h, list) {
> + if (!vma_area_is(vma, VMA_AREA_REGULAR))
> + continue;
> +
> + if ((vma->vma.prot & VDSO_PROT) != VDSO_PROT)
> + continue;
> +
> + /*
> + * I need to poke every potentially marked vma,
> + * otherwise if task never called for vdso functions
> + * page frame number won't be reported.
> + */
> + args->start = vma->vma.start;
> + args->len = vma_area_len(vma);
> +
> + if (parasite_execute(PARASITE_CMD_CHECK_VDSO_MARK, ctl)) {
I'm not very happy with going to parasite for every (even pre-checked) vma.
Make it in one go to parasite with an array of vmas.
> + pr_err("vdso: Parasite failed to poke for mark\n");
> + ret = -1;
> + goto err;
> + }
> +
> + off = (vma->vma.start / PAGE_SIZE) * sizeof(u64);
> + if (lseek(fd, off, SEEK_SET) != off) {
> + pr_perror("Failed to seek address %lx\n", vma->vma.start);
> + ret = -1;
> + goto err;
> + }
> +
> + ret = read(fd, &pfn, sizeof(pfn));
> + if (ret < 0 || ret != sizeof(pfn)) {
> + pr_perror("Can't read pme for pid %d", pid);
> + ret = -1;
> + goto err;
> + }
> +
> + pfn = PME_PFRAME(pfn);
> + BUG_ON(!pfn);
You don't need this value for args->is_marked case.
> +
> + /*
> + * Defer handling marked vdso.
> + */
> + if (unlikely(args->is_marked)) {
> + BUG_ON(args->proxy_addr == VDSO_BAD_ADDR);
> + BUG_ON(marked);
> + marked = vma;
> + proxy_addr = args->proxy_addr;
> + continue;
> + }
> +
> + /*
> + * Set proper VMA statuses.
> + */
> + if (pfn == vdso_pfn) {
> + if (!vma_area_is(vma, VMA_AREA_VDSO)) {
> + pr_debug("vdso: Restore status by pfn at %lx\n",
> + (long)vma->vma.start);
> + vma->vma.status |= VMA_AREA_VDSO;
> + }
> + } else {
> + if (vma_area_is(vma, VMA_AREA_VDSO)) {
> + pr_debug("vdso: Drop mishinted status at %lx\n",
> + (long)vma->vma.start);
> + vma->vma.status &= ~VMA_AREA_VDSO;
> + }
> + }
> + }
> +
> + /*
> + * There is marked vdso, it means such vdso is autogenerated
> + * and must be dropped from vma list.
> + */
> + if (marked) {
> + pr_debug("vdso: Found marked at %lx (proxy at %lx)\n",
> + (long)marked->vma.start, (long)proxy_addr);
> +
> + /*
> + * Don't forget to restore the proxy vdso status, since
> + * it's being not recognized by the kernel as vdso.
> + */
> + list_for_each_entry(vma, &vma_area_list->h, list) {
> + if (vma->vma.start == proxy_addr) {
> + vma->vma.status |= VMA_AREA_REGULAR | VMA_AREA_VDSO;
> + pr_debug("vdso: Restore proxy status at %lx\n",
> + (long)vma->vma.start);
> + break;
> + }
> + }
> +
> + pr_debug("vdso: Droppping marked vdso at %lx\n",
> + (long)vma->vma.start);
> + list_del(&marked->list);
> + xfree(marked);
> + }
> + ret = 0;
> +err:
> + close(fd);
> + return ret;
> +}
More information about the CRIU
mailing list