@@ -89,7 +89,8 @@ static int shm_fd;
89
89
static int huge_fd ;
90
90
static char * huge_fd_off0 ;
91
91
static unsigned long long * count_verify ;
92
- static int uffd , uffd_flags , finished , * pipefd ;
92
+ static int uffd = -1 ;
93
+ static int uffd_flags , finished , * pipefd ;
93
94
static char * area_src , * area_src_alias , * area_dst , * area_dst_alias ;
94
95
static char * zeropage ;
95
96
pthread_attr_t attr ;
@@ -342,6 +343,111 @@ static struct uffd_test_ops hugetlb_uffd_test_ops = {
342
343
343
344
static struct uffd_test_ops * uffd_test_ops ;
344
345
346
+ static void userfaultfd_open (uint64_t * features )
347
+ {
348
+ struct uffdio_api uffdio_api ;
349
+
350
+ uffd = syscall (__NR_userfaultfd , O_CLOEXEC | O_NONBLOCK | UFFD_USER_MODE_ONLY );
351
+ if (uffd < 0 )
352
+ err ("userfaultfd syscall not available in this kernel" );
353
+ uffd_flags = fcntl (uffd , F_GETFD , NULL );
354
+
355
+ uffdio_api .api = UFFD_API ;
356
+ uffdio_api .features = * features ;
357
+ if (ioctl (uffd , UFFDIO_API , & uffdio_api ))
358
+ err ("UFFDIO_API failed.\nPlease make sure to "
359
+ "run with either root or ptrace capability." );
360
+ if (uffdio_api .api != UFFD_API )
361
+ err ("UFFDIO_API error: %" PRIu64 , (uint64_t )uffdio_api .api );
362
+
363
+ * features = uffdio_api .features ;
364
+ }
365
+
366
+ static inline void munmap_area (void * * area )
367
+ {
368
+ if (* area )
369
+ if (munmap (* area , nr_pages * page_size ))
370
+ err ("munmap" );
371
+
372
+ * area = NULL ;
373
+ }
374
+
375
+ static void uffd_test_ctx_clear (void )
376
+ {
377
+ size_t i ;
378
+
379
+ if (pipefd ) {
380
+ for (i = 0 ; i < nr_cpus * 2 ; ++ i ) {
381
+ if (close (pipefd [i ]))
382
+ err ("close pipefd" );
383
+ }
384
+ free (pipefd );
385
+ pipefd = NULL ;
386
+ }
387
+
388
+ if (count_verify ) {
389
+ free (count_verify );
390
+ count_verify = NULL ;
391
+ }
392
+
393
+ if (uffd != -1 ) {
394
+ if (close (uffd ))
395
+ err ("close uffd" );
396
+ uffd = -1 ;
397
+ }
398
+
399
+ huge_fd_off0 = NULL ;
400
+ munmap_area ((void * * )& area_src );
401
+ munmap_area ((void * * )& area_src_alias );
402
+ munmap_area ((void * * )& area_dst );
403
+ munmap_area ((void * * )& area_dst_alias );
404
+ }
405
+
406
+ static void uffd_test_ctx_init_ext (uint64_t * features )
407
+ {
408
+ unsigned long nr , cpu ;
409
+
410
+ uffd_test_ctx_clear ();
411
+
412
+ uffd_test_ops -> allocate_area ((void * * )& area_src );
413
+ uffd_test_ops -> allocate_area ((void * * )& area_dst );
414
+
415
+ uffd_test_ops -> release_pages (area_src );
416
+ uffd_test_ops -> release_pages (area_dst );
417
+
418
+ userfaultfd_open (features );
419
+
420
+ count_verify = malloc (nr_pages * sizeof (unsigned long long ));
421
+ if (!count_verify )
422
+ err ("count_verify" );
423
+
424
+ for (nr = 0 ; nr < nr_pages ; nr ++ ) {
425
+ * area_mutex (area_src , nr ) =
426
+ (pthread_mutex_t )PTHREAD_MUTEX_INITIALIZER ;
427
+ count_verify [nr ] = * area_count (area_src , nr ) = 1 ;
428
+ /*
429
+ * In the transition between 255 to 256, powerpc will
430
+ * read out of order in my_bcmp and see both bytes as
431
+ * zero, so leave a placeholder below always non-zero
432
+ * after the count, to avoid my_bcmp to trigger false
433
+ * positives.
434
+ */
435
+ * (area_count (area_src , nr ) + 1 ) = 1 ;
436
+ }
437
+
438
+ pipefd = malloc (sizeof (int ) * nr_cpus * 2 );
439
+ if (!pipefd )
440
+ err ("pipefd" );
441
+ for (cpu = 0 ; cpu < nr_cpus ; cpu ++ )
442
+ if (pipe2 (& pipefd [cpu * 2 ], O_CLOEXEC | O_NONBLOCK ))
443
+ err ("pipe" );
444
+ }
445
+
446
+ static inline void uffd_test_ctx_init (uint64_t features )
447
+ {
448
+ uffd_test_ctx_init_ext (& features );
449
+ }
450
+
345
451
static int my_bcmp (char * str1 , char * str2 , size_t n )
346
452
{
347
453
unsigned long i ;
@@ -726,40 +832,6 @@ static int stress(struct uffd_stats *uffd_stats)
726
832
return 0 ;
727
833
}
728
834
729
- static int userfaultfd_open_ext (uint64_t * features )
730
- {
731
- struct uffdio_api uffdio_api ;
732
-
733
- uffd = syscall (__NR_userfaultfd , O_CLOEXEC | O_NONBLOCK | UFFD_USER_MODE_ONLY );
734
- if (uffd < 0 ) {
735
- fprintf (stderr ,
736
- "userfaultfd syscall not available in this kernel\n" );
737
- return 1 ;
738
- }
739
- uffd_flags = fcntl (uffd , F_GETFD , NULL );
740
-
741
- uffdio_api .api = UFFD_API ;
742
- uffdio_api .features = * features ;
743
- if (ioctl (uffd , UFFDIO_API , & uffdio_api )) {
744
- fprintf (stderr , "UFFDIO_API failed.\nPlease make sure to "
745
- "run with either root or ptrace capability.\n" );
746
- return 1 ;
747
- }
748
- if (uffdio_api .api != UFFD_API ) {
749
- fprintf (stderr , "UFFDIO_API error: %" PRIu64 "\n" ,
750
- (uint64_t )uffdio_api .api );
751
- return 1 ;
752
- }
753
-
754
- * features = uffdio_api .features ;
755
- return 0 ;
756
- }
757
-
758
- static int userfaultfd_open (uint64_t features )
759
- {
760
- return userfaultfd_open_ext (& features );
761
- }
762
-
763
835
sigjmp_buf jbuf , * sigbuf ;
764
836
765
837
static void sighndl (int sig , siginfo_t * siginfo , void * ptr )
@@ -868,6 +940,8 @@ static int faulting_process(int signal_test)
868
940
MREMAP_MAYMOVE | MREMAP_FIXED , area_src );
869
941
if (area_dst == MAP_FAILED )
870
942
err ("mremap" );
943
+ /* Reset area_src since we just clobbered it */
944
+ area_src = NULL ;
871
945
872
946
for (; nr < nr_pages ; nr ++ ) {
873
947
count = * area_count (area_dst , nr );
@@ -961,10 +1035,8 @@ static int userfaultfd_zeropage_test(void)
961
1035
printf ("testing UFFDIO_ZEROPAGE: " );
962
1036
fflush (stdout );
963
1037
964
- uffd_test_ops -> release_pages ( area_dst );
1038
+ uffd_test_ctx_init ( 0 );
965
1039
966
- if (userfaultfd_open (0 ))
967
- return 1 ;
968
1040
uffdio_register .range .start = (unsigned long ) area_dst ;
969
1041
uffdio_register .range .len = nr_pages * page_size ;
970
1042
uffdio_register .mode = UFFDIO_REGISTER_MODE_MISSING ;
@@ -981,7 +1053,6 @@ static int userfaultfd_zeropage_test(void)
981
1053
if (my_bcmp (area_dst , zeropage , page_size ))
982
1054
err ("zeropage is not zero" );
983
1055
984
- close (uffd );
985
1056
printf ("done.\n" );
986
1057
return 0 ;
987
1058
}
@@ -999,12 +1070,10 @@ static int userfaultfd_events_test(void)
999
1070
printf ("testing events (fork, remap, remove): " );
1000
1071
fflush (stdout );
1001
1072
1002
- uffd_test_ops -> release_pages (area_dst );
1003
-
1004
1073
features = UFFD_FEATURE_EVENT_FORK | UFFD_FEATURE_EVENT_REMAP |
1005
1074
UFFD_FEATURE_EVENT_REMOVE ;
1006
- if ( userfaultfd_open ( features ))
1007
- return 1 ;
1075
+ uffd_test_ctx_init ( features );
1076
+
1008
1077
fcntl (uffd , F_SETFL , uffd_flags | O_NONBLOCK );
1009
1078
1010
1079
uffdio_register .range .start = (unsigned long ) area_dst ;
@@ -1037,8 +1106,6 @@ static int userfaultfd_events_test(void)
1037
1106
if (pthread_join (uffd_mon , NULL ))
1038
1107
return 1 ;
1039
1108
1040
- close (uffd );
1041
-
1042
1109
uffd_stats_report (& stats , 1 );
1043
1110
1044
1111
return stats .missing_faults != nr_pages ;
@@ -1058,11 +1125,9 @@ static int userfaultfd_sig_test(void)
1058
1125
printf ("testing signal delivery: " );
1059
1126
fflush (stdout );
1060
1127
1061
- uffd_test_ops -> release_pages (area_dst );
1062
-
1063
1128
features = UFFD_FEATURE_EVENT_FORK |UFFD_FEATURE_SIGBUS ;
1064
- if ( userfaultfd_open ( features ))
1065
- return 1 ;
1129
+ uffd_test_ctx_init ( features );
1130
+
1066
1131
fcntl (uffd , F_SETFL , uffd_flags | O_NONBLOCK );
1067
1132
1068
1133
uffdio_register .range .start = (unsigned long ) area_dst ;
@@ -1103,7 +1168,6 @@ static int userfaultfd_sig_test(void)
1103
1168
printf ("done.\n" );
1104
1169
if (userfaults )
1105
1170
err ("Signal test failed, userfaults: %ld" , userfaults );
1106
- close (uffd );
1107
1171
1108
1172
return userfaults != 0 ;
1109
1173
}
@@ -1126,10 +1190,7 @@ static int userfaultfd_minor_test(void)
1126
1190
printf ("testing minor faults: " );
1127
1191
fflush (stdout );
1128
1192
1129
- uffd_test_ops -> release_pages (area_dst );
1130
-
1131
- if (userfaultfd_open_ext (& features ))
1132
- return 1 ;
1193
+ uffd_test_ctx_init_ext (& features );
1133
1194
/* If kernel reports the feature isn't supported, skip the test. */
1134
1195
if (!(features & UFFD_FEATURE_MINOR_HUGETLBFS )) {
1135
1196
printf ("skipping test due to lack of feature support\n" );
@@ -1183,8 +1244,6 @@ static int userfaultfd_minor_test(void)
1183
1244
if (pthread_join (uffd_mon , NULL ))
1184
1245
return 1 ;
1185
1246
1186
- close (uffd );
1187
-
1188
1247
uffd_stats_report (& stats , 1 );
1189
1248
1190
1249
return stats .missing_faults != 0 || stats .minor_faults != nr_pages ;
@@ -1267,7 +1326,7 @@ static void userfaultfd_pagemap_test(unsigned int test_pgsize)
1267
1326
/* Flush so it doesn't flush twice in parent/child later */
1268
1327
fflush (stdout );
1269
1328
1270
- uffd_test_ops -> release_pages ( area_dst );
1329
+ uffd_test_ctx_init ( 0 );
1271
1330
1272
1331
if (test_pgsize > page_size ) {
1273
1332
/* This is a thp test */
@@ -1279,9 +1338,6 @@ static void userfaultfd_pagemap_test(unsigned int test_pgsize)
1279
1338
err ("madvise(MADV_NOHUGEPAGE) failed" );
1280
1339
}
1281
1340
1282
- if (userfaultfd_open (0 ))
1283
- err ("userfaultfd_open" );
1284
-
1285
1341
uffdio_register .range .start = (unsigned long ) area_dst ;
1286
1342
uffdio_register .range .len = nr_pages * page_size ;
1287
1343
uffdio_register .mode = UFFDIO_REGISTER_MODE_WP ;
@@ -1324,7 +1380,6 @@ static void userfaultfd_pagemap_test(unsigned int test_pgsize)
1324
1380
pagemap_check_wp (value , false);
1325
1381
1326
1382
close (pagemap_fd );
1327
- close (uffd );
1328
1383
printf ("done\n" );
1329
1384
}
1330
1385
@@ -1334,50 +1389,9 @@ static int userfaultfd_stress(void)
1334
1389
char * tmp_area ;
1335
1390
unsigned long nr ;
1336
1391
struct uffdio_register uffdio_register ;
1337
- unsigned long cpu ;
1338
1392
struct uffd_stats uffd_stats [nr_cpus ];
1339
1393
1340
- uffd_test_ops -> allocate_area ((void * * )& area_src );
1341
- if (!area_src )
1342
- return 1 ;
1343
- uffd_test_ops -> allocate_area ((void * * )& area_dst );
1344
- if (!area_dst )
1345
- return 1 ;
1346
-
1347
- if (userfaultfd_open (0 ))
1348
- return 1 ;
1349
-
1350
- count_verify = malloc (nr_pages * sizeof (unsigned long long ));
1351
- if (!count_verify ) {
1352
- perror ("count_verify" );
1353
- return 1 ;
1354
- }
1355
-
1356
- for (nr = 0 ; nr < nr_pages ; nr ++ ) {
1357
- * area_mutex (area_src , nr ) = (pthread_mutex_t )
1358
- PTHREAD_MUTEX_INITIALIZER ;
1359
- count_verify [nr ] = * area_count (area_src , nr ) = 1 ;
1360
- /*
1361
- * In the transition between 255 to 256, powerpc will
1362
- * read out of order in my_bcmp and see both bytes as
1363
- * zero, so leave a placeholder below always non-zero
1364
- * after the count, to avoid my_bcmp to trigger false
1365
- * positives.
1366
- */
1367
- * (area_count (area_src , nr ) + 1 ) = 1 ;
1368
- }
1369
-
1370
- pipefd = malloc (sizeof (int ) * nr_cpus * 2 );
1371
- if (!pipefd ) {
1372
- perror ("pipefd" );
1373
- return 1 ;
1374
- }
1375
- for (cpu = 0 ; cpu < nr_cpus ; cpu ++ ) {
1376
- if (pipe2 (& pipefd [cpu * 2 ], O_CLOEXEC | O_NONBLOCK )) {
1377
- perror ("pipe" );
1378
- return 1 ;
1379
- }
1380
- }
1394
+ uffd_test_ctx_init (0 );
1381
1395
1382
1396
if (posix_memalign (& area , page_size , page_size ))
1383
1397
err ("out of memory" );
@@ -1498,8 +1512,6 @@ static int userfaultfd_stress(void)
1498
1512
uffd_stats_report (uffd_stats , nr_cpus );
1499
1513
}
1500
1514
1501
- close (uffd );
1502
-
1503
1515
if (test_type == TEST_ANON ) {
1504
1516
/*
1505
1517
* shmem/hugetlb won't be able to run since they have different
0 commit comments