From: Joshua Hahn <joshua.hahnjy@gmail.com>
To: Johannes Weiner <hannes@cmpxchg.org>, Gregory Price <gourry@gourry.net>
Cc: Alistair Popple <apopple@nvidia.com>,
Andrew Morton <akpm@linux-foundation.org>,
Axel Rasmussen <axelrasmussen@google.com>,
Barry Song <baohua@kernel.org>, Ben Segall <bsegall@google.com>,
Brendan Jackman <jackmanb@google.com>,
Byungchul Park <byungchul@sk.com>,
David Hildenbrand <david@kernel.org>,
David Rientjes <rientjes@google.com>,
Dietmar Eggemann <dietmar.eggemann@arm.com>,
"Harry Yoo (Oracle)" <harry@kernel.org>,
Ingo Molnar <mingo@redhat.com>,
Juri Lelli <juri.lelli@redhat.com>,
K Prateek Nayak <kprateek.nayak@amd.com>,
Kairui Song <kasong@tencent.com>,
"Liam R. Howlett" <liam@infradead.org>,
Lorenzo Stoakes <ljs@kernel.org>,
Matthew Brost <matthew.brost@intel.com>,
Mel Gorman <mgorman@suse.de>, Michal Hocko <mhocko@kernel.org>,
Michal Hocko <mhocko@suse.com>, Mike Rapoport <rppt@kernel.org>,
Muchun Song <muchun.song@linux.dev>,
Peter Zijlstra <peterz@infradead.org>,
Qi Zheng <qi.zheng@linux.dev>, Rakie Kim <rakie.kim@sk.com>,
Roman Gushchin <roman.gushchin@linux.dev>,
Shakeel Butt <shakeel.butt@linux.dev>,
Steven Rostedt <rostedt@goodmis.org>,
Suren Baghdasaryan <surenb@google.com>,
"T.J. Mercier" <tjmercier@google.com>,
Valentin Schneider <vschneid@redhat.com>,
Vincent Guittot <vincent.guittot@linaro.org>,
Vlastimil Babka <vbabka@kernel.org>, Wei Xu <weixugc@google.com>,
Ying Huang <ying.huang@linux.alibaba.com>,
Yosry Ahmed <yosry@kernel.org>, Yuanchu Xie <yuanchu@google.com>,
Zi Yan <ziy@nvidia.com>,
cgroups@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-mm@kvack.org, kernel-team@meta.com
Subject: [RFC PATCH v3 09/14] mm/memcontrol: Make memory.high tier-aware
Date: Fri, 7 Aug 2026 13:20:52 -0700 [thread overview]
Message-ID: <20260807202059.2620949-10-joshua.hahnjy@gmail.com> (raw)
In-Reply-To: <20260807202059.2620949-1-joshua.hahnjy@gmail.com>
On machines serving multiple workloads whose memory is isolated via
the memory cgroup controller, it is currently impossible to enforce a
fair distribution of tiered memory among the workloads, as the only
enforceable limits have to do with total memory footprint, but not where
that memory resides.
This makes ensuring consistent baseline performance difficult, as each
workload's performance is heavily impacted by workload-external factors
such as which other workloads are co-located in the same host, and the
order in which the workloads are started.
Extend the existing memory.high protection to be tier-aware.
Depending on the combination of limit breaches, selectively reclaim on
tiers: when memory.high is breached, perform reclaim on all tiers.
When memory.high is safe but individual tier limits are breached,
perform targeted reclaim on those tiers only.
No-op unless the system has tiered memcg limits enabled.
Signed-off-by: Joshua Hahn <joshua.hahnjy@gmail.com>
---
mm/memcontrol.c | 66 ++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 55 insertions(+), 11 deletions(-)
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 025496794cb91..44ea465b2005d 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -2387,6 +2387,28 @@ static int memcg_hotplug_cpu_dead(unsigned int cpu)
return 0;
}
+static bool memcg_tier_over_limit(struct mem_cgroup *memcg,
+ unsigned long *overage, int *breached_slot)
+{
+ int nr_tier_slots = mt_nr_tier_slots();
+
+ for (int slot = 0; slot < nr_tier_slots; slot++) {
+ unsigned long usage = page_counter_read(&memcg->tier[slot]);
+ unsigned long limit = READ_ONCE(memcg->tier[slot].high);
+
+ if (usage <= limit)
+ continue;
+
+ if (overage)
+ *overage = usage - limit;
+ if (breached_slot)
+ *breached_slot = slot;
+ return true;
+ }
+
+ return false;
+}
+
static unsigned long reclaim_high(struct mem_cgroup *memcg,
unsigned int nr_pages,
gfp_t gfp_mask)
@@ -2395,10 +2417,19 @@ static unsigned long reclaim_high(struct mem_cgroup *memcg,
do {
unsigned long pflags;
+ const nodemask_t *reclaim_nodes = NULL;
if (page_counter_read(&memcg->memory) <=
- READ_ONCE(memcg->memory.high))
- continue;
+ READ_ONCE(memcg->memory.high)) {
+ int slot;
+
+ if (!mem_cgroup_tiered_limits())
+ continue;
+ if (!memcg_tier_over_limit(memcg, NULL, &slot))
+ continue;
+
+ reclaim_nodes = mt_tier_nodes(slot);
+ }
memcg_memory_event(memcg, MEMCG_HIGH);
@@ -2406,7 +2437,7 @@ static unsigned long reclaim_high(struct mem_cgroup *memcg,
nr_reclaimed += try_to_free_mem_cgroup_pages(memcg, nr_pages,
gfp_mask,
MEMCG_RECLAIM_MAY_SWAP,
- NULL, NULL);
+ NULL, reclaim_nodes);
psi_memstall_leave(&pflags);
} while ((memcg = parent_mem_cgroup(memcg)) &&
!mem_cgroup_is_root(memcg));
@@ -2842,23 +2873,25 @@ static int try_charge_memcg(struct mem_cgroup *memcg, gfp_t gfp_mask,
* reclaim, the cost of mismatch is negligible.
*/
do {
- bool mem_high, swap_high;
+ bool mem_high, swap_high, tier_high;
mem_high = page_counter_read(&memcg->memory) >
READ_ONCE(memcg->memory.high);
swap_high = page_counter_read(&memcg->swap) >
READ_ONCE(memcg->swap.high);
+ tier_high = mem_cgroup_tiered_limits() &&
+ memcg_tier_over_limit(memcg, NULL, NULL);
/* Don't bother a random interrupted task */
if (!in_task()) {
- if (mem_high) {
+ if (mem_high || tier_high) {
schedule_work(&memcg->high_work);
break;
}
continue;
}
- if (mem_high || swap_high) {
+ if (mem_high || swap_high || tier_high) {
/*
* The allocating tasks in this cgroup will need to do
* reclaim or be throttled to prevent further growth
@@ -4967,13 +5000,24 @@ static ssize_t memory_high_write(struct kernfs_open_file *of,
for (;;) {
unsigned long nr_pages = page_counter_read(&memcg->memory);
- unsigned long reclaimed;
+ unsigned long reclaimed, charge;
+ const nodemask_t *reclaim_nodes = NULL;
if (high != READ_ONCE(memcg->memory.high))
break;
- if (nr_pages <= high)
- break;
+ if (nr_pages <= high) {
+ int slot;
+
+ if (!mem_cgroup_tiered_limits())
+ break;
+ if (!memcg_tier_over_limit(memcg, &charge, &slot))
+ break;
+
+ reclaim_nodes = mt_tier_nodes(slot);
+ } else {
+ charge = nr_pages - high;
+ }
if (signal_pending(current))
break;
@@ -4988,9 +5032,9 @@ static ssize_t memory_high_write(struct kernfs_open_file *of,
continue;
}
- reclaimed = try_to_free_mem_cgroup_pages(memcg, nr_pages - high,
+ reclaimed = try_to_free_mem_cgroup_pages(memcg, charge,
GFP_KERNEL, MEMCG_RECLAIM_MAY_SWAP,
- NULL, NULL);
+ NULL, reclaim_nodes);
if (!reclaimed && !nr_retries--)
break;
--
2.53.0-Meta
next prev parent reply other threads:[~2026-08-07 20:21 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-07 20:20 [RFC PATCH v3 00/14] Introduce tiered memcg limits Joshua Hahn
2026-08-07 20:20 ` [RFC PATCH v3 01/14] mm/memcontrol: Introduce cgroup.memory=tiered_limits boot parameter Joshua Hahn
2026-08-07 20:20 ` [RFC PATCH v3 02/14] mm/memcontrol: Refactor page_counter charging in try_charge_memcg Joshua Hahn
2026-08-07 20:20 ` [RFC PATCH v3 03/14] mm/memory-tiers: Introduce a mapping from nid to tier_slot Joshua Hahn
2026-08-07 20:20 ` [RFC PATCH v3 04/14] mm/memcontrol: Allocate per-tier page_counters Joshua Hahn
2026-08-07 20:20 ` [RFC PATCH v3 05/14] mm/memcontrol: Set tier limits proportional to memory limits Joshua Hahn
2026-08-07 20:20 ` [RFC PATCH v3 06/14] mm/vmscan, memcontrol: Add nodemask to try_to_free_mem_cgroup_pages Joshua Hahn
2026-08-07 20:20 ` [RFC PATCH v3 07/14] mm/memcontrol: Charge/uncharge tiered memory to mem_cgroup Joshua Hahn
2026-08-07 20:20 ` [RFC PATCH v3 08/14] mm/memcontrol: Make memory.low and memory.min tier-aware Joshua Hahn
2026-08-07 20:20 ` Joshua Hahn [this message]
2026-08-18 1:21 ` [RFC PATCH v3 09/14] mm/memcontrol: Make memory.high tier-aware Song Hu
2026-08-19 3:46 ` Joshua Hahn
2026-08-07 20:20 ` [RFC PATCH v3 10/14] mm/memcontrol: Make memory.max tier-aware Joshua Hahn
2026-08-07 20:20 ` [RFC PATCH v3 11/14] mm/memcontrol, migrate: Transfer tier charge on migration Joshua Hahn
2026-08-07 20:20 ` [RFC PATCH v3 12/14] mm/memcontrol: Kick async reclaim on migration and folio replacement Joshua Hahn
2026-08-07 20:20 ` [RFC PATCH v3 13/14] mm/memcontrol, sched/numa: Gate NUMA promotions into memcg tiers Joshua Hahn
2026-08-07 20:20 ` [RFC PATCH v3 14/14] mm/page_alloc: steer allocations away from exhausted memory tiers Joshua Hahn
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=20260807202059.2620949-10-joshua.hahnjy@gmail.com \
--to=joshua.hahnjy@gmail.com \
--cc=akpm@linux-foundation.org \
--cc=apopple@nvidia.com \
--cc=axelrasmussen@google.com \
--cc=baohua@kernel.org \
--cc=bsegall@google.com \
--cc=byungchul@sk.com \
--cc=cgroups@vger.kernel.org \
--cc=david@kernel.org \
--cc=dietmar.eggemann@arm.com \
--cc=gourry@gourry.net \
--cc=hannes@cmpxchg.org \
--cc=harry@kernel.org \
--cc=jackmanb@google.com \
--cc=juri.lelli@redhat.com \
--cc=kasong@tencent.com \
--cc=kernel-team@meta.com \
--cc=kprateek.nayak@amd.com \
--cc=liam@infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=ljs@kernel.org \
--cc=matthew.brost@intel.com \
--cc=mgorman@suse.de \
--cc=mhocko@kernel.org \
--cc=mhocko@suse.com \
--cc=mingo@redhat.com \
--cc=muchun.song@linux.dev \
--cc=peterz@infradead.org \
--cc=qi.zheng@linux.dev \
--cc=rakie.kim@sk.com \
--cc=rientjes@google.com \
--cc=roman.gushchin@linux.dev \
--cc=rostedt@goodmis.org \
--cc=rppt@kernel.org \
--cc=shakeel.butt@linux.dev \
--cc=surenb@google.com \
--cc=tjmercier@google.com \
--cc=vbabka@kernel.org \
--cc=vincent.guittot@linaro.org \
--cc=vschneid@redhat.com \
--cc=weixugc@google.com \
--cc=ying.huang@linux.alibaba.com \
--cc=yosry@kernel.org \
--cc=yuanchu@google.com \
--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
all inboxes | Powered by JetHome®