From: Johannes Weiner <hannes@cmpxchg.org>
To: "Lorenzo Stoakes (Oracle)" <ljs@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>,
David Hildenbrand <david@kernel.org>,
Shakeel Butt <shakeel.butt@linux.dev>,
Yosry Ahmed <yosry.ahmed@linux.dev>, Zi Yan <ziy@nvidia.com>,
"Liam R. Howlett" <Liam.Howlett@oracle.com>,
Usama Arif <usama.arif@linux.dev>,
Kiryl Shutsemau <kas@kernel.org>,
Dave Chinner <david@fromorbit.com>,
Roman Gushchin <roman.gushchin@linux.dev>,
linux-mm@kvack.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v3 7/7] mm: switch deferred split shrinker to list_lru
Date: Mon, 6 Apr 2026 17:37:43 -0400 [thread overview]
Message-ID: <adQnp7d8UJQipDSj@cmpxchg.org> (raw)
In-Reply-To: <a87fdbf4-8e30-465f-b3bd-9ed3ba97c684@lucifer.local>
On Wed, Apr 01, 2026 at 06:33:04PM +0100, Lorenzo Stoakes (Oracle) wrote:
> On Mon, Mar 30, 2026 at 12:40:22PM -0400, Johannes Weiner wrote:
> > > > @@ -414,10 +414,9 @@ static inline int split_huge_page(struct page *page)
> > > > {
> > > > return split_huge_page_to_list_to_order(page, NULL, 0);
> > > > }
> > > > +
> > > > +extern struct list_lru deferred_split_lru;
> > >
> > > It might be nice for the sake of avoiding a global to instead expose this
> > > as a getter?
> > >
> > > Or actually better, since every caller outside of huge_memory.c that
> > > references this uses folio_memcg_list_lru_alloc(), do something like:
> > >
> > > int folio_memcg_alloc_deferred(struct folio *folio, gfp_t gfp);
> > >
> > > in mm/huge_memory.c:
> > >
> > > /**
> > > * blah blah blah put on error blah
> > > */
> > > int folio_memcg_alloc_deferred(struct folio *folio, gfp_t gfp)
> > > {
> > > int err;
> > >
> > > err = folio_memcg_list_lru_alloc(folio, &deferred_split_lru, gfP);
> > > if (err) {
> > > folio_put(folio);
> > > return err;
> > > }
> > >
> > > return 0;
> > > }
> > >
> > > And then the callers can just invoke this, and you can make
> > > deferred_split_lru static in mm/huge_memory.c?
> >
> > That sounds reasonable. Let me make this change.
>
> Thanks!
Done. This looks much nicer. Though I kept the folio_put() in the
caller because that's who owns the reference. It would be quite
unexpected for this one to consume a ref on error.
> > > > @@ -939,6 +949,7 @@ static int __init thp_shrinker_init(void)
> > > >
> > > > huge_zero_folio_shrinker = shrinker_alloc(0, "thp-zero");
> > > > if (!huge_zero_folio_shrinker) {
> > > > + list_lru_destroy(&deferred_split_lru);
> > > > shrinker_free(deferred_split_shrinker);
> > >
> > > Presumably no probably-impossible-in-reality race on somebody entering the
> > > shrinker and referencing the deferred_split_lru before the shrinker is freed?
> >
> > Ah right, I think for clarity it would indeed be better to destroy the
> > shrinker, then the queue. Let me re-order this one.
> >
> > But yes, in practice, none of the above fails. If we have trouble
> > doing a couple of small kmallocs during a subsys_initcall(), that
> > machine is unlikely to finish booting, let alone allocate enough
> > memory to enter the THP shrinker.
>
> Yeah I thought that might be the case, but seems more logical killing shrinker
> first, thanks!
Done.
> > > > @@ -3854,34 +3761,34 @@ 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 *l;
> > >
> > > Nit, and maybe this is a convention, but hate single letter variable names,
> > > 'lru' or something might be nicer?
> >
> > Yeah I stuck with the list_lru internal naming, which uses `lru` for
> > the struct list_lru, and `l` for struct list_lru_one. I suppose that
> > was fine for the very domain-specific code and short functions in
> > there, but it's grating in large, general MM functions like these.
> >
> > Since `lru` is taken, any preferences? llo?
>
> ljs? ;)
>
> Could be list?
list is taken in some of these contexts already. I may have
overthought this. lru works fine in those callsites, and is in line
with what other sites are using (git grep list_lru_one).
> But, and I _know_ it's nitty sorry, but maybe worth expanding that comment to
> explain that e.g. 'we must take the folio look prior to the list_lru lock to
> avoid racing with deferred_split_scan() in accessing the folio reference count'
> or similar?
Good idea! Done.
> > > > + int nid = folio_nid(folio);
> > > > unsigned long flags;
> > > > bool unqueued = false;
> > > >
> > > > WARN_ON_ONCE(folio_ref_count(folio));
> > > > WARN_ON_ONCE(!mem_cgroup_disabled() && !folio_memcg_charged(folio));
> > > >
> > > > - ds_queue = folio_split_queue_lock_irqsave(folio, &flags);
> > > > - if (!list_empty(&folio->_deferred_list)) {
> > > > - ds_queue->split_queue_len--;
> > > > + rcu_read_lock();
> > > > + l = list_lru_lock_irqsave(&deferred_split_lru, nid, folio_memcg(folio), &flags);
> > > > + if (__list_lru_del(&deferred_split_lru, l, &folio->_deferred_list, nid)) {
> > >
> > > Maybe worth factoring __list_lru_del() into something that explicitly
> > > references &folio->_deferred_list rather than open codingin both places?
> >
> > Hm, I wouldn't want to encode this into list_lru API, but we could do
> > a huge_memory.c-local helper?
> >
> > folio_deferred_split_del(folio, l, nid)
>
> Well, I kind of hate how we're using the global deferred_split_lru all over the
> place, so a helper woudl be preferable but one that also could be used for
> khugepaged.c and memory.c also?
This function is used only in huge_memory.c. I managed to make the
deferred_list_lru static as well without making any changes to this ^
particular function/callsite.
Let me know, after looking at the delta diff below, if you'd still
like to see changes here.
> > > > @@ -4534,64 +4438,32 @@ static unsigned long deferred_split_scan(struct shrinker *shrink,
> > > > }
> > > > folio_unlock(folio);
> > > > next:
> > > > - if (did_split || !folio_test_partially_mapped(folio))
> > > > - continue;
> > > > /*
> > > > * Only add back to the queue if folio is partially mapped.
> > > > * If thp_underused returns false, or if split_folio fails
> > > > * in the case it was underused, then consider it used and
> > > > * don't add it back to split_queue.
> > > > */
> > > > - fqueue = folio_split_queue_lock_irqsave(folio, &flags);
> > > > - if (list_empty(&folio->_deferred_list)) {
> > > > - list_add_tail(&folio->_deferred_list, &fqueue->split_queue);
> > > > - fqueue->split_queue_len++;
> > > > + if (!did_split && folio_test_partially_mapped(folio)) {
> > > > + rcu_read_lock();
> > > > + l = list_lru_lock_irqsave(&deferred_split_lru,
> > > > + folio_nid(folio),
> > > > + folio_memcg(folio),
> > > > + &flags);
> > > > + __list_lru_add(&deferred_split_lru, l,
> > > > + &folio->_deferred_list,
> > > > + folio_nid(folio), folio_memcg(folio));
> > > > + list_lru_unlock_irqrestore(l, &flags);
> > >
> > > Hmm this does make me think it'd be nice to have a list_lru_add() variant
> > > for irqsave/restore then, since it's a repeating pattern!
> >
> > Yeah, this site calls for it the most :( I tried to balance callsite
> > prettiness with the need to extend the list_lru api; it's just one
> > caller. And the possible mutations and variants with these locks is
> > seemingly endless once you open that can of worms...
>
> True...
>
> >
> > Case in point: this is process context and we could use
> > spin_lock_irq() here. I'm just using list_lru_lock_irqsave() because
> > that's the common variant used by the add and del paths already.
> >
> > If I went with a helper, I could do list_lru_add_irq().
> >
> > I think it would actually nicely mirror the list_lru_shrink_walk_irq()
> > a few lines up.
>
> Yeah, I mean I'm pretty sure this repeats quite a few times so is worthy of a
> helper.
It's only one callsite, actually. But I added the helper. It's churny
on the list_lru side, but that callsite does look much better.
Anyway, I hope I got everything. Can you take a look? Will obviously
fold this into the respective patches, but just double checking
whether these things are what you had in mind.
---
diff --git a/include/linux/huge_mm.h b/include/linux/huge_mm.h
index 8d801ed378db..b473605b4d7d 100644
--- a/include/linux/huge_mm.h
+++ b/include/linux/huge_mm.h
@@ -415,7 +415,8 @@ static inline int split_huge_page(struct page *page)
return split_huge_page_to_list_to_order(page, NULL, 0);
}
-extern struct list_lru deferred_split_lru;
+int folio_memcg_alloc_deferred(struct folio *folio);
+
void deferred_split_folio(struct folio *folio, bool partially_mapped);
void __split_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
diff --git a/include/linux/list_lru.h b/include/linux/list_lru.h
index 4bd29b61c59a..733a262b91e5 100644
--- a/include/linux/list_lru.h
+++ b/include/linux/list_lru.h
@@ -83,6 +83,21 @@ int memcg_list_lru_alloc(struct mem_cgroup *memcg, struct list_lru *lru,
gfp_t gfp);
#ifdef CONFIG_MEMCG
+/**
+ * folio_memcg_list_lru_alloc - allocate list_lru heads for shrinkable folio
+ * @folio: the newly allocated & charged folio
+ * @lru: the list_lru this might be queued on
+ * @gfp: gfp mask
+ *
+ * Allocate list_lru heads (per-memcg, per-node) needed to queue this
+ * particular folio down the line.
+ *
+ * This does memcg_list_lru_alloc(), but on the memcg that @folio is
+ * associated with. Handles folio_memcg() access rules in the fast
+ * path (list_lru heads allocated) and the allocation slowpath.
+ *
+ * Returns 0 on success, a negative error value otherwise.
+ */
int folio_memcg_list_lru_alloc(struct folio *folio, struct list_lru *lru,
gfp_t gfp);
#else
@@ -118,6 +133,10 @@ struct list_lru_one *list_lru_lock(struct list_lru *lru, int nid,
*/
void list_lru_unlock(struct list_lru_one *l);
+struct list_lru_one *list_lru_lock_irq(struct list_lru *lru, int nid,
+ struct mem_cgroup *memcg);
+void list_lru_unlock_irq(struct list_lru_one *l);
+
struct list_lru_one *list_lru_lock_irqsave(struct list_lru *lru, int nid,
struct mem_cgroup *memcg, unsigned long *irq_flags);
void list_lru_unlock_irqrestore(struct list_lru_one *l,
@@ -161,6 +180,9 @@ bool __list_lru_del(struct list_lru *lru, struct list_lru_one *l,
bool list_lru_add(struct list_lru *lru, struct list_head *item, int nid,
struct mem_cgroup *memcg);
+bool list_lru_add_irq(struct list_lru *lru, struct list_head *item, int nid,
+ struct mem_cgroup *memcg);
+
/**
* list_lru_add_obj: add an element to the lru list's tail
* @lru: the lru pointer
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index c8c6c4602cc7..a0cce6a56620 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -69,7 +69,7 @@ unsigned long transparent_hugepage_flags __read_mostly =
(1<<TRANSPARENT_HUGEPAGE_USE_ZERO_PAGE_FLAG);
static struct lock_class_key deferred_split_key;
-struct list_lru deferred_split_lru;
+static struct list_lru deferred_split_lru;
static struct shrinker *deferred_split_shrinker;
static unsigned long deferred_split_count(struct shrinker *shrink,
struct shrink_control *sc);
@@ -913,6 +913,11 @@ static inline void hugepage_exit_sysfs(struct kobject *hugepage_kobj)
}
#endif /* CONFIG_SYSFS */
+int folio_memcg_alloc_deferred(struct folio *folio)
+{
+ return folio_memcg_list_lru_alloc(folio, &deferred_split_lru, GFP_KERNEL);
+}
+
static int __init thp_shrinker_init(void)
{
deferred_split_shrinker = shrinker_alloc(SHRINKER_NUMA_AWARE |
@@ -949,8 +954,8 @@ static int __init thp_shrinker_init(void)
huge_zero_folio_shrinker = shrinker_alloc(0, "thp-zero");
if (!huge_zero_folio_shrinker) {
- list_lru_destroy(&deferred_split_lru);
shrinker_free(deferred_split_shrinker);
+ list_lru_destroy(&deferred_split_lru);
return -ENOMEM;
}
@@ -964,8 +969,8 @@ static int __init thp_shrinker_init(void)
static void __init thp_shrinker_exit(void)
{
shrinker_free(huge_zero_folio_shrinker);
- list_lru_destroy(&deferred_split_lru);
shrinker_free(deferred_split_shrinker);
+ list_lru_destroy(&deferred_split_lru);
}
static int __init hugepage_init(void)
@@ -1246,7 +1251,7 @@ static struct folio *vma_alloc_anon_folio_pmd(struct vm_area_struct *vma,
return NULL;
}
- if (folio_memcg_list_lru_alloc(folio, &deferred_split_lru, GFP_KERNEL)) {
+ if (folio_memcg_alloc_deferred(folio)) {
folio_put(folio);
count_vm_event(THP_FAULT_FALLBACK);
count_mthp_stat(order, MTHP_STAT_ANON_FAULT_FALLBACK);
@@ -3761,31 +3766,37 @@ 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 *l;
+ struct list_lru_one *lru;
bool dequeue_deferred;
int ret = 0;
VM_WARN_ON_ONCE(!mapping && end);
- /* Prevent deferred_split_scan() touching ->_refcount */
+ /*
+ * 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) {
rcu_read_lock();
- l = list_lru_lock(&deferred_split_lru,
- folio_nid(folio), folio_memcg(folio));
+ lru = list_lru_lock(&deferred_split_lru,
+ folio_nid(folio), folio_memcg(folio));
}
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, l,
+ __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(l);
+ list_lru_unlock(lru);
rcu_read_unlock();
}
@@ -3890,7 +3901,7 @@ static int __folio_freeze_and_split_unmapped(struct folio *folio, unsigned int n
swap_cluster_unlock(ci);
} else {
if (dequeue_deferred) {
- list_lru_unlock(l);
+ list_lru_unlock(lru);
rcu_read_unlock();
}
return -EAGAIN;
@@ -4268,7 +4279,7 @@ int split_folio_to_list(struct folio *folio, struct list_head *list)
*/
bool __folio_unqueue_deferred_split(struct folio *folio)
{
- struct list_lru_one *l;
+ struct list_lru_one *lru;
int nid = folio_nid(folio);
unsigned long flags;
bool unqueued = false;
@@ -4277,8 +4288,8 @@ bool __folio_unqueue_deferred_split(struct folio *folio)
WARN_ON_ONCE(!mem_cgroup_disabled() && !folio_memcg_charged(folio));
rcu_read_lock();
- l = list_lru_lock_irqsave(&deferred_split_lru, nid, folio_memcg(folio), &flags);
- if (__list_lru_del(&deferred_split_lru, l, &folio->_deferred_list, nid)) {
+ lru = list_lru_lock_irqsave(&deferred_split_lru, nid, folio_memcg(folio), &flags);
+ if (__list_lru_del(&deferred_split_lru, lru, &folio->_deferred_list, nid)) {
if (folio_test_partially_mapped(folio)) {
folio_clear_partially_mapped(folio);
mod_mthp_stat(folio_order(folio),
@@ -4286,7 +4297,7 @@ bool __folio_unqueue_deferred_split(struct folio *folio)
}
unqueued = true;
}
- list_lru_unlock_irqrestore(l, &flags);
+ list_lru_unlock_irqrestore(lru, &flags);
rcu_read_unlock();
return unqueued; /* useful for debug warnings */
@@ -4295,7 +4306,7 @@ bool __folio_unqueue_deferred_split(struct folio *folio)
/* partially_mapped=false won't clear PG_partially_mapped folio flag */
void deferred_split_folio(struct folio *folio, bool partially_mapped)
{
- struct list_lru_one *l;
+ struct list_lru_one *lru;
int nid;
struct mem_cgroup *memcg;
unsigned long flags;
@@ -4324,7 +4335,7 @@ void deferred_split_folio(struct folio *folio, bool partially_mapped)
rcu_read_lock();
memcg = folio_memcg(folio);
- l = list_lru_lock_irqsave(&deferred_split_lru, nid, memcg, &flags);
+ lru = list_lru_lock_irqsave(&deferred_split_lru, nid, memcg, &flags);
if (partially_mapped) {
if (!folio_test_partially_mapped(folio)) {
folio_set_partially_mapped(folio);
@@ -4337,8 +4348,8 @@ void deferred_split_folio(struct folio *folio, bool partially_mapped)
/* partially mapped folios cannot become non-partially mapped */
VM_WARN_ON_FOLIO(folio_test_partially_mapped(folio), folio);
}
- __list_lru_add(&deferred_split_lru, l, &folio->_deferred_list, nid, memcg);
- list_lru_unlock_irqrestore(l, &flags);
+ __list_lru_add(&deferred_split_lru, lru, &folio->_deferred_list, nid, memcg);
+ list_lru_unlock_irqrestore(lru, &flags);
rcu_read_unlock();
}
@@ -4411,8 +4422,6 @@ static unsigned long deferred_split_scan(struct shrinker *shrink,
list_for_each_entry_safe(folio, next, &dispose, _deferred_list) {
bool did_split = false;
bool underused = false;
- struct list_lru_one *l;
- unsigned long flags;
list_del_init(&folio->_deferred_list);
@@ -4446,14 +4455,10 @@ static unsigned long deferred_split_scan(struct shrinker *shrink,
*/
if (!did_split && folio_test_partially_mapped(folio)) {
rcu_read_lock();
- l = list_lru_lock_irqsave(&deferred_split_lru,
- folio_nid(folio),
- folio_memcg(folio),
- &flags);
- __list_lru_add(&deferred_split_lru, l,
- &folio->_deferred_list,
- folio_nid(folio), folio_memcg(folio));
- list_lru_unlock_irqrestore(l, &flags);
+ list_lru_add_irq(&deferred_split_lru,
+ &folio->_deferred_list,
+ folio_nid(folio),
+ folio_memcg(folio));
rcu_read_unlock();
}
folio_put(folio);
diff --git a/mm/khugepaged.c b/mm/khugepaged.c
index a81470f529e3..44a9b1350dbd 100644
--- a/mm/khugepaged.c
+++ b/mm/khugepaged.c
@@ -1121,7 +1121,7 @@ static enum scan_result collapse_huge_page(struct mm_struct *mm, unsigned long a
if (result != SCAN_SUCCEED)
goto out_nolock;
- if (folio_memcg_list_lru_alloc(folio, &deferred_split_lru, GFP_KERNEL))
+ if (folio_memcg_alloc_deferred(folio))
goto out_nolock;
mmap_read_lock(mm);
diff --git a/mm/list_lru.c b/mm/list_lru.c
index 1ccdd45b1d14..23bf7c243083 100644
--- a/mm/list_lru.c
+++ b/mm/list_lru.c
@@ -160,6 +160,18 @@ void list_lru_unlock(struct list_lru_one *l)
unlock_list_lru(l, /*irq_off=*/false, /*irq_flags=*/NULL);
}
+struct list_lru_one *list_lru_lock_irq(struct list_lru *lru, int nid,
+ struct mem_cgroup *memcg)
+{
+ return lock_list_lru_of_memcg(lru, nid, memcg, /*irq=*/true,
+ /*irq_flags=*/NULL, /*skip_empty=*/false);
+}
+
+void list_lru_unlock_irq(struct list_lru_one *l)
+{
+ unlock_list_lru(l, /*irq_off=*/true, /*irq_flags=*/NULL);
+}
+
struct list_lru_one *list_lru_lock_irqsave(struct list_lru *lru, int nid,
struct mem_cgroup *memcg,
unsigned long *flags)
@@ -213,6 +225,18 @@ bool list_lru_add(struct list_lru *lru, struct list_head *item, int nid,
return ret;
}
+bool list_lru_add_irq(struct list_lru *lru, struct list_head *item,
+ int nid, struct mem_cgroup *memcg)
+{
+ struct list_lru_one *l;
+ bool ret;
+
+ l = list_lru_lock_irq(lru, nid, memcg);
+ ret = __list_lru_add(lru, l, item, nid, memcg);
+ list_lru_unlock_irq(l);
+ return ret;
+}
+
bool list_lru_add_obj(struct list_lru *lru, struct list_head *item)
{
bool ret;
diff --git a/mm/memory.c b/mm/memory.c
index 24dd531125b4..23da4720576d 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -4658,8 +4658,7 @@ static struct folio *alloc_swap_folio(struct vm_fault *vmf)
folio_put(folio);
goto next;
}
- if (order > 1 &&
- folio_memcg_list_lru_alloc(folio, &deferred_split_lru, GFP_KERNEL)) {
+ if (order > 1 && folio_memcg_alloc_deferred(folio)) {
folio_put(folio);
goto fallback;
}
@@ -5183,8 +5182,7 @@ static struct folio *alloc_anon_folio(struct vm_fault *vmf)
folio_put(folio);
goto next;
}
- if (order > 1 &&
- folio_memcg_list_lru_alloc(folio, &deferred_split_lru, GFP_KERNEL)) {
+ if (order > 1 && folio_memcg_alloc_deferred(folio)) {
folio_put(folio);
goto fallback;
}
next prev parent reply other threads:[~2026-04-06 21:37 UTC|newest]
Thread overview: 42+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-18 19:53 [PATCH v3 0/7] mm: switch THP shrinker to list_lru Johannes Weiner
2026-03-18 19:53 ` [PATCH v3 1/7] mm: list_lru: lock_list_lru_of_memcg() cannot return NULL if !skip_empty Johannes Weiner
2026-03-18 20:12 ` Shakeel Butt
2026-03-24 11:30 ` Lorenzo Stoakes (Oracle)
2026-03-18 19:53 ` [PATCH v3 2/7] mm: list_lru: deduplicate unlock_list_lru() Johannes Weiner
2026-03-24 11:32 ` Lorenzo Stoakes (Oracle)
2026-03-18 19:53 ` [PATCH v3 3/7] mm: list_lru: move list dead check to lock_list_lru_of_memcg() Johannes Weiner
2026-03-18 20:20 ` Shakeel Butt
2026-03-24 11:34 ` Lorenzo Stoakes (Oracle)
2026-03-18 19:53 ` [PATCH v3 4/7] mm: list_lru: deduplicate lock_list_lru() Johannes Weiner
2026-03-18 20:22 ` Shakeel Butt
2026-03-24 11:36 ` Lorenzo Stoakes (Oracle)
2026-03-18 19:53 ` [PATCH v3 5/7] mm: list_lru: introduce caller locking for additions and deletions Johannes Weiner
2026-03-18 20:51 ` Shakeel Butt
2026-03-20 16:18 ` Johannes Weiner
2026-03-24 11:55 ` Lorenzo Stoakes (Oracle)
2026-03-18 19:53 ` [PATCH v3 6/7] mm: list_lru: introduce folio_memcg_list_lru_alloc() Johannes Weiner
2026-03-18 20:52 ` Shakeel Butt
2026-03-18 21:01 ` Shakeel Butt
2026-03-24 12:01 ` Lorenzo Stoakes (Oracle)
2026-03-30 16:54 ` Johannes Weiner
2026-04-01 14:43 ` Lorenzo Stoakes (Oracle)
2026-03-18 19:53 ` [PATCH v3 7/7] mm: switch deferred split shrinker to list_lru Johannes Weiner
2026-03-18 20:26 ` David Hildenbrand (Arm)
2026-03-18 23:18 ` Shakeel Butt
2026-03-24 13:48 ` Lorenzo Stoakes (Oracle)
2026-03-30 16:40 ` Johannes Weiner
2026-04-01 17:33 ` Lorenzo Stoakes (Oracle)
2026-04-06 21:37 ` Johannes Weiner [this message]
2026-03-27 7:51 ` Kairui Song
2026-03-30 16:51 ` Johannes Weiner
2026-03-30 16:37 ` [PATCH v3 7/7] mm: switch deferred split shrinker to list_lru - [s390] panic in __memcg_list_lru_alloc Mikhail Zaslonko
2026-03-30 19:03 ` Andrew Morton
2026-03-30 20:41 ` Johannes Weiner
2026-03-30 20:56 ` Johannes Weiner
2026-03-30 22:46 ` Vasily Gorbik
2026-03-31 8:04 ` Mikhail Zaslonko
2026-03-18 21:00 ` [PATCH v3 0/7] mm: switch THP shrinker to list_lru Lorenzo Stoakes (Oracle)
2026-03-18 22:31 ` Johannes Weiner
2026-03-19 8:47 ` Lorenzo Stoakes (Oracle)
2026-03-19 8:52 ` David Hildenbrand (Arm)
2026-03-19 11:45 ` Lorenzo Stoakes (Oracle)
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=adQnp7d8UJQipDSj@cmpxchg.org \
--to=hannes@cmpxchg.org \
--cc=Liam.Howlett@oracle.com \
--cc=akpm@linux-foundation.org \
--cc=david@fromorbit.com \
--cc=david@kernel.org \
--cc=kas@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=ljs@kernel.org \
--cc=roman.gushchin@linux.dev \
--cc=shakeel.butt@linux.dev \
--cc=usama.arif@linux.dev \
--cc=yosry.ahmed@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox