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 <[email protected]>
---
 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


Reply via email to