Re: [RESEND PATCH v3 2/2] userfaultfd: selftest: Add tests for UFFD_FEATURE_SIGBUS feature
On Mon, Jul 31, 2017 at 09:54:06PM -0400, Prakash Sangappa wrote: > This patch adds tests for UFFD_FEATURE_SIGBUS feature. The > tests will verify signal delivery instead of userfault events. > Also, test use of UFFDIO_COPY to allocate memory and retry > accessing monitored area after signal delivery. > > This patch also fixes a bug in uffd_poll_thread() where 'uffd' > is leaked. > > Signed-off-by: Prakash Sangappa> --- Reviewed-by: Mike Rapoport > Change log > > v3: Eliminated use of sig_repeat variable and simplified error return. > > v2: > - Added comments to explain the tests. > - Fixed test to fail immediately if signal repeats. > - Addressed other review comments. > > v1: https://lkml.org/lkml/2017/7/26/101 > --- > tools/testing/selftests/vm/userfaultfd.c | 127 > +- > 1 files changed, 124 insertions(+), 3 deletions(-) > > diff --git a/tools/testing/selftests/vm/userfaultfd.c > b/tools/testing/selftests/vm/userfaultfd.c > index 1eae79a..52740ae 100644 > --- a/tools/testing/selftests/vm/userfaultfd.c > +++ b/tools/testing/selftests/vm/userfaultfd.c > @@ -66,6 +66,7 @@ > #include > #include > #include > +#include > > #ifdef __NR_userfaultfd > > @@ -408,6 +409,7 @@ static int copy_page(int ufd, unsigned long offset) > userfaults++; > break; > case UFFD_EVENT_FORK: > + close(uffd); > uffd = msg.arg.fork.ufd; > pollfd[0].fd = uffd; > break; > @@ -572,6 +574,17 @@ static int userfaultfd_open(int features) > return 0; > } > > +sigjmp_buf jbuf, *sigbuf; > + > +static void sighndl(int sig, siginfo_t *siginfo, void *ptr) > +{ > + if (sig == SIGBUS) { > + if (sigbuf) > + siglongjmp(*sigbuf, 1); > + abort(); > + } > +} > + > /* > * For non-cooperative userfaultfd test we fork() a process that will > * generate pagefaults, will mremap the area monitored by the > @@ -585,19 +598,59 @@ static int userfaultfd_open(int features) > * The release of the pages currently generates event for shmem and > * anonymous memory (UFFD_EVENT_REMOVE), hence it is not checked > * for hugetlb. > + * For signal test(UFFD_FEATURE_SIGBUS), signal_test = 1, we register > + * monitored area, generate pagefaults and test that signal is delivered. > + * Use UFFDIO_COPY to allocate missing page and retry. For signal_test = 2 > + * test robustness use case - we release monitored area, fork a process > + * that will generate pagefaults and verify signal is generated. > + * This also tests UFFD_FEATURE_EVENT_FORK event along with the signal > + * feature. Using monitor thread, verify no userfault events are generated. > */ > -static int faulting_process(void) > +static int faulting_process(int signal_test) > { > unsigned long nr; > unsigned long long count; > unsigned long split_nr_pages; > + unsigned long lastnr; > + struct sigaction act; > + unsigned long signalled = 0; > > if (test_type != TEST_HUGETLB) > split_nr_pages = (nr_pages + 1) / 2; > else > split_nr_pages = nr_pages; > > + if (signal_test) { > + sigbuf = > + memset(, 0, sizeof(act)); > + act.sa_sigaction = sighndl; > + act.sa_flags = SA_SIGINFO; > + if (sigaction(SIGBUS, , 0)) { > + perror("sigaction"); > + return 1; > + } > + lastnr = (unsigned long)-1; > + } > + > for (nr = 0; nr < split_nr_pages; nr++) { > + if (signal_test) { > + if (sigsetjmp(*sigbuf, 1) != 0) { > + if (nr == lastnr) { > + fprintf(stderr, "Signal repeated\n"); > + return 1; > + } > + > + lastnr = nr; > + if (signal_test == 1) { > + if (copy_page(uffd, nr * page_size)) > + signalled++; > + } else { > + signalled++; > + continue; > + } > + } > + } > + > count = *area_count(area_dst, nr); > if (count != count_verify[nr]) { > fprintf(stderr, > @@ -607,6 +660,9 @@ static int faulting_process(void) > } > } > > + if (signal_test) > + return signalled != split_nr_pages; > + > if (test_type == TEST_HUGETLB) > return 0; > > @@ -761,7 +817,7 @@ static int userfaultfd_events_test(void) > perror("fork"), exit(1);
Re: [RESEND PATCH v3 2/2] userfaultfd: selftest: Add tests for UFFD_FEATURE_SIGBUS feature
On Mon, Jul 31, 2017 at 09:54:06PM -0400, Prakash Sangappa wrote: > This patch adds tests for UFFD_FEATURE_SIGBUS feature. The > tests will verify signal delivery instead of userfault events. > Also, test use of UFFDIO_COPY to allocate memory and retry > accessing monitored area after signal delivery. > > This patch also fixes a bug in uffd_poll_thread() where 'uffd' > is leaked. > > Signed-off-by: Prakash Sangappa > --- Reviewed-by: Mike Rapoport > Change log > > v3: Eliminated use of sig_repeat variable and simplified error return. > > v2: > - Added comments to explain the tests. > - Fixed test to fail immediately if signal repeats. > - Addressed other review comments. > > v1: https://lkml.org/lkml/2017/7/26/101 > --- > tools/testing/selftests/vm/userfaultfd.c | 127 > +- > 1 files changed, 124 insertions(+), 3 deletions(-) > > diff --git a/tools/testing/selftests/vm/userfaultfd.c > b/tools/testing/selftests/vm/userfaultfd.c > index 1eae79a..52740ae 100644 > --- a/tools/testing/selftests/vm/userfaultfd.c > +++ b/tools/testing/selftests/vm/userfaultfd.c > @@ -66,6 +66,7 @@ > #include > #include > #include > +#include > > #ifdef __NR_userfaultfd > > @@ -408,6 +409,7 @@ static int copy_page(int ufd, unsigned long offset) > userfaults++; > break; > case UFFD_EVENT_FORK: > + close(uffd); > uffd = msg.arg.fork.ufd; > pollfd[0].fd = uffd; > break; > @@ -572,6 +574,17 @@ static int userfaultfd_open(int features) > return 0; > } > > +sigjmp_buf jbuf, *sigbuf; > + > +static void sighndl(int sig, siginfo_t *siginfo, void *ptr) > +{ > + if (sig == SIGBUS) { > + if (sigbuf) > + siglongjmp(*sigbuf, 1); > + abort(); > + } > +} > + > /* > * For non-cooperative userfaultfd test we fork() a process that will > * generate pagefaults, will mremap the area monitored by the > @@ -585,19 +598,59 @@ static int userfaultfd_open(int features) > * The release of the pages currently generates event for shmem and > * anonymous memory (UFFD_EVENT_REMOVE), hence it is not checked > * for hugetlb. > + * For signal test(UFFD_FEATURE_SIGBUS), signal_test = 1, we register > + * monitored area, generate pagefaults and test that signal is delivered. > + * Use UFFDIO_COPY to allocate missing page and retry. For signal_test = 2 > + * test robustness use case - we release monitored area, fork a process > + * that will generate pagefaults and verify signal is generated. > + * This also tests UFFD_FEATURE_EVENT_FORK event along with the signal > + * feature. Using monitor thread, verify no userfault events are generated. > */ > -static int faulting_process(void) > +static int faulting_process(int signal_test) > { > unsigned long nr; > unsigned long long count; > unsigned long split_nr_pages; > + unsigned long lastnr; > + struct sigaction act; > + unsigned long signalled = 0; > > if (test_type != TEST_HUGETLB) > split_nr_pages = (nr_pages + 1) / 2; > else > split_nr_pages = nr_pages; > > + if (signal_test) { > + sigbuf = > + memset(, 0, sizeof(act)); > + act.sa_sigaction = sighndl; > + act.sa_flags = SA_SIGINFO; > + if (sigaction(SIGBUS, , 0)) { > + perror("sigaction"); > + return 1; > + } > + lastnr = (unsigned long)-1; > + } > + > for (nr = 0; nr < split_nr_pages; nr++) { > + if (signal_test) { > + if (sigsetjmp(*sigbuf, 1) != 0) { > + if (nr == lastnr) { > + fprintf(stderr, "Signal repeated\n"); > + return 1; > + } > + > + lastnr = nr; > + if (signal_test == 1) { > + if (copy_page(uffd, nr * page_size)) > + signalled++; > + } else { > + signalled++; > + continue; > + } > + } > + } > + > count = *area_count(area_dst, nr); > if (count != count_verify[nr]) { > fprintf(stderr, > @@ -607,6 +660,9 @@ static int faulting_process(void) > } > } > > + if (signal_test) > + return signalled != split_nr_pages; > + > if (test_type == TEST_HUGETLB) > return 0; > > @@ -761,7 +817,7 @@ static int userfaultfd_events_test(void) > perror("fork"), exit(1); > > if (!pid) > - return
[RESEND PATCH v3 2/2] userfaultfd: selftest: Add tests for UFFD_FEATURE_SIGBUS feature
This patch adds tests for UFFD_FEATURE_SIGBUS feature. The tests will verify signal delivery instead of userfault events. Also, test use of UFFDIO_COPY to allocate memory and retry accessing monitored area after signal delivery. This patch also fixes a bug in uffd_poll_thread() where 'uffd' is leaked. Signed-off-by: Prakash Sangappa--- Change log v3: Eliminated use of sig_repeat variable and simplified error return. v2: - Added comments to explain the tests. - Fixed test to fail immediately if signal repeats. - Addressed other review comments. v1: https://lkml.org/lkml/2017/7/26/101 --- tools/testing/selftests/vm/userfaultfd.c | 127 +- 1 files changed, 124 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/vm/userfaultfd.c b/tools/testing/selftests/vm/userfaultfd.c index 1eae79a..52740ae 100644 --- a/tools/testing/selftests/vm/userfaultfd.c +++ b/tools/testing/selftests/vm/userfaultfd.c @@ -66,6 +66,7 @@ #include #include #include +#include #ifdef __NR_userfaultfd @@ -408,6 +409,7 @@ static int copy_page(int ufd, unsigned long offset) userfaults++; break; case UFFD_EVENT_FORK: + close(uffd); uffd = msg.arg.fork.ufd; pollfd[0].fd = uffd; break; @@ -572,6 +574,17 @@ static int userfaultfd_open(int features) return 0; } +sigjmp_buf jbuf, *sigbuf; + +static void sighndl(int sig, siginfo_t *siginfo, void *ptr) +{ + if (sig == SIGBUS) { + if (sigbuf) + siglongjmp(*sigbuf, 1); + abort(); + } +} + /* * For non-cooperative userfaultfd test we fork() a process that will * generate pagefaults, will mremap the area monitored by the @@ -585,19 +598,59 @@ static int userfaultfd_open(int features) * The release of the pages currently generates event for shmem and * anonymous memory (UFFD_EVENT_REMOVE), hence it is not checked * for hugetlb. + * For signal test(UFFD_FEATURE_SIGBUS), signal_test = 1, we register + * monitored area, generate pagefaults and test that signal is delivered. + * Use UFFDIO_COPY to allocate missing page and retry. For signal_test = 2 + * test robustness use case - we release monitored area, fork a process + * that will generate pagefaults and verify signal is generated. + * This also tests UFFD_FEATURE_EVENT_FORK event along with the signal + * feature. Using monitor thread, verify no userfault events are generated. */ -static int faulting_process(void) +static int faulting_process(int signal_test) { unsigned long nr; unsigned long long count; unsigned long split_nr_pages; + unsigned long lastnr; + struct sigaction act; + unsigned long signalled = 0; if (test_type != TEST_HUGETLB) split_nr_pages = (nr_pages + 1) / 2; else split_nr_pages = nr_pages; + if (signal_test) { + sigbuf = + memset(, 0, sizeof(act)); + act.sa_sigaction = sighndl; + act.sa_flags = SA_SIGINFO; + if (sigaction(SIGBUS, , 0)) { + perror("sigaction"); + return 1; + } + lastnr = (unsigned long)-1; + } + for (nr = 0; nr < split_nr_pages; nr++) { + if (signal_test) { + if (sigsetjmp(*sigbuf, 1) != 0) { + if (nr == lastnr) { + fprintf(stderr, "Signal repeated\n"); + return 1; + } + + lastnr = nr; + if (signal_test == 1) { + if (copy_page(uffd, nr * page_size)) + signalled++; + } else { + signalled++; + continue; + } + } + } + count = *area_count(area_dst, nr); if (count != count_verify[nr]) { fprintf(stderr, @@ -607,6 +660,9 @@ static int faulting_process(void) } } + if (signal_test) + return signalled != split_nr_pages; + if (test_type == TEST_HUGETLB) return 0; @@ -761,7 +817,7 @@ static int userfaultfd_events_test(void) perror("fork"), exit(1); if (!pid) - return faulting_process(); + return faulting_process(0); waitpid(pid, , 0); if (err) @@ -778,6 +834,70 @@ static int userfaultfd_events_test(void) return userfaults != nr_pages; } +static
[RESEND PATCH v3 2/2] userfaultfd: selftest: Add tests for UFFD_FEATURE_SIGBUS feature
This patch adds tests for UFFD_FEATURE_SIGBUS feature. The tests will verify signal delivery instead of userfault events. Also, test use of UFFDIO_COPY to allocate memory and retry accessing monitored area after signal delivery. This patch also fixes a bug in uffd_poll_thread() where 'uffd' is leaked. Signed-off-by: Prakash Sangappa --- Change log v3: Eliminated use of sig_repeat variable and simplified error return. v2: - Added comments to explain the tests. - Fixed test to fail immediately if signal repeats. - Addressed other review comments. v1: https://lkml.org/lkml/2017/7/26/101 --- tools/testing/selftests/vm/userfaultfd.c | 127 +- 1 files changed, 124 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/vm/userfaultfd.c b/tools/testing/selftests/vm/userfaultfd.c index 1eae79a..52740ae 100644 --- a/tools/testing/selftests/vm/userfaultfd.c +++ b/tools/testing/selftests/vm/userfaultfd.c @@ -66,6 +66,7 @@ #include #include #include +#include #ifdef __NR_userfaultfd @@ -408,6 +409,7 @@ static int copy_page(int ufd, unsigned long offset) userfaults++; break; case UFFD_EVENT_FORK: + close(uffd); uffd = msg.arg.fork.ufd; pollfd[0].fd = uffd; break; @@ -572,6 +574,17 @@ static int userfaultfd_open(int features) return 0; } +sigjmp_buf jbuf, *sigbuf; + +static void sighndl(int sig, siginfo_t *siginfo, void *ptr) +{ + if (sig == SIGBUS) { + if (sigbuf) + siglongjmp(*sigbuf, 1); + abort(); + } +} + /* * For non-cooperative userfaultfd test we fork() a process that will * generate pagefaults, will mremap the area monitored by the @@ -585,19 +598,59 @@ static int userfaultfd_open(int features) * The release of the pages currently generates event for shmem and * anonymous memory (UFFD_EVENT_REMOVE), hence it is not checked * for hugetlb. + * For signal test(UFFD_FEATURE_SIGBUS), signal_test = 1, we register + * monitored area, generate pagefaults and test that signal is delivered. + * Use UFFDIO_COPY to allocate missing page and retry. For signal_test = 2 + * test robustness use case - we release monitored area, fork a process + * that will generate pagefaults and verify signal is generated. + * This also tests UFFD_FEATURE_EVENT_FORK event along with the signal + * feature. Using monitor thread, verify no userfault events are generated. */ -static int faulting_process(void) +static int faulting_process(int signal_test) { unsigned long nr; unsigned long long count; unsigned long split_nr_pages; + unsigned long lastnr; + struct sigaction act; + unsigned long signalled = 0; if (test_type != TEST_HUGETLB) split_nr_pages = (nr_pages + 1) / 2; else split_nr_pages = nr_pages; + if (signal_test) { + sigbuf = + memset(, 0, sizeof(act)); + act.sa_sigaction = sighndl; + act.sa_flags = SA_SIGINFO; + if (sigaction(SIGBUS, , 0)) { + perror("sigaction"); + return 1; + } + lastnr = (unsigned long)-1; + } + for (nr = 0; nr < split_nr_pages; nr++) { + if (signal_test) { + if (sigsetjmp(*sigbuf, 1) != 0) { + if (nr == lastnr) { + fprintf(stderr, "Signal repeated\n"); + return 1; + } + + lastnr = nr; + if (signal_test == 1) { + if (copy_page(uffd, nr * page_size)) + signalled++; + } else { + signalled++; + continue; + } + } + } + count = *area_count(area_dst, nr); if (count != count_verify[nr]) { fprintf(stderr, @@ -607,6 +660,9 @@ static int faulting_process(void) } } + if (signal_test) + return signalled != split_nr_pages; + if (test_type == TEST_HUGETLB) return 0; @@ -761,7 +817,7 @@ static int userfaultfd_events_test(void) perror("fork"), exit(1); if (!pid) - return faulting_process(); + return faulting_process(0); waitpid(pid, , 0); if (err) @@ -778,6 +834,70 @@ static int userfaultfd_events_test(void) return userfaults != nr_pages; } +static int