@@ -118,6 +118,48 @@ static unsigned long long get_mmap_min_addr(void)
118118 return addr ;
119119}
120120
121+ /*
122+ * This test validates that merge is called when expanding a mapping.
123+ * Mapping containing three pages is created, middle page is unmapped
124+ * and then the mapping containing the first page is expanded so that
125+ * it fills the created hole. The two parts should merge creating
126+ * single mapping with three pages.
127+ */
128+ static void mremap_expand_merge (unsigned long page_size )
129+ {
130+ char * test_name = "mremap expand merge" ;
131+ FILE * fp ;
132+ char * line = NULL ;
133+ size_t len = 0 ;
134+ bool success = false;
135+
136+ char * start = mmap (NULL , 3 * page_size , PROT_READ | PROT_WRITE , MAP_PRIVATE | MAP_ANONYMOUS , -1 , 0 );
137+ munmap (start + page_size , page_size );
138+ mremap (start , page_size , 2 * page_size , 0 );
139+
140+ fp = fopen ("/proc/self/maps" , "r" );
141+ if (fp == NULL ) {
142+ ksft_test_result_fail ("%s\n" , test_name );
143+ return ;
144+ }
145+
146+ while (getline (& line , & len , fp ) != -1 ) {
147+ char * first = strtok (line ,"- " );
148+ void * first_val = (void * ) strtol (first , NULL , 16 );
149+ char * second = strtok (NULL ,"- " );
150+ void * second_val = (void * ) strtol (second , NULL , 16 );
151+ if (first_val == start && second_val == start + 3 * page_size ) {
152+ success = true;
153+ break ;
154+ }
155+ }
156+ if (success )
157+ ksft_test_result_pass ("%s\n" , test_name );
158+ else
159+ ksft_test_result_fail ("%s\n" , test_name );
160+ fclose (fp );
161+ }
162+
121163/*
122164 * Returns the start address of the mapping on success, else returns
123165 * NULL on failure.
@@ -336,6 +378,7 @@ int main(int argc, char **argv)
336378 int i , run_perf_tests ;
337379 unsigned int threshold_mb = VALIDATION_DEFAULT_THRESHOLD ;
338380 unsigned int pattern_seed ;
381+ int num_expand_tests = 1 ;
339382 struct test test_cases [MAX_TEST ];
340383 struct test perf_test_cases [MAX_PERF_TEST ];
341384 int page_size ;
@@ -407,12 +450,14 @@ int main(int argc, char **argv)
407450 (threshold_mb * _1MB >= _1GB );
408451
409452 ksft_set_plan (ARRAY_SIZE (test_cases ) + (run_perf_tests ?
410- ARRAY_SIZE (perf_test_cases ) : 0 ));
453+ ARRAY_SIZE (perf_test_cases ) : 0 ) + num_expand_tests );
411454
412455 for (i = 0 ; i < ARRAY_SIZE (test_cases ); i ++ )
413456 run_mremap_test_case (test_cases [i ], & failures , threshold_mb ,
414457 pattern_seed );
415458
459+ mremap_expand_merge (page_size );
460+
416461 if (run_perf_tests ) {
417462 ksft_print_msg ("\n%s\n" ,
418463 "mremap HAVE_MOVE_PMD/PUD optimization time comparison for 1GB region:" );
0 commit comments