All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Lorenzo Stoakes (ARM)" <ljs@kernel.org>
To: Kiryl Shutsemau <kirill@shutemov.name>
Cc: akpm@linux-foundation.org, david@kernel.org,
	nico.pache@linux.dev,  baolin.wang@linux.alibaba.com,
	baohua@kernel.org, dev.jain@arm.com, hughd@google.com,
	 lance.yang@linux.dev, liam@infradead.org, mhocko@suse.com,
	rppt@kernel.org,  ryan.roberts@arm.com, shuah@kernel.org,
	surenb@google.com, usama.arif@linux.dev,  vbabka@kernel.org,
	ziy@nvidia.com, usama.anjum@arm.com, agordeev@linux.ibm.com,
	 linux-mm@kvack.org, linux-kselftest@vger.kernel.org,
	linux-kernel@vger.kernel.org,  kas@kernel.org
Subject: Re: [PATCH v4 10/19] selftests/mm: add khugepaged completion barrier helper
Date: Tue, 18 Aug 2026 11:34:27 +0100	[thread overview]
Message-ID: <aoQ0VzEcH-SydZXs@lucifer> (raw)
In-Reply-To: <20260815015901.1236937-11-kirill@shutemov.name>

On Sat, Aug 15, 2026 at 02:58:52AM +0100, Kiryl Shutsemau wrote:
> From: "Kiryl Shutsemau (Meta)" <kas@kernel.org>
>
> Race and functional tests need to drive khugepaged in step: set up a
> layout, let one full scan pass over it, check the result.  The khugepaged
> selftest already waits for full_scans to advance by two, but only makes
> progress if scan_sleep_millisecs happens to be short.
>
> Lift it into khugepaged_full_pass() and drive it through sysfs: any store
> to scan_sleep_millisecs wakes the daemon, so the barrier completes whatever
> the scan cadence.  A store can be lost when the daemon is between scans, so
> it keeps storing until the pass lands; a store to an awake daemon costs
> nothing and queues no extra pass.
>
> One wake completes one pass only if the whole mm list fits in a scan batch,
> so callers need a large pages_to_scan.
>
> Settings pushes must not start passes either.  A store to either sleep knob
> wakes the daemon, so thp_write_settings() now writes a khugepaged knob only
> when its value changes.  The other knobs do not wake, but writing them
> uniformly costs nothing.  thp_update_num() is exported for tests that want
> the same restraint.
>
> Assisted-by: Claude-Code:claude-opus-5
> Tested-by: Muhammad Usama Anjum <usama.anjum@arm.com>
> Signed-off-by: Kiryl Shutsemau (Meta) <kas@kernel.org>
> ---
>  .../testing/selftests/mm/hugepage_settings.c  | 74 ++++++++++++++++---
>  .../testing/selftests/mm/hugepage_settings.h  |  3 +
>  2 files changed, 68 insertions(+), 9 deletions(-)
>
> diff --git a/tools/testing/selftests/mm/hugepage_settings.c b/tools/testing/selftests/mm/hugepage_settings.c
> index d7917dce3aba..992efee17b71 100644
> --- a/tools/testing/selftests/mm/hugepage_settings.c
> +++ b/tools/testing/selftests/mm/hugepage_settings.c
> @@ -183,6 +183,19 @@ void thp_read_settings(struct thp_settings *settings)
>  	}
>  }
>
> +/*
> + * Write only on change: a store to either sleep knob wakes khugepaged --
> + * __sleep_millisecs_store() clears khugepaged_sleep_expire and wakes the
> + * queue -- and settings pushes/pops must not start scan passes nobody
> + * asked for; khugepaged_full_pass() is the only sanctioned wake.  The
> + * other knobs do not wake, but writing them the same way costs nothing.
> + */

This seems quite schloppy and way too much information in a single dense
comment.

You/claude don't need to give your life story in every comment :)

Smaller, clearer, human-written please.

	/*

> +void thp_update_num(const char *name, unsigned long num)
> +{
> +	if (thp_read_num(name) != num)
> +		thp_write_num(name, num);
> +}
> +
>  void thp_write_settings(struct thp_settings *settings)
>  {
>  	struct khugepaged_settings *khugepaged = &settings->khugepaged;
> @@ -198,15 +211,15 @@ void thp_write_settings(struct thp_settings *settings)
>  			shmem_enabled_strings[settings->shmem_enabled]);
>  	thp_write_num("use_zero_page", settings->use_zero_page);
>
> -	thp_write_num("khugepaged/defrag", khugepaged->defrag);
> -	thp_write_num("khugepaged/alloc_sleep_millisecs",
> -			khugepaged->alloc_sleep_millisecs);
> -	thp_write_num("khugepaged/scan_sleep_millisecs",
> -			khugepaged->scan_sleep_millisecs);
> -	thp_write_num("khugepaged/max_ptes_none", khugepaged->max_ptes_none);
> -	thp_write_num("khugepaged/max_ptes_swap", khugepaged->max_ptes_swap);
> -	thp_write_num("khugepaged/max_ptes_shared", khugepaged->max_ptes_shared);
> -	thp_write_num("khugepaged/pages_to_scan", khugepaged->pages_to_scan);
> +	thp_update_num("khugepaged/defrag", khugepaged->defrag);
> +	thp_update_num("khugepaged/alloc_sleep_millisecs",
> +		       khugepaged->alloc_sleep_millisecs);
> +	thp_update_num("khugepaged/scan_sleep_millisecs",
> +		       khugepaged->scan_sleep_millisecs);
> +	thp_update_num("khugepaged/max_ptes_none", khugepaged->max_ptes_none);
> +	thp_update_num("khugepaged/max_ptes_swap", khugepaged->max_ptes_swap);
> +	thp_update_num("khugepaged/max_ptes_shared", khugepaged->max_ptes_shared);
> +	thp_update_num("khugepaged/pages_to_scan", khugepaged->pages_to_scan);
>
>  	if (dev_queue_read_ahead_path[0])
>  		write_num(dev_queue_read_ahead_path, settings->read_ahead_kb);
> @@ -230,6 +243,49 @@ void thp_write_settings(struct thp_settings *settings)
>  	}
>  }
>
> +/*
> + * Completion barrier for khugepaged: wait until a full scan pass that
> + * started after this call has finished. full_scans must advance by two;
> + * a +1 step may complete a pass that examined this mm before the
> + * caller's setup was in place.
> + *
> + * Any store to scan_sleep_millisecs wakes the daemon, so the barrier works
> + * whatever the configured scan cadence -- but a store can be lost.
> + * __sleep_millisecs_store() clears khugepaged_sleep_expire and wakes the
> + * queue; if the daemon is between scans rather than sleeping, it sets
> + * khugepaged_sleep_expire itself on the way into khugepaged_wait_work() and
> + * then sleeps for the full interval, having never seen the store.  So keep
> + * storing until the pass lands; a store while the daemon is awake costs
> + * nothing and does not queue an extra pass.
> + *
> + * One wake completes one full pass only if the whole mm list fits in
> + * one scan batch, so callers must pair this with a large
> + * pages_to_scan.
> + */

Same comment about the comment. This is dense and schloppy. Clarity and
terseness please.

> +bool khugepaged_full_pass(unsigned int timeout_s)
> +{
> +	unsigned long deadline_ms = timeout_s * 1000UL;
> +	unsigned long sleep_ms =
> +		thp_read_num("khugepaged/scan_sleep_millisecs");
> +	unsigned long elapsed_ms = 0;
> +	int pass;
> +
> +	for (pass = 0; pass < 2; pass++) {
> +		unsigned long target =
> +			thp_read_num("khugepaged/full_scans") + 1;
> +
> +		while (thp_read_num("khugepaged/full_scans") < target) {
> +			if (elapsed_ms >= deadline_ms)
> +				return false;
> +			thp_write_num("khugepaged/scan_sleep_millisecs",
> +				      sleep_ms);
> +			usleep(10 * 1000);
> +			elapsed_ms += 10;
> +		}
> +	}
> +	return true;
> +}
> +
>  struct thp_settings *thp_current_settings(void)
>  {
>  	if (!settings_index) {
> diff --git a/tools/testing/selftests/mm/hugepage_settings.h b/tools/testing/selftests/mm/hugepage_settings.h
> index 726c73c43c05..ba7d38370d43 100644
> --- a/tools/testing/selftests/mm/hugepage_settings.h
> +++ b/tools/testing/selftests/mm/hugepage_settings.h
> @@ -70,6 +70,7 @@ int thp_read_string(const char *name, const char * const strings[]);
>  void thp_write_string(const char *name, const char *val);
>  unsigned long thp_read_num(const char *name);
>  void thp_write_num(const char *name, unsigned long num);
> +void thp_update_num(const char *name, unsigned long num);
>
>  void thp_write_settings(struct thp_settings *settings);
>  void thp_read_settings(struct thp_settings *settings);
> @@ -83,6 +84,8 @@ static inline void thp_save_settings(void)
>  	hugepage_save_settings(/* thp = */ true, /* hugetlb = */ false);
>  }
>
> +bool khugepaged_full_pass(unsigned int timeout_s);
> +
>  void thp_set_read_ahead_path(char *path);
>  unsigned long thp_supported_orders(void);
>  unsigned long thp_shmem_supported_orders(void);
> --
> 2.54.0
>

--
Cheers, Lorenzo

  reply	other threads:[~2026-08-18 10:34 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-15  1:58 [PATCH v4 00/19] selftests/mm: improve khugepaged coverage Kiryl Shutsemau
2026-08-15  1:58 ` [PATCH v4 01/19] selftests/mm: raise the khugepaged test-case cap Kiryl Shutsemau
2026-08-18  9:11   ` Lorenzo Stoakes (ARM)
2026-08-15  1:58 ` [PATCH v4 02/19] selftests/mm: skip collapse_compound_extreme() where the PMD is too large Kiryl Shutsemau
2026-08-18  9:22   ` Lorenzo Stoakes (ARM)
2026-08-15  1:58 ` [PATCH v4 03/19] selftests/mm: scale khugepaged's collapse wait with the PMD size Kiryl Shutsemau
2026-08-18 10:04   ` Lorenzo Stoakes (ARM)
2026-08-15  1:58 ` [PATCH v4 04/19] selftests/mm: skip khugepaged page cache cases without a PMD folio Kiryl Shutsemau
2026-08-18 10:07   ` Lorenzo Stoakes (ARM)
2026-08-15  1:58 ` [PATCH v4 05/19] selftests/mm: make the swap cases' swapout reliable Kiryl Shutsemau
2026-08-18 10:11   ` Lorenzo Stoakes (ARM)
2026-08-15  1:58 ` [PATCH v4 06/19] selftests/mm: stop khugepaged during the MADV_COLLAPSE cases Kiryl Shutsemau
2026-08-18 10:12   ` Lorenzo Stoakes (ARM)
2026-08-15  1:58 ` [PATCH v4 07/19] selftests/mm: move is_backed_by_folio() into vm_util Kiryl Shutsemau
2026-08-18 10:14   ` Lorenzo Stoakes (ARM)
2026-08-15  1:58 ` [PATCH v4 08/19] selftests/mm: add folio-order check for address ranges Kiryl Shutsemau
2026-08-18 10:25   ` Lorenzo Stoakes (ARM)
2026-08-15  1:58 ` [PATCH v4 09/19] selftests/mm: add folio-order detection self-check Kiryl Shutsemau
2026-08-18 10:30   ` Lorenzo Stoakes (ARM)
2026-08-15  1:58 ` [PATCH v4 10/19] selftests/mm: add khugepaged completion barrier helper Kiryl Shutsemau
2026-08-18 10:34   ` Lorenzo Stoakes (ARM) [this message]
2026-08-15  1:58 ` [PATCH v4 11/19] selftests/mm: add order-parameterized khugepaged collapse cases Kiryl Shutsemau
2026-08-18 10:38   ` Lorenzo Stoakes (ARM)
2026-08-15  1:58 ` [PATCH v4 12/19] selftests/mm: parameterize the mixed-source collapse case by source order Kiryl Shutsemau
2026-08-18 10:47   ` Lorenzo Stoakes (ARM)
2026-08-15  1:58 ` [PATCH v4 13/19] selftests/mm: cover a shared-source collapse write race Kiryl Shutsemau
2026-08-15  1:58 ` [PATCH v4 14/19] selftests/mm: run every supported collapse order by default Kiryl Shutsemau
2026-08-15  1:58 ` [PATCH v4 15/19] selftests/mm: check that one khugepaged pass collapses one window Kiryl Shutsemau
2026-08-15  1:58 ` [PATCH v4 16/19] selftests/mm: add khugepaged race harness Kiryl Shutsemau
2026-08-15  1:58 ` [PATCH v4 17/19] selftests/mm: race collapse of windows with holes Kiryl Shutsemau
2026-08-15  1:59 ` [PATCH v4 18/19] selftests/mm: add memory-pressure threads to the khugepaged race harness Kiryl Shutsemau
2026-08-15  1:59 ` [PATCH v4 19/19] selftests/mm: zap whole PTE tables in " Kiryl Shutsemau

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=aoQ0VzEcH-SydZXs@lucifer \
    --to=ljs@kernel.org \
    --cc=agordeev@linux.ibm.com \
    --cc=akpm@linux-foundation.org \
    --cc=baohua@kernel.org \
    --cc=baolin.wang@linux.alibaba.com \
    --cc=david@kernel.org \
    --cc=dev.jain@arm.com \
    --cc=hughd@google.com \
    --cc=kas@kernel.org \
    --cc=kirill@shutemov.name \
    --cc=lance.yang@linux.dev \
    --cc=liam@infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=mhocko@suse.com \
    --cc=nico.pache@linux.dev \
    --cc=rppt@kernel.org \
    --cc=ryan.roberts@arm.com \
    --cc=shuah@kernel.org \
    --cc=surenb@google.com \
    --cc=usama.anjum@arm.com \
    --cc=usama.arif@linux.dev \
    --cc=vbabka@kernel.org \
    --cc=ziy@nvidia.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.