All Virtuozzo development lists (kernel + QEMU)
 help / color / mirror / Atom feed
From: no-reply@sashiko.virtuozzo.com
To: Konstantin Khorenko <khorenko@virtuozzo.com>,
	Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
Cc: devel@openvz.org
Subject: Re: [Devel] [PATCH RFC PATCH hci-8.1 1/4] mm: support moving anonymous page tables between address spaces
Date: Fri, 9 Oct 2026 15:02:57 +0000	[thread overview]
Message-ID: <010701a12130526e-014d84a3-165c-4739-b370-0af39d2eb1b9-000000@eu-central-1.amazonses.com> (raw)
In-Reply-To: <20261009-vfio_v1-v1-1-1901cd6c3c74@virtuozzo.com>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] mm: cross-mm move forces rmap locks, serializing padata workers on one anon_vma
- [Low] mm: padata workers in move_page_range_exec() allocate page tables outside exec task memcg
--

commit 8261a13046a4e58b21e6c687a520d3921507b391
Author: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>

mm: support moving anonymous page tables between address spaces

This teaches move_page_tables() and move_huge_pmd() to use the destination
mm for page-table operations and to transfer RSS, swap-list and huge-page
table accounting. Cross-mm moves are restricted to same-address anonymous
DOEXEC VMAs. It also adds a parallel exec move wrapper,
move_page_range_exec(), built on padata.

Reference in the commit message:
https://virtuozzo.atlassian.net/browse/VSTOR-103860

> diff --git a/mm/mremap.c b/mm/mremap.c
> --- a/mm/mremap.c
> +++ b/mm/mremap.c

[ ... ]

> @@ -610,10 +646,19 @@ unsigned long move_page_tables(struct vm_area_struct *vma,
>  	struct mmu_notifier_range range;
>  	pmd_t *old_pmd, *new_pmd;
>  	pud_t *old_pud, *new_pud;
> +	bool cross_mm = vma->vm_mm != new_vma->vm_mm;
>  
>  	if (!len)
>  		return 0;
>  
> +	/* Cross-mm moves are only used for same-address anonymous DOEXEC VMAs. */
> +	if (cross_mm) {
> +		if (WARN_ON_ONCE(!vma_is_anonymous(vma) ||
> +				 !(vma->vm_flags & VM_EXEC_KEEP) ||
> +				 old_addr != new_addr || !need_rmap_locks))
> +			return 0;
> +	}

[Severity: Medium]
Does requiring need_rmap_locks for every cross-mm move serialize the padata
workers added below?

move_page_range_chunk() passes need_rmap_locks=true for every chunk:

    return move_page_tables(args->old_vma, addr, args->new_vma, addr,
                            len, true, false) == len ? 0 : -ENOMEM;

For each PMD-sized extent, move_ptes() and move_pgt_entry() then call
take_rmap_locks(vma), which does:

    if (vma->anon_vma)
            anon_vma_lock_write(vma->anon_vma);

All workers operate on the same old VMA, so they all contend on the same
anon_vma write lock, and the PTE-moving loop runs inside that critical
section. Only page-table allocation and cond_resched() can overlap.

Since passing false is rejected by the WARN_ON_ONCE() above, the parallel
path cannot avoid the lock. Does that largely cancel the speedup that
move_page_range_exec() is meant to provide with up to 16 threads?

The commit message does not say why rmap locks are required for cross-mm
moves, or that the workers end up serialized on this lock. Could that be
documented, or could the requirement be relaxed for this case?

[ ... ]

> +static int move_page_range_chunk(unsigned long addr, unsigned long end, void *arg)
> +{
> +	struct move_page_range_args *args = arg;
> +	unsigned long len = end - addr;
> +
> +	return move_page_tables(args->old_vma, addr, args->new_vma, addr,
> +				len, true, false) == len ? 0 : -ENOMEM;
> +}

[ ... ]

> +int move_page_range_exec(struct vm_area_struct *new_vma,
> +			 struct vm_area_struct *old_vma)
> +{

[ ... ]

> +#ifdef CONFIG_PADATA
> +	return padata_do_multithreaded(&job);
> +#else
> +	return move_page_range_chunk(old_vma->vm_start, old_vma->vm_end, &args);
> +#endif
> +}

[Severity: Low]
Are the destination page tables allocated by the padata helpers charged to
the right memcg?

When the job spans more than one chunk, padata_do_multithreaded() queues the
helpers on system_unbound_wq. Each helper then runs:

    padata_mt_helper()
      move_page_range_chunk()
        move_page_tables()
          alloc_new_pud(new_vma->vm_mm, ...)
          alloc_new_pmd(new_vma->vm_mm, ...)
          pte_alloc(new_vma->vm_mm, new_pmd)

These use GFP_PGTABLE_USER, which includes __GFP_ACCOUNT. The charge is
resolved from active_memcg() or current, and here that is the kworker rather
than the exec'ing task.

Neither padata nor this patch calls set_active_memcg() or otherwise attaches
the workers to the submitter's cgroup. Can part of the exec'ing task's
page-table memory therefore escape its memcg limit?

copy_page_range_mt() in mm/memory.c appears to have the same behavior, but
this adds a new padata consumer that relies on it. Should the workers run
under the submitter's memcg, for example by wrapping the chunk function with
set_active_memcg()?

-- 
Sashiko AI review · https://sashiko.vzint.dev/#/patchset/20261009-vfio_v1-v1-0-1901cd6c3c74@virtuozzo.com?part=1

_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

  reply	other threads:[~2026-10-09 15:04 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-09 14:00 [Devel] [PATCH RFC hci-8.1 0/4] mm: keep DMA-pinned MADV_DOEXEC memory working across exec Andrey Drobyshev
2026-10-09 14:00 ` [Devel] [PATCH RFC PATCH hci-8.1 1/4] mm: support moving anonymous page tables between address spaces Andrey Drobyshev
2026-10-09 15:02   ` no-reply [this message]
2026-10-09 14:00 ` [Devel] [PATCH RFC PATCH hci-8.1 2/4] exec: protect preserved memory against surviving shared-mm tasks Andrey Drobyshev
2026-10-09 14:57   ` no-reply
2026-10-09 14:00 ` [Devel] [PATCH RFC PATCH hci-8.1 3/4] mm: move MADV_DOEXEC memory instead of copying it Andrey Drobyshev
2026-10-09 15:08   ` no-reply
2026-10-09 14:00 ` [Devel] [PATCH RFC PATCH hci-8.1 4/4] selftests/mm: test memory preservation across exec Andrey Drobyshev
2026-10-09 15:07   ` no-reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=010701a12130526e-014d84a3-165c-4739-b370-0af39d2eb1b9-000000@eu-central-1.amazonses.com \
    --to=no-reply@sashiko.virtuozzo.com \
    --cc=andrey.drobyshev@virtuozzo.com \
    --cc=devel@openvz.org \
    --cc=khorenko@virtuozzo.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.