Re: [PATCH v5 13/19] selftests/mm: cover a shared-source collapse write race

From: Kiryl Shutsemau

Date: Tue Sep 08 2026 - 18:13:53 EST


On Tue, Sep 08, 2026 at 01:50:59PM +0100, Kiryl Shutsemau wrote:
> + close(sync[1]);
> + if (read(sync[0], &go, 1) != 1)
> + ksft_exit_fail_msg("child never reached the collapse\n");
> +
> + /*
> + * Unshare one page at a time: a burst would break CoW on the whole
> + * range before the collapse starts, leaving nothing shared to collapse.
> + */
> + i = 0;
> + for (;;) {
> + if (i < n)
> + ip[i * stride] = i + 0xbeef0000;
> + i++;
> + usleep(10 * 1000);
> + if (waitpid(child, &wstatus, WNOHANG))
> + break;
> + }

Sashiko flagged two issues here:

- sync[0] never closed. It is fd leak;

- wstatus is garbage if waitpid() fails, returning -1;

Here's a fixup:

diff --git a/tools/testing/selftests/mm/khugepaged.c b/tools/testing/selftests/mm/khugepaged.c
index 335f946eca61..c0a07d75a306 100644
--- a/tools/testing/selftests/mm/khugepaged.c
+++ b/tools/testing/selftests/mm/khugepaged.c
@@ -1228,6 +1228,7 @@ static void collapse_fork_cow_race(struct collapse_context *c, struct mem_ops *o
close(sync[1]);
if (read(sync[0], &go, 1) != 1)
ksft_exit_fail_msg("child never reached the collapse\n");
+ close(sync[0]);

/*
* Unshare one page at a time: a burst would break CoW on the whole
@@ -1235,12 +1236,17 @@ static void collapse_fork_cow_race(struct collapse_context *c, struct mem_ops *o
*/
i = 0;
for (;;) {
+ pid_t ret;
+
if (i < n)
ip[i * stride] = i + 0xbeef0000;
i++;
usleep(10 * 1000);
- if (waitpid(child, &wstatus, WNOHANG))
+ ret = waitpid(child, &wstatus, WNOHANG);
+ if (ret == child)
break;
+ if (ret < 0)
+ ksft_exit_fail_perror("waitpid()");
}

/* Finish whatever the paced sweep did not reach */
--
Kiryl Shutsemau / Kirill A. Shutemov