On Sat, Dec 2, 2023 at 2:11 AM David Hildenbrand <david@xxxxxxxxxx> wrote: > > On 02.12.23 09:04, Ryan Roberts wrote: > > On 01/12/2023 20:47, David Hildenbrand wrote: > >> On 01.12.23 10:29, Ryan Roberts wrote: > >>> On 21/11/2023 17:16, Suren Baghdasaryan wrote: > >>>> Add tests for new UFFDIO_MOVE ioctl which uses uffd to move source > >>>> into destination buffer while checking the contents of both after > >>>> the move. After the operation the content of the destination buffer > >>>> should match the original source buffer's content while the source > >>>> buffer should be zeroed. Separate tests are designed for PMD aligned and > >>>> unaligned cases because they utilize different code paths in the kernel. > >>>> > >>>> Signed-off-by: Suren Baghdasaryan <surenb@xxxxxxxxxx> > >>>> --- > >>>> tools/testing/selftests/mm/uffd-common.c | 24 +++ > >>>> tools/testing/selftests/mm/uffd-common.h | 1 + > >>>> tools/testing/selftests/mm/uffd-unit-tests.c | 189 +++++++++++++++++++ > >>>> 3 files changed, 214 insertions(+) > >>>> > >>>> diff --git a/tools/testing/selftests/mm/uffd-common.c > >>>> b/tools/testing/selftests/mm/uffd-common.c > >>>> index fb3bbc77fd00..b0ac0ec2356d 100644 > >>>> --- a/tools/testing/selftests/mm/uffd-common.c > >>>> +++ b/tools/testing/selftests/mm/uffd-common.c > >>>> @@ -631,6 +631,30 @@ int copy_page(int ufd, unsigned long offset, bool wp) > >>>> return __copy_page(ufd, offset, false, wp); > >>>> } > >>>> +int move_page(int ufd, unsigned long offset, unsigned long len) > >>>> +{ > >>>> + struct uffdio_move uffdio_move; > >>>> + > >>>> + if (offset + len > nr_pages * page_size) > >>>> + err("unexpected offset %lu and length %lu\n", offset, len); > >>>> + uffdio_move.dst = (unsigned long) area_dst + offset; > >>>> + uffdio_move.src = (unsigned long) area_src + offset; > >>>> + uffdio_move.len = len; > >>>> + uffdio_move.mode = UFFDIO_MOVE_MODE_ALLOW_SRC_HOLES; > >>>> + uffdio_move.move = 0; > >>>> + if (ioctl(ufd, UFFDIO_MOVE, &uffdio_move)) { > >>>> + /* real retval in uffdio_move.move */ > >>>> + if (uffdio_move.move != -EEXIST) > >>>> + err("UFFDIO_MOVE error: %"PRId64, > >>>> + (int64_t)uffdio_move.move); > >>> > >>> Hi Suren, > >>> > >>> FYI this error is triggering in mm-unstable (715b67adf4c8): > >>> > >>> Testing move-pmd on anon... ERROR: UFFDIO_MOVE error: -16 (errno=16, > >>> @uffd-common.c:648) > >>> > >>> I'm running in a VM on Apple M2 (arm64). I haven't debugged any further, but > >>> happy to go deeper if you can direct. > >> > >> Does it trigger reliably? Which pagesize is that kernel using? > > > > Yep, although very occasionally it fails with EAGAIN. 4K kernel; see other email > > for full config. > > > >> > >> I can spot that uffd_move_pmd_test()/uffd_move_pmd_handle_fault() uses > >> default_huge_page_size(), which reads the default hugetlb size. > > > > My kernel command line is explicitly seting the default huge page size to 2M. > > > > Okay, so that likely won't affect it. > > I can only guess that it has to do with the alignment of the virtual > area we are testing with, and that we do seem to get more odd patterns > on arm64. > > uffd_move_test_common() is a bit more elaborate, but if we aligned the > src+start area up, surely "step_count" cannot be left unmodified? > > So assuming we get either an unaligned source or an unaligned dst from > mmap(), I am not convinced that we won't be moving areas that are not > necessarily fully backed by PMDs and maybe don't even fall into the VMA > of interest? > > Not sure if that could trigger the THP splitting issue, though. > > But I just quickly scanned that test setup, could be I am missing > something. It might make sense to just print the mmap'ed range and the > actual ranges we are trying to move. Maybe something "obvious" can be > observed. I was able to reproduce the issue on an Android device and after implementing David's suggestions to split the large folio and after replacing default_huge_page_size() with read_pmd_pagesize(), the move-pmd test started working for me. Ryan, could you please apply attached patches (over mm-unstable) and try the test again? Thanks, Suren. > > -- > Cheers, > > David / dhildenb >
From cbd4348484986193c45235babbae6e30318d9e48 Mon Sep 17 00:00:00 2001 From: Suren Baghdasaryan <surenb@xxxxxxxxxx> Date: Sun, 3 Dec 2023 19:53:45 -0800 Subject: [PATCH 1/2] userfaultfd: split large pmd-mapped folio Signed-off-by: Suren Baghdasaryan <surenb@xxxxxxxxxx> --- mm/userfaultfd.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c index 71d0281f1162..6e6f672067fe 100644 --- a/mm/userfaultfd.c +++ b/mm/userfaultfd.c @@ -1382,8 +1382,25 @@ ssize_t move_pages(struct userfaultfd_ctx *ctx, struct mm_struct *mm, /* Check if we can move the pmd without splitting it. */ if (move_splits_huge_pmd(dst_addr, src_addr, src_start + len) || !pmd_none(dst_pmdval)) { + struct folio *folio = pfn_folio(pmd_pfn(*src_pmd)); + if (!folio || !PageAnonExclusive(&folio->page)) { + spin_unlock(ptl); + err = -EBUSY; + break; + } + folio_get(folio); spin_unlock(ptl); split_huge_pmd(src_vma, src_pmd, src_addr); + if (folio_test_large(folio)) { + folio_lock(folio); + err = split_folio(folio); + folio_unlock(folio); + if (err) { + folio_put(folio); + break; + } + } + folio_put(folio); continue; } -- 2.43.0.rc2.451.g8631bc7472-goog
From ab3e137ce9ebf3a949e14b9f544a8a2144934f86 Mon Sep 17 00:00:00 2001 From: Suren Baghdasaryan <surenb@xxxxxxxxxx> Date: Sun, 3 Dec 2023 20:04:08 -0800 Subject: [PATCH 2/2] selftests/mm: use correct function to obtain huge page size Signed-off-by: Suren Baghdasaryan <surenb@xxxxxxxxxx> --- tools/testing/selftests/mm/uffd-unit-tests.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/mm/uffd-unit-tests.c b/tools/testing/selftests/mm/uffd-unit-tests.c index e4e271511db9..07c8dc490993 100644 --- a/tools/testing/selftests/mm/uffd-unit-tests.c +++ b/tools/testing/selftests/mm/uffd-unit-tests.c @@ -1096,7 +1096,7 @@ static void uffd_move_handle_fault(struct uffd_msg *msg, static void uffd_move_pmd_handle_fault(struct uffd_msg *msg, struct uffd_args *args) { - uffd_move_handle_fault_common(msg, args, default_huge_page_size()); + uffd_move_handle_fault_common(msg, args, read_pmd_pagesize()); } static void @@ -1199,7 +1199,7 @@ static void uffd_move_test(uffd_test_args_t *targs) static void uffd_move_pmd_test(uffd_test_args_t *targs) { - uffd_move_test_common(targs, default_huge_page_size(), + uffd_move_test_common(targs, read_pmd_pagesize(), uffd_move_pmd_handle_fault); } -- 2.43.0.rc2.451.g8631bc7472-goog