99 * from a different thread.
1010 */
1111
12- #include "config.h"
1312#include <poll.h>
1413#include "tst_test.h"
1514#include "tst_safe_macros.h"
1615#include "tst_safe_pthread.h"
1716#include "lapi/userfaultfd.h"
1817
18+ #define BEFORE_5_11 1
19+ #define AFTER_5_11 2
20+ #define DESC (x ) .flags = x, .desc = #x
21+
22+ static struct tcase {
23+ int flags ;
24+ const char * desc ;
25+ int kver ;
26+ } tcases [] = {
27+ { DESC (O_CLOEXEC | O_NONBLOCK ) },
28+ { DESC (O_CLOEXEC | O_NONBLOCK | UFFD_USER_MODE_ONLY ), .kver = AFTER_5_11 , },
29+ };
30+
1931static int page_size ;
2032static char * page ;
2133static void * copy_page ;
2234static int uffd ;
35+ static int kver ;
36+
37+ static void setup (void )
38+ {
39+ if (tst_kvercmp (5 , 11 , 0 ) >= 0 )
40+ kver = AFTER_5_11 ;
41+ else
42+ kver = BEFORE_5_11 ;
43+ }
2344
2445static void set_pages (void )
2546{
@@ -30,10 +51,16 @@ static void set_pages(void)
3051 MAP_PRIVATE | MAP_ANONYMOUS , -1 , 0 );
3152}
3253
33- static void handle_thread (void )
54+ static void reset_pages (void )
55+ {
56+ SAFE_MUNMAP (page , page_size );
57+ SAFE_MUNMAP (copy_page , page_size );
58+ }
59+
60+ static void * handle_thread (void )
3461{
3562 static struct uffd_msg msg ;
36- struct uffdio_copy uffdio_copy ;
63+ struct uffdio_copy uffdio_copy = {} ;
3764
3865 struct pollfd pollfd ;
3966 int nready ;
@@ -47,7 +74,7 @@ static void handle_thread(void)
4774 SAFE_READ (1 , uffd , & msg , sizeof (msg ));
4875
4976 if (msg .event != UFFD_EVENT_PAGEFAULT )
50- tst_brk (TBROK | TERRNO , "Received unexpected UFFD_EVENT" );
77+ tst_brk (TBROK | TERRNO , "Received unexpected UFFD_EVENT %d" , msg . event );
5178
5279 memset (copy_page , 'X' , page_size );
5380
@@ -56,25 +83,27 @@ static void handle_thread(void)
5683 uffdio_copy .dst = (unsigned long ) msg .arg .pagefault .address
5784 & ~(page_size - 1 );
5885 uffdio_copy .len = page_size ;
59- uffdio_copy .mode = 0 ;
60- uffdio_copy .copy = 0 ;
6186 SAFE_IOCTL (uffd , UFFDIO_COPY , & uffdio_copy );
6287
6388 close (uffd );
89+ return NULL ;
6490}
6591
66- static void run (void )
92+ static void run (unsigned int i )
6793{
6894 pthread_t thr ;
69- struct uffdio_api uffdio_api ;
95+ struct uffdio_api uffdio_api = {} ;
7096 struct uffdio_register uffdio_register ;
97+ struct tcase * tc = & tcases [i ];
98+
99+ if (tc -> kver == AFTER_5_11 && kver == BEFORE_5_11 )
100+ tst_brk (TCONF , "%s requires kernel >= 5.11" , tc -> desc );
71101
72102 set_pages ();
73103
74- uffd = SAFE_USERFAULTFD (O_CLOEXEC | O_NONBLOCK , false);
104+ uffd = SAFE_USERFAULTFD (tc -> flags , false);
75105
76106 uffdio_api .api = UFFD_API ;
77- uffdio_api .features = 0 ;
78107 SAFE_IOCTL (uffd , UFFDIO_API , & uffdio_api );
79108
80109 uffdio_register .range .start = (unsigned long ) page ;
@@ -83,8 +112,7 @@ static void run(void)
83112
84113 SAFE_IOCTL (uffd , UFFDIO_REGISTER , & uffdio_register );
85114
86- SAFE_PTHREAD_CREATE (& thr , NULL ,
87- (void * (* )(void * )) handle_thread , NULL );
115+ SAFE_PTHREAD_CREATE (& thr , NULL , (void * ) handle_thread , NULL );
88116
89117 char c = page [0xf ];
90118
@@ -94,9 +122,11 @@ static void run(void)
94122 tst_res (TFAIL , "Pagefault not handled!" );
95123
96124 SAFE_PTHREAD_JOIN (thr , NULL );
125+ reset_pages ();
97126}
98127
99128static struct tst_test test = {
100- .test_all = run ,
101- .min_kver = "4.3" ,
129+ .setup = setup ,
130+ .test = run ,
131+ .tcnt = ARRAY_SIZE (tcases ),
102132};
0 commit comments