Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

userfaultfd: selftest: exercise -EEXIST only in background transfer

I was stress testing some backports and with high load, after some time,
the latest version of the selftest showed some false positive in
connection with the uffdio_copy_retry. This seems to fix it while still
exercising -EEXIST in the background transfer once in a while.

The fork child will quit after the last UFFDIO_COPY is run, so a
repeated UFFDIO_COPY may not return -EEXIST. This change restricts the
-EEXIST stress to the background transfer where the memory can't go away
from under it.

Also updated uffdio_zeropage, so the interface is consistent.

Link: http://lkml.kernel.org/r/20171004171541.1495-2-aarcange@redhat.com
Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
Cc: Pavel Emelyanov <xemul@virtuozzo.com>
Cc: Mike Rapoport <rppt@linux.vnet.ibm.com>
Cc: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
Cc: Mike Kravetz <mike.kravetz@oracle.com>
Cc: Shuah Khan <shuah@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Andrea Arcangeli and committed by
Linus Torvalds
7ddd8faf 064f0e93

+20 -5
+20 -5
tools/testing/selftests/vm/userfaultfd.c
··· 397 397 } 398 398 } 399 399 400 - static int copy_page(int ufd, unsigned long offset) 400 + static int __copy_page(int ufd, unsigned long offset, bool retry) 401 401 { 402 402 struct uffdio_copy uffdio_copy; 403 403 ··· 418 418 fprintf(stderr, "UFFDIO_COPY unexpected copy %Ld\n", 419 419 uffdio_copy.copy), exit(1); 420 420 } else { 421 - if (test_uffdio_copy_eexist) { 421 + if (test_uffdio_copy_eexist && retry) { 422 422 test_uffdio_copy_eexist = false; 423 423 retry_copy_page(ufd, &uffdio_copy, offset); 424 424 } 425 425 return 1; 426 426 } 427 427 return 0; 428 + } 429 + 430 + static int copy_page_retry(int ufd, unsigned long offset) 431 + { 432 + return __copy_page(ufd, offset, true); 433 + } 434 + 435 + static int copy_page(int ufd, unsigned long offset) 436 + { 437 + return __copy_page(ufd, offset, false); 428 438 } 429 439 430 440 static void *uffd_poll_thread(void *arg) ··· 554 544 for (page_nr = cpu * nr_pages_per_cpu; 555 545 page_nr < (cpu+1) * nr_pages_per_cpu; 556 546 page_nr++) 557 - copy_page(uffd, page_nr * page_size); 547 + copy_page_retry(uffd, page_nr * page_size); 558 548 559 549 return NULL; 560 550 } ··· 789 779 } 790 780 } 791 781 792 - static int uffdio_zeropage(int ufd, unsigned long offset) 782 + static int __uffdio_zeropage(int ufd, unsigned long offset, bool retry) 793 783 { 794 784 struct uffdio_zeropage uffdio_zeropage; 795 785 int ret; ··· 824 814 fprintf(stderr, "UFFDIO_ZEROPAGE unexpected %Ld\n", 825 815 uffdio_zeropage.zeropage), exit(1); 826 816 } else { 827 - if (test_uffdio_zeropage_eexist) { 817 + if (test_uffdio_zeropage_eexist && retry) { 828 818 test_uffdio_zeropage_eexist = false; 829 819 retry_uffdio_zeropage(ufd, &uffdio_zeropage, 830 820 offset); ··· 838 828 } 839 829 840 830 return 0; 831 + } 832 + 833 + static int uffdio_zeropage(int ufd, unsigned long offset) 834 + { 835 + return __uffdio_zeropage(ufd, offset, false); 841 836 } 842 837 843 838 /* exercise UFFDIO_ZEROPAGE */