Although the child process in collapse_fork*() or collapse_max_ptes_shared() reports `KSFT_FAIL`, the result is ignored because the test only checks whether the parent’s page was collapsed into a huge page. As a result, the test is considered successful whenever the parent’s page is a huge page, even if the child test fails, as shown below: # # Run test: collapse_max_ptes_shared (khugepaged:anon) # Allocate huge page... OK # Share huge page over fork()... OK # Trigger CoW on page 1023 of 2048... OK # Maybe collapse with max_ptes_shared exceeded.... OK # Trigger CoW on page 1024 of 2048... Fail Bail out! Unexpected huge page # Planned tests != run tests (26 != 23) # Totals: pass:23 fail:0 xfail:0 xpass:0 skip:0 error:0 // child failed. # Check if parent still has huge page... OK // parent hpage success ok 24 collapse_max_ptes_shared // considered as success ... # Totals: pass:26 fail:0 xfail:0 xpass:0 skip:0 error:0 To address this, propagate the child’s failure and skip the subsequent check in the parent. Signed-off-by: Yeoreum Yun --- tools/testing/selftests/mm/khugepaged.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tools/testing/selftests/mm/khugepaged.c b/tools/testing/selftests/mm/khugepaged.c index f82673f5f6b47..c32244b565658 100644 --- a/tools/testing/selftests/mm/khugepaged.c +++ b/tools/testing/selftests/mm/khugepaged.c @@ -1009,6 +1009,8 @@ static void collapse_fork(struct collapse_context *c, struct mem_ops *ops) wait(&wstatus); exit_status = WEXITSTATUS(wstatus); + if (exit_status == KSFT_FAIL) + goto out; ksft_print_msg("Check if parent still has small page..."); if (ops->check_huge(p, hpage_pmd_size, 0, hpage_pmd_size)) @@ -1016,6 +1018,7 @@ static void collapse_fork(struct collapse_context *c, struct mem_ops *ops) else fail("Fail"); validate_memory(p, 0, page_size); +out: ops->cleanup_area(p, hpage_pmd_size); ksft_test_result_report(exit_status, "%s\n", __func__); } @@ -1056,6 +1059,8 @@ static void collapse_fork_compound(struct collapse_context *c, struct mem_ops *o wait(&wstatus); exit_status = WEXITSTATUS(wstatus); + if (exit_status == KSFT_FAIL) + goto out; ksft_print_msg("Check if parent still has huge page..."); if (ops->check_huge(p, hpage_pmd_size, 1, hpage_pmd_size)) @@ -1063,6 +1068,7 @@ static void collapse_fork_compound(struct collapse_context *c, struct mem_ops *o else fail("Fail"); validate_memory(p, 0, hpage_pmd_size); +out: ops->cleanup_area(p, hpage_pmd_size); ksft_test_result_report(exit_status, "%s\n", __func__); } @@ -1114,6 +1120,8 @@ static void collapse_max_ptes_shared(struct collapse_context *c, struct mem_ops wait(&wstatus); exit_status = WEXITSTATUS(wstatus); + if (exit_status == KSFT_FAIL) + goto out; ksft_print_msg("Check if parent still has huge page..."); if (ops->check_huge(p, hpage_pmd_size, 1, hpage_pmd_size)) @@ -1121,6 +1129,7 @@ static void collapse_max_ptes_shared(struct collapse_context *c, struct mem_ops else fail("Fail"); validate_memory(p, 0, hpage_pmd_size); +out: ops->cleanup_area(p, hpage_pmd_size); ksft_test_result_report(exit_status, "%s\n", __func__); } -- 2.43.0