All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kiryl Shutsemau <kirill@shutemov.name>
To: "David Hildenbrand (Arm)" <david@kernel.org>
Cc: akpm@linux-foundation.org, ljs@kernel.org, hannes@cmpxchg.org,
	 usama.arif@linux.dev, lance.yang@linux.dev, ziy@nvidia.com,
	kasong@tencent.com,  hughd@google.com,
	baolin.wang@linux.alibaba.com, baohua@kernel.org,
	 liam@infradead.org, nico.pache@linux.dev, dev.jain@arm.com,
	ryan.roberts@arm.com,  balbirs@nvidia.com, linux-mm@kvack.org,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH v2 2/2] mm/huge_memory: dequeue the deferred split after the split freeze
Date: Mon, 7 Sep 2026 15:12:21 +0100	[thread overview]
Message-ID: <ap7Fs9DCP3PVOxwY@thinkstation> (raw)
In-Reply-To: <f44181bb-ff82-4537-b2eb-fcbde304d7eb@kernel.org>

On Mon, Sep 07, 2026 at 03:55:53PM +0200, David Hildenbrand (Arm) wrote:
> On 8/31/26 11:15, Kiryl Shutsemau wrote:
> > From: "Kiryl Shutsemau (Meta)" <kas@kernel.org>
> > 
> > __folio_freeze_and_split_unmapped() takes the deferred split list_lru lock
> > across the freeze. It is only there to stop deferred_split_scan() from
> > touching the folio under split.
> > 
> > With deferred_split_isolate() fixed, the workaround can be dropped.
> > 
> > Unqueue the folio after folio_ref_freeze(), the way
> > __folio_migrate_mapping() does: folio_unqueue_deferred_split() needs a
> > zero refcount and a memcg still set, and both hold there.
> > 
> > If the split is called from deferred_split_scan(), the unqueue is a
> > no-op -- the folio is already removed from the list. But
> > PG_partially_mapped is still set, so it has to be cleared here or
> > MTHP_STAT_NR_ANON_PARTIALLY_MAPPED never comes back down.
> > 
> > Assisted-by: Claude-Code:claude-opus-5
> > Signed-off-by: Kiryl Shutsemau (Meta) <kas@kernel.org>
> > Reviewed-by: Zi Yan <ziy@nvidia.com>
> > Reviewed-by: Johannes Weiner <hannes@cmpxchg.org>
> > Acked-by: David Hildenbrand (Arm) <david@kernel.org>
> > ---
> >  mm/huge_memory.c | 44 +++++++++++++-------------------------------
> >  1 file changed, 13 insertions(+), 31 deletions(-)
> > 
> > diff --git a/mm/huge_memory.c b/mm/huge_memory.c
> > index 6281ed993243..c84e8cbc986d 100644
> > --- a/mm/huge_memory.c
> > +++ b/mm/huge_memory.c
> > @@ -3931,41 +3931,27 @@ static int __folio_freeze_and_split_unmapped(struct folio *folio, unsigned int n
> >  	struct folio *end_folio = folio_next(folio);
> >  	struct folio *new_folio, *next;
> >  	int old_order = folio_order(folio);
> > -	struct list_lru_one *lru;
> > -	bool dequeue_deferred;
> >  	int ret = 0;
> >  
> >  	VM_WARN_ON_ONCE(!mapping && end);
> > -	/*
> > -	 * If this folio can be on the deferred split queue, lock out
> > -	 * the shrinker before freezing the ref. If the shrinker sees
> > -	 * a 0-ref folio, it assumes it beat folio_put() to the list
> > -	 * lock and must clean up the LRU state - the same dequeue we
> > -	 * will do below as part of the split.
> > -	 */
> > -	dequeue_deferred = folio_test_anon(folio) && old_order > 1;
> > -	if (dequeue_deferred) {
> > -		struct mem_cgroup *memcg;
> >  
> > -		rcu_read_lock();
> > -		memcg = folio_memcg(folio);
> > -		lru = list_lru_lock(&deferred_split_lru,
> > -				    folio_nid(folio), &memcg);
> > -	}
> 
> Nice cleanup.
> 
> >  	if (folio_ref_freeze(folio, folio_cache_ref_count(folio) + 1)) {
> >  		struct swap_cluster_info *ci = NULL;
> >  		struct lruvec *lruvec;
> >  
> > -		if (dequeue_deferred) {
> > -			__list_lru_del(&deferred_split_lru, lru,
> > -				       &folio->_deferred_list, folio_nid(folio));
> > -			if (folio_test_partially_mapped(folio)) {
> > -				folio_clear_partially_mapped(folio);
> > -				mod_mthp_stat(old_order,
> > -					MTHP_STAT_NR_ANON_PARTIALLY_MAPPED, -1);
> > -			}
> > -			list_lru_unlock(lru);
> > -			rcu_read_unlock();
> > +		/* Take off the deferred split queue while frozen and memcg set */
> > +		folio_unqueue_deferred_split(folio);
> > +
> > +		/*
> > +		 * deferred_split_scan() takes the folio off the queue before it
> > +		 * splits it, so the unqueue above finds an empty list and
> > +		 * leaves PG_partially_mapped set.
> > +		 * Clear it here: the flag does not survive the split.
> > +		 */
> > +		if (folio_test_partially_mapped(folio)) {
> > +			folio_clear_partially_mapped(folio);
> > +			mod_mthp_stat(old_order,
> > +				      MTHP_STAT_NR_ANON_PARTIALLY_MAPPED, -1);
> >  		}
> 
> In general,
> 
> Acked-by: David Hildenbrand (Arm) <david@kernel.org>
> 
> But I do wonder whether this sequence (that also
> __folio_unqueue_deferred_split()) performs would deserve a small local helper in
> mm/huge_memory.c
> 
> Could be done as a separate cleanup.

Just to be sure, do you want a helper like this:

static void folio_clear_partially_mapped_stat(struct folio *folio)
{
      if (!folio_test_partially_mapped(folio))
              return;

      folio_clear_partially_mapped(folio);
      mod_mthp_stat(folio_order(folio),
                    MTHP_STAT_NR_ANON_PARTIALLY_MAPPED, -1);
}

?

-- 
  Kiryl Shutsemau / Kirill A. Shutemov

  reply	other threads:[~2026-09-07 14:12 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-31  9:15 [PATCH v2 0/2] Fix deferred_split_isolate() and drop the split workaround Kiryl Shutsemau
2026-08-31  9:15 ` [PATCH v2 1/2] mm/huge_memory: do not touch frozen folios in deferred_split_isolate() Kiryl Shutsemau
2026-08-31 11:16   ` Lance Yang
2026-08-31 11:23   ` Usama Arif
2026-09-01  1:38   ` Baolin Wang
2026-09-07 13:48   ` David Hildenbrand (Arm)
2026-08-31  9:15 ` [PATCH v2 2/2] mm/huge_memory: dequeue the deferred split after the split freeze Kiryl Shutsemau
2026-08-31 11:34   ` Lance Yang
2026-09-07 13:55   ` David Hildenbrand (Arm)
2026-09-07 14:12     ` Kiryl Shutsemau [this message]
2026-09-07 14:30       ` David Hildenbrand (Arm)

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=ap7Fs9DCP3PVOxwY@thinkstation \
    --to=kirill@shutemov.name \
    --cc=akpm@linux-foundation.org \
    --cc=balbirs@nvidia.com \
    --cc=baohua@kernel.org \
    --cc=baolin.wang@linux.alibaba.com \
    --cc=david@kernel.org \
    --cc=dev.jain@arm.com \
    --cc=hannes@cmpxchg.org \
    --cc=hughd@google.com \
    --cc=kasong@tencent.com \
    --cc=lance.yang@linux.dev \
    --cc=liam@infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=ljs@kernel.org \
    --cc=nico.pache@linux.dev \
    --cc=ryan.roberts@arm.com \
    --cc=usama.arif@linux.dev \
    --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.