@@ -610,6 +610,129 @@ static void mremap_shrink_multiple_vmas(unsigned long page_size,
610610 inplace ? " [inplace]" : "" );
611611}
612612
613+ static void mremap_move_multiple_vmas_split (unsigned int pattern_seed ,
614+ unsigned long page_size ,
615+ bool dont_unmap )
616+ {
617+ char * test_name = "mremap move multiple vmas split" ;
618+ int mremap_flags = MREMAP_FIXED | MREMAP_MAYMOVE ;
619+ const size_t size = 10 * page_size ;
620+ bool success = true;
621+ char * ptr , * tgt_ptr ;
622+ int i ;
623+
624+ if (dont_unmap )
625+ mremap_flags |= MREMAP_DONTUNMAP ;
626+
627+ ptr = mmap (NULL , size , PROT_READ | PROT_WRITE ,
628+ MAP_PRIVATE | MAP_ANON , -1 , 0 );
629+ if (ptr == MAP_FAILED ) {
630+ perror ("mmap" );
631+ success = false;
632+ goto out ;
633+ }
634+
635+ tgt_ptr = mmap (NULL , size , PROT_READ | PROT_WRITE ,
636+ MAP_PRIVATE | MAP_ANON , -1 , 0 );
637+ if (tgt_ptr == MAP_FAILED ) {
638+ perror ("mmap" );
639+ success = false;
640+ goto out ;
641+ }
642+ if (munmap (tgt_ptr , size )) {
643+ perror ("munmap" );
644+ success = false;
645+ goto out_unmap ;
646+ }
647+
648+ /*
649+ * Unmap so we end up with:
650+ *
651+ * 0 1 2 3 4 5 6 7 8 9 10 offset in buffer
652+ * |**********| |*******|
653+ * |**********| |*******|
654+ * 0 1 2 3 4 5 6 7 8 9 pattern offset
655+ */
656+ if (munmap (& ptr [5 * page_size ], page_size )) {
657+ perror ("munmap" );
658+ success = false;
659+ goto out_unmap ;
660+ }
661+
662+ /* Set up random patterns. */
663+ srand (pattern_seed );
664+ for (i = 0 ; i < 10 ; i ++ ) {
665+ int j ;
666+ char * buf = & ptr [i * page_size ];
667+
668+ if (i == 5 )
669+ continue ;
670+
671+ for (j = 0 ; j < page_size ; j ++ )
672+ buf [j ] = rand ();
673+ }
674+
675+ /*
676+ * Move the below:
677+ *
678+ * <------------->
679+ * 0 1 2 3 4 5 6 7 8 9 10 offset in buffer
680+ * |**********| |*******|
681+ * |**********| |*******|
682+ * 0 1 2 3 4 5 6 7 8 9 pattern offset
683+ *
684+ * Into:
685+ *
686+ * 0 1 2 3 4 5 6 7 offset in buffer
687+ * |*****| |*****|
688+ * |*****| |*****|
689+ * 2 3 4 5 6 7 pattern offset
690+ */
691+ if (mremap (& ptr [2 * page_size ], size - 3 * page_size , size - 3 * page_size ,
692+ mremap_flags , tgt_ptr ) == MAP_FAILED ) {
693+ perror ("mremap" );
694+ success = false;
695+ goto out_unmap ;
696+ }
697+
698+ /* Offset into random pattern. */
699+ srand (pattern_seed );
700+ for (i = 0 ; i < 2 * page_size ; i ++ )
701+ rand ();
702+
703+ /* Check pattern. */
704+ for (i = 0 ; i < 7 ; i ++ ) {
705+ int j ;
706+ char * buf = & tgt_ptr [i * page_size ];
707+
708+ if (i == 3 )
709+ continue ;
710+
711+ for (j = 0 ; j < page_size ; j ++ ) {
712+ char chr = rand ();
713+
714+ if (chr != buf [j ]) {
715+ ksft_print_msg ("page %d offset %d corrupted, expected %d got %d\n" ,
716+ i , j , chr , buf [j ]);
717+ goto out_unmap ;
718+ }
719+ }
720+ }
721+
722+ out_unmap :
723+ if (munmap (tgt_ptr , size ))
724+ perror ("munmap tgt" );
725+ if (munmap (ptr , size ))
726+ perror ("munmap src" );
727+ out :
728+ if (success )
729+ ksft_test_result_pass ("%s%s\n" , test_name ,
730+ dont_unmap ? " [dontunnmap]" : "" );
731+ else
732+ ksft_test_result_fail ("%s%s\n" , test_name ,
733+ dont_unmap ? " [dontunnmap]" : "" );
734+ }
735+
613736/* Returns the time taken for the remap on success else returns -1. */
614737static long long remap_region (struct config c , unsigned int threshold_mb ,
615738 char * rand_addr )
@@ -951,7 +1074,7 @@ int main(int argc, char **argv)
9511074 char * rand_addr ;
9521075 size_t rand_size ;
9531076 int num_expand_tests = 2 ;
954- int num_misc_tests = 6 ;
1077+ int num_misc_tests = 8 ;
9551078 struct test test_cases [MAX_TEST ] = {};
9561079 struct test perf_test_cases [MAX_PERF_TEST ];
9571080 int page_size ;
@@ -1082,6 +1205,8 @@ int main(int argc, char **argv)
10821205 mremap_shrink_multiple_vmas (page_size , /* inplace= */ false);
10831206 mremap_move_multiple_vmas (pattern_seed , page_size , /* dontunmap= */ false);
10841207 mremap_move_multiple_vmas (pattern_seed , page_size , /* dontunmap= */ true);
1208+ mremap_move_multiple_vmas_split (pattern_seed , page_size , /* dontunmap= */ false);
1209+ mremap_move_multiple_vmas_split (pattern_seed , page_size , /* dontunmap= */ true);
10851210
10861211 if (run_perf_tests ) {
10871212 ksft_print_msg ("\n%s\n" ,
0 commit comments