selftests/mm/uffd: don't treat UFFDIO_COPY -ENOENT as a failure
Subsystems (3)
Mike Rapoport
maintainerPATCH RESEND 1/1 selftests/mm/uffd: don't treat UFFDIO_COPY -ENOENT as a failure
From: "Mike Rapoport (Microsoft)" <[email protected]>
Non-cooperarive uffd events are inherently racy and can happen in parallel with other userfaultfd operations.
During event tests in uffd-unit-tests, the uffd monitor calls UFFDIO_UNREGISTER upon receiving UFFD_EVENT_REMOVE.
In parallel, the faulting_process() verifies that the removed memory is actually zeroed.
If a verification read wins the race with UFFDIO_UNREGISTER, it causes a missing fault that uffd monitor would receive after UFFDIO_UNREGISTER is complete. The monitor resolves the fault using UFFDIO_COPY that fails with -ENOENT which means that VMA has been changed (see commit 27d02568f529 ("userfaultfd: mcopy_atomic: return -ENOENT when no compatible VMA found")).
Treat -ENOENT returned by UFFDIO_COPY as non-fatal, the same way -EEXIST is treated for concurrent faults, and don't fail the test.
---
I've noticed transient faults of uffd-unit-tests in the CI runs [1] and found this issue with uffd-unit-tests.
The issue is longstanding and it's not related to or exposed by the recent uffd refactoring.
I didn't even look for a Fixes: commit, as this is a selftest only and I don't see a reason to backport it.
[1] https://github.com/linux-mm/linux-mm/actions
tools/testing/selftests/mm/uffd-common.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
tools/testing/selftests/mm/uffd-common.c +7 -2
@@ -639,8 +639,13 @@ int __copy_page(uffd_global_test_opts_t *gopts, unsigned long offset, bool retry uffdio_copy.mode =0 ; uffdio_copy.copy =0 ;if (ioctl (gopts->uffd,UFFDIO_COPY , &uffdio_copy)) { -/* real retval in ufdio_copy.copy */ -if (uffdio_copy.copy != -EEXIST ) +/* +* real retval in uffdio_copy.copy +* +* -EEXIST: the page was faulted in concurrently +* -ENOENT: the destination range was concurrently removed +*/ +if (uffdio_copy.copy != -EEXIST && uffdio_copy.copy != -ENOENT )err ("UFFDIO_COPY error: %" PRId64, (int64_t )uffdio_copy.copy);wake_range (gopts->uffd, uffdio_copy.dst, gopts->page_size);
base-commit: dc59e4fea9d83f03bad6bddf3fa2e52491777482
Signature · 1 line
2.53.0
Quoted 18 lines · Mike Rapoport
From: "Mike Rapoport (Microsoft)" <[email protected]>
Non-cooperarive uffd events are inherently racy and can happen in parallel with other userfaultfd operations.
During event tests in uffd-unit-tests, the uffd monitor calls
UFFDIO_UNREGISTERupon receivingUFFD_EVENT_REMOVE.In parallel, the
faulting_process()verifies that the removed memory is actually zeroed.If a verification read wins the race with
UFFDIO_UNREGISTER, it causes a missing fault that uffd monitor would receive afterUFFDIO_UNREGISTERis complete. The monitor resolves the fault usingUFFDIO_COPYthat fails with-ENOENTwhich means that VMA has been changed (see commit27d02568f529("userfaultfd:mcopy_atomic: return-ENOENTwhen no compatible VMA found")).
Quoted 5 lines
Treat
-ENOENTreturned byUFFDIO_COPYas non-fatal, the same way-EEXISTis treated for concurrent faults, and don't fail the test.Signed-off-by Mike Rapoport (Microsoft) <[email protected]>---
Signature · 3 lines
Cheers, David
Quoted 18 lines · Mike Rapoport
From: "Mike Rapoport (Microsoft)" <[email protected]>
Non-cooperarive uffd events are inherently racy and can happen in parallel with other userfaultfd operations.
During event tests in uffd-unit-tests, the uffd monitor calls
UFFDIO_UNREGISTERupon receivingUFFD_EVENT_REMOVE.In parallel, the
faulting_process()verifies that the removed memory is actually zeroed.If a verification read wins the race with
UFFDIO_UNREGISTER, it causes a missing fault that uffd monitor would receive afterUFFDIO_UNREGISTERis complete. The monitor resolves the fault usingUFFDIO_COPYthat fails with-ENOENTwhich means that VMA has been changed (see commit27d02568f529("userfaultfd:mcopy_atomic: return-ENOENTwhen no compatible VMA found")).
Quoted 4 lines
Treat
-ENOENTreturned byUFFDIO_COPYas non-fatal, the same way-EEXISTis treated for concurrent faults, and don't fail the test.Signed-off-by Mike Rapoport (Microsoft) <[email protected]>
LGTM, so:
Quoted 3 lines
---
I've noticed transient faults of uffd-unit-tests in the CI runs [1] and found this issue with uffd-unit-tests.
Nice work tracking that down!
Quoted 33 lines
The issue is longstanding and it's not related to or exposed by the recent uffd refactoring.
I didn't even look for a Fixes: commit, as this is a selftest only and I don't see a reason to backport it.
[1] https://github.com/linux-mm/linux-mm/actions
tools/testing/selftests/mm/uffd-common.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)tools/testing/selftests/mm/uffd-common.c +7
-2@@ -639,8 +639,13 @@ int __copy_page(uffd_global_test_opts_t *gopts, unsigned long offset, bool retry uffdio_copy.mode =0 ; uffdio_copy.copy =0 ;if (ioctl (gopts->uffd,UFFDIO_COPY , &uffdio_copy)) { -/* real retval in ufdio_copy.copy */ -if (uffdio_copy.copy != -EEXIST ) +/* +* real retval in uffdio_copy.copy +* +* -EEXIST: the page was faulted in concurrently +* -ENOENT: the destination range was concurrently removed +*/ +if (uffdio_copy.copy != -EEXIST && uffdio_copy.copy != -ENOENT )err ("UFFDIO_COPY error: %" PRId64, (int64_t )uffdio_copy.copy);wake_range (gopts->uffd, uffdio_copy.dst, gopts->page_size);
Quoted 4 lines
base-commit:
dc59e4fea9d83f03bad6bddf3fa2e52491777482--
2.53.0
Cheers, Lorenzo