* Re: [PATCH v3 1/4] mm/zswap: Make shrink_worker writeback cursor per-memcg
From: Hao Jia @ 2026-06-09 3:18 UTC (permalink / raw)
To: Nhat Pham, Yosry Ahmed, shakeel.butt
Cc: akpm, tj, hannes, mhocko, mkoutny, chengming.zhou, muchun.song,
roman.gushchin, cgroups, linux-mm, linux-kernel, linux-doc,
Hao Jia
In-Reply-To: <CAKEwX=MCFbsh9ndBtR0-bGRr_=v-6bBwTo=muzd9ZSD-LAK1nQ@mail.gmail.com>
On 2026/6/9 02:01, Nhat Pham wrote:
> On Mon, Jun 8, 2026 at 9:48 AM Yosry Ahmed <yosry@kernel.org> wrote:
>>
>>> But OTOH, this does seem like a recipe for inefficient reclaim. We
>>> might exhaust hotter memory of a cgroup while sparing colder memory of
>>> another cgroup... But maybe if they're all cold anyway, then who
>>> cares, and eventually you'll get to the cold stuff of other child?
>>
>> Forgot to respond to this part, the unfairness is limited to the batch
>> size per-invocation, so it should be fine as long as you don't divide
>> the amount over 100 iterations for some reason. Also yes, all memory
>> in zswap is cold, the relative coldness is not that important (e.g.
>> compared to relative coldness during reclaim).
>
> Ok then yeah, I think we should shelve per-memcg cursor for the next
> version. Down the line, if we have more data that unfairness is an
> issue, we can always fix it. One step at a time :)
Thanks a lot to Yosry, Nhat, and Shakeel for the great suggestions!
Let me summarize what I plan to do in the next version to make sure we
are on the same page:
- Drop the per-memcg cursor and keep the root cgroup cursor
(zswap_next_shrink) logic intact.
- Stick to using the zswap_writeback_only key, and change the
proactive writeback size to use the compressed size.
- Consolidate and reuse the logic between shrink_worker() and
shrink_memcg(). Enable batch writeback in the shrink_worker() path,
while keeping the writeback behavior in the zswap_store() path unchanged.
Please let me know if I missed or misunderstood anything. Thanks again
for clearing things up!
Thanks,
Hao
^ permalink raw reply
* [tj-cgroup:for-7.2] BUILD SUCCESS a99ce697ea5e27b867c9ba4ee55fa5ba3b8d1188
From: kernel test robot @ 2026-06-09 2:58 UTC (permalink / raw)
To: Tejun Heo; +Cc: cgroups
tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git for-7.2
branch HEAD: a99ce697ea5e27b867c9ba4ee55fa5ba3b8d1188 cgroup: Migrate tasks to the root css when a controller is rebound
elapsed time: 8964m
configs tested: 86
configs skipped: 9
The following configs have been built successfully.
More configs may be tested in the coming days.
tested configs:
alpha allnoconfig gcc-16.1.0
alpha allyesconfig gcc-16.1.0
arc allmodconfig gcc-16.1.0
arc allnoconfig gcc-16.1.0
arc allyesconfig gcc-16.1.0
arm allnoconfig clang-23
arm allyesconfig gcc-16.1.0
arm64 allmodconfig clang-23
arm64 allnoconfig gcc-16.1.0
csky allmodconfig gcc-16.1.0
csky allnoconfig gcc-16.1.0
csky randconfig-001-20260609 gcc-9.5.0
csky randconfig-002-20260609 gcc-11.5.0
hexagon allmodconfig clang-23
hexagon allnoconfig clang-23
i386 allmodconfig gcc-14
i386 allnoconfig gcc-14
i386 allyesconfig gcc-14
i386 buildonly-randconfig-001-20260609 gcc-14
i386 buildonly-randconfig-002-20260609 gcc-14
i386 buildonly-randconfig-003-20260609 clang-22
i386 buildonly-randconfig-004-20260609 clang-22
i386 buildonly-randconfig-005-20260609 gcc-14
i386 buildonly-randconfig-006-20260609 clang-22
i386 randconfig-011-20260609 clang-22
i386 randconfig-012-20260609 clang-22
i386 randconfig-013-20260609 clang-22
i386 randconfig-014-20260609 gcc-14
i386 randconfig-015-20260609 clang-22
i386 randconfig-016-20260609 clang-22
i386 randconfig-017-20260609 gcc-14
loongarch allmodconfig clang-19
loongarch allnoconfig clang-20
m68k allmodconfig gcc-16.1.0
m68k allnoconfig gcc-16.1.0
m68k allyesconfig gcc-16.1.0
microblaze allnoconfig gcc-16.1.0
microblaze allyesconfig gcc-16.1.0
mips allmodconfig gcc-16.1.0
mips allnoconfig gcc-16.1.0
mips allyesconfig gcc-16.1.0
nios2 allmodconfig gcc-11.5.0
nios2 allnoconfig gcc-11.5.0
openrisc allmodconfig gcc-16.1.0
openrisc allnoconfig gcc-16.1.0
openrisc defconfig gcc-16.1.0
parisc allmodconfig gcc-16.1.0
parisc allnoconfig gcc-16.1.0
parisc allyesconfig gcc-16.1.0
parisc defconfig gcc-16.1.0
powerpc allmodconfig gcc-16.1.0
powerpc allnoconfig gcc-16.1.0
powerpc mpc834x_itxgp_defconfig clang-23
riscv allmodconfig clang-23
riscv allnoconfig gcc-16.1.0
riscv allyesconfig clang-23
riscv defconfig clang-23
riscv randconfig-002-20260609 clang-23
s390 allmodconfig clang-23
s390 allnoconfig clang-23
s390 allyesconfig gcc-16.1.0
s390 defconfig clang-18
s390 randconfig-001-20260609 clang-23
s390 randconfig-002-20260609 gcc-16.1.0
sh allmodconfig gcc-16.1.0
sh allnoconfig gcc-16.1.0
sh allyesconfig gcc-16.1.0
sh randconfig-001-20260609 gcc-13.4.0
sh randconfig-002-20260609 gcc-11.5.0
sparc allnoconfig gcc-16.1.0
sparc defconfig gcc-16.1.0
sparc randconfig-001-20260609 gcc-16.1.0
sparc64 allmodconfig clang-20
sparc64 randconfig-001-20260609 clang-23
um allmodconfig clang-23
um allnoconfig clang-16
um allyesconfig gcc-14
um randconfig-002-20260609 gcc-12
x86_64 allmodconfig clang-22
x86_64 allnoconfig clang-22
x86_64 allyesconfig clang-22
x86_64 rhel-9.4-rust clang-22
xtensa allnoconfig gcc-16.1.0
xtensa allyesconfig gcc-16.1.0
xtensa randconfig-001-20260609 gcc-16.1.0
xtensa randconfig-002-20260609 gcc-8.5.0
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* [tj-cgroup:for-7.1-fixes] BUILD SUCCESS 57aff991119693e09b414aff3267c0eae5e81da0
From: kernel test robot @ 2026-06-09 2:58 UTC (permalink / raw)
To: Tejun Heo; +Cc: cgroups
tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git for-7.1-fixes
branch HEAD: 57aff991119693e09b414aff3267c0eae5e81da0 cgroup/cpuset: Change Ridong's email
elapsed time: 8965m
configs tested: 66
configs skipped: 10
The following configs have been built successfully.
More configs may be tested in the coming days.
tested configs:
alpha allnoconfig gcc-16.1.0
alpha allyesconfig gcc-16.1.0
arc allmodconfig gcc-16.1.0
arc allnoconfig gcc-16.1.0
arc allyesconfig gcc-16.1.0
arm allnoconfig clang-23
arm allyesconfig gcc-16.1.0
arm64 allmodconfig clang-23
arm64 allnoconfig gcc-16.1.0
csky allmodconfig gcc-16.1.0
csky allnoconfig gcc-16.1.0
csky randconfig-001-20260609 gcc-9.5.0
csky randconfig-002-20260609 gcc-11.5.0
hexagon allmodconfig clang-23
hexagon allnoconfig clang-23
i386 allmodconfig gcc-14
i386 allnoconfig gcc-14
i386 allyesconfig gcc-14
loongarch allmodconfig clang-19
loongarch allnoconfig clang-20
m68k allmodconfig gcc-16.1.0
m68k allnoconfig gcc-16.1.0
m68k allyesconfig gcc-16.1.0
microblaze allnoconfig gcc-16.1.0
microblaze allyesconfig gcc-16.1.0
mips allmodconfig gcc-16.1.0
mips allnoconfig gcc-16.1.0
mips allyesconfig gcc-16.1.0
mips jazz_defconfig clang-23
nios2 allmodconfig gcc-11.5.0
nios2 allnoconfig gcc-11.5.0
openrisc allmodconfig gcc-16.1.0
openrisc allnoconfig gcc-16.1.0
openrisc defconfig gcc-16.1.0
parisc allmodconfig gcc-16.1.0
parisc allnoconfig gcc-16.1.0
parisc allyesconfig gcc-16.1.0
parisc defconfig gcc-16.1.0
powerpc allmodconfig gcc-16.1.0
powerpc allnoconfig gcc-16.1.0
riscv allmodconfig clang-23
riscv allnoconfig gcc-16.1.0
riscv allyesconfig clang-23
riscv defconfig clang-23
s390 allmodconfig clang-23
s390 allnoconfig clang-23
s390 allyesconfig gcc-16.1.0
s390 defconfig clang-18
s390 randconfig-002-20260609 gcc-16.1.0
sh allmodconfig gcc-16.1.0
sh allnoconfig gcc-16.1.0
sh allyesconfig gcc-16.1.0
sh randconfig-001-20260609 gcc-13.4.0
sh randconfig-002-20260609 gcc-11.5.0
sparc allnoconfig gcc-16.1.0
sparc defconfig gcc-16.1.0
sparc64 allmodconfig clang-20
um allmodconfig clang-23
um allnoconfig clang-16
um allyesconfig gcc-14
x86_64 allmodconfig clang-22
x86_64 allnoconfig clang-22
x86_64 allyesconfig clang-22
x86_64 rhel-9.4-rust clang-22
xtensa allnoconfig gcc-16.1.0
xtensa allyesconfig gcc-16.1.0
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* Re: [PATCH] mm: constify oom_control, scan_control, and alloc_context nodemask
From: Zi Yan @ 2026-06-09 1:44 UTC (permalink / raw)
To: Gregory Price
Cc: linux-mm, linux-kernel, cgroups, kernel-team, longman, chenridong,
akpm, david, ljs, liam, vbabka, rppt, surenb, mhocko, kasong,
qi.zheng, shakeel.butt, baohua, axelrasmussen, yuanchu, weixugc,
rientjes, chrisl, shikemeng, nphamcs, baoquan.he, youngjun.park,
tj, hannes, mkoutny, jackmanb
In-Reply-To: <20260609002919.3967782-1-gourry@gourry.net>
On 8 Jun 2026, at 20:29, Gregory Price wrote:
> The nodemasks in these structures may come from a variety of sources,
> including tasks and cpusets - and should never be modified by any code
> when being passed around inside another context.
>
> Signed-off-by: Gregory Price <gourry@gourry.net>
> ---
> include/linux/cpuset.h | 4 ++--
> include/linux/mm.h | 4 ++--
> include/linux/mmzone.h | 6 +++---
> include/linux/oom.h | 2 +-
> include/linux/swap.h | 2 +-
> kernel/cgroup/cpuset.c | 2 +-
> mm/internal.h | 2 +-
> mm/mmzone.c | 5 +++--
> mm/page_alloc.c | 6 +++---
> mm/show_mem.c | 9 ++++++---
> mm/vmscan.c | 6 +++---
> 11 files changed, 26 insertions(+), 22 deletions(-)
>
LGTM and it compiles. As long as Sashiko does not complain, feel free to
add:
Acked-by: Zi Yan <ziy@nvidia.com>
Best Regards,
Yan, Zi
^ permalink raw reply
* [PATCH] mm: constify oom_control, scan_control, and alloc_context nodemask
From: Gregory Price @ 2026-06-09 0:29 UTC (permalink / raw)
To: linux-mm
Cc: linux-kernel, cgroups, kernel-team, longman, chenridong, akpm,
david, ljs, liam, vbabka, rppt, surenb, mhocko, kasong, qi.zheng,
shakeel.butt, baohua, axelrasmussen, yuanchu, weixugc, rientjes,
chrisl, shikemeng, nphamcs, baoquan.he, youngjun.park, tj, hannes,
mkoutny, jackmanb, ziy
The nodemasks in these structures may come from a variety of sources,
including tasks and cpusets - and should never be modified by any code
when being passed around inside another context.
Signed-off-by: Gregory Price <gourry@gourry.net>
---
include/linux/cpuset.h | 4 ++--
include/linux/mm.h | 4 ++--
include/linux/mmzone.h | 6 +++---
include/linux/oom.h | 2 +-
include/linux/swap.h | 2 +-
kernel/cgroup/cpuset.c | 2 +-
mm/internal.h | 2 +-
mm/mmzone.c | 5 +++--
mm/page_alloc.c | 6 +++---
mm/show_mem.c | 9 ++++++---
mm/vmscan.c | 6 +++---
11 files changed, 26 insertions(+), 22 deletions(-)
diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h
index 65d76a38974b..a80d38e752d2 100644
--- a/include/linux/cpuset.h
+++ b/include/linux/cpuset.h
@@ -83,7 +83,7 @@ extern bool cpuset_cpus_allowed_fallback(struct task_struct *p);
extern nodemask_t cpuset_mems_allowed(struct task_struct *p);
#define cpuset_current_mems_allowed (current->mems_allowed)
void cpuset_init_current_mems_allowed(void);
-int cpuset_nodemask_valid_mems_allowed(nodemask_t *nodemask);
+int cpuset_nodemask_valid_mems_allowed(const nodemask_t *nodemask);
extern bool cpuset_current_node_allowed(int node, gfp_t gfp_mask);
@@ -224,7 +224,7 @@ static inline nodemask_t cpuset_mems_allowed(struct task_struct *p)
#define cpuset_current_mems_allowed (node_states[N_MEMORY])
static inline void cpuset_init_current_mems_allowed(void) {}
-static inline int cpuset_nodemask_valid_mems_allowed(nodemask_t *nodemask)
+static inline int cpuset_nodemask_valid_mems_allowed(const nodemask_t *nodemask)
{
return 1;
}
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 485df9c2dbdd..2101e5205fc0 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -4042,7 +4042,7 @@ extern int __meminit early_pfn_to_nid(unsigned long pfn);
extern void mem_init(void);
extern void __init mmap_init(void);
-extern void __show_mem(unsigned int flags, nodemask_t *nodemask, int max_zone_idx);
+extern void __show_mem(unsigned int flags, const nodemask_t *nodemask, int max_zone_idx);
static inline void show_mem(void)
{
__show_mem(0, NULL, MAX_NR_ZONES - 1);
@@ -4052,7 +4052,7 @@ extern void si_meminfo(struct sysinfo * val);
extern void si_meminfo_node(struct sysinfo *val, int nid);
extern __printf(3, 4)
-void warn_alloc(gfp_t gfp_mask, nodemask_t *nodemask, const char *fmt, ...);
+void warn_alloc(gfp_t gfp_mask, const nodemask_t *nodemask, const char *fmt, ...);
extern void setup_per_cpu_pageset(void);
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index ca2712187147..919be0d9b4fa 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -1815,7 +1815,7 @@ static inline int zonelist_node_idx(const struct zoneref *zoneref)
struct zoneref *__next_zones_zonelist(struct zoneref *z,
enum zone_type highest_zoneidx,
- nodemask_t *nodes);
+ const nodemask_t *nodes);
/**
* next_zones_zonelist - Returns the next zone at or below highest_zoneidx within the allowed nodemask using a cursor within a zonelist as a starting point
@@ -1834,7 +1834,7 @@ struct zoneref *__next_zones_zonelist(struct zoneref *z,
*/
static __always_inline struct zoneref *next_zones_zonelist(struct zoneref *z,
enum zone_type highest_zoneidx,
- nodemask_t *nodes)
+ const nodemask_t *nodes)
{
if (likely(!nodes && zonelist_zone_idx(z) <= highest_zoneidx))
return z;
@@ -1860,7 +1860,7 @@ static __always_inline struct zoneref *next_zones_zonelist(struct zoneref *z,
*/
static inline struct zoneref *first_zones_zonelist(struct zonelist *zonelist,
enum zone_type highest_zoneidx,
- nodemask_t *nodes)
+ const nodemask_t *nodes)
{
return next_zones_zonelist(zonelist->_zonerefs,
highest_zoneidx, nodes);
diff --git a/include/linux/oom.h b/include/linux/oom.h
index 7b02bc1d0a7e..00da05d227e6 100644
--- a/include/linux/oom.h
+++ b/include/linux/oom.h
@@ -30,7 +30,7 @@ struct oom_control {
struct zonelist *zonelist;
/* Used to determine mempolicy */
- nodemask_t *nodemask;
+ const nodemask_t *nodemask;
/* Memory cgroup in which oom is invoked, or NULL for global oom */
struct mem_cgroup *memcg;
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 8f0f68e245ba..bf76356d94fe 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -351,7 +351,7 @@ extern void swap_setup(void);
/* linux/mm/vmscan.c */
extern unsigned long zone_reclaimable_pages(struct zone *zone);
extern unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
- gfp_t gfp_mask, nodemask_t *mask);
+ gfp_t gfp_mask, const nodemask_t *mask);
unsigned long lruvec_lru_size(struct lruvec *lruvec, enum lru_list lru, int zone_idx);
#define MEMCG_RECLAIM_MAY_SWAP (1 << 1)
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 5c33ab20cc20..536ce591c7ba 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -4153,7 +4153,7 @@ nodemask_t cpuset_mems_allowed(struct task_struct *tsk)
*
* Are any of the nodes in the nodemask allowed in current->mems_allowed?
*/
-int cpuset_nodemask_valid_mems_allowed(nodemask_t *nodemask)
+int cpuset_nodemask_valid_mems_allowed(const nodemask_t *nodemask)
{
return nodes_intersects(*nodemask, current->mems_allowed);
}
diff --git a/mm/internal.h b/mm/internal.h
index 181e79f1d6a2..a2ef9512b5bc 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -668,7 +668,7 @@ void page_alloc_sysctl_init(void);
*/
struct alloc_context {
struct zonelist *zonelist;
- nodemask_t *nodemask;
+ const nodemask_t *nodemask;
struct zoneref *preferred_zoneref;
int migratetype;
diff --git a/mm/mmzone.c b/mm/mmzone.c
index 0c8f181d9d50..59dc3f2076a6 100644
--- a/mm/mmzone.c
+++ b/mm/mmzone.c
@@ -43,7 +43,8 @@ struct zone *next_zone(struct zone *zone)
return zone;
}
-static inline int zref_in_nodemask(struct zoneref *zref, nodemask_t *nodes)
+static inline int zref_in_nodemask(struct zoneref *zref,
+ const nodemask_t *nodes)
{
#ifdef CONFIG_NUMA
return node_isset(zonelist_node_idx(zref), *nodes);
@@ -55,7 +56,7 @@ static inline int zref_in_nodemask(struct zoneref *zref, nodemask_t *nodes)
/* Returns the next zone at or below highest_zoneidx in a zonelist */
struct zoneref *__next_zones_zonelist(struct zoneref *z,
enum zone_type highest_zoneidx,
- nodemask_t *nodes)
+ const nodemask_t *nodes)
{
/*
* Find the next suitable zone to use for the allocation.
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 81a9d4d1e6c0..586524bbde9c 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -3979,7 +3979,7 @@ get_page_from_freelist(gfp_t gfp_mask, unsigned int order, int alloc_flags,
return NULL;
}
-static void warn_alloc_show_mem(gfp_t gfp_mask, nodemask_t *nodemask)
+static void warn_alloc_show_mem(gfp_t gfp_mask, const nodemask_t *nodemask)
{
unsigned int filter = SHOW_MEM_FILTER_NODES;
@@ -3999,7 +3999,7 @@ static void warn_alloc_show_mem(gfp_t gfp_mask, nodemask_t *nodemask)
mem_cgroup_show_protected_memory(NULL);
}
-void warn_alloc(gfp_t gfp_mask, nodemask_t *nodemask, const char *fmt, ...)
+void warn_alloc(gfp_t gfp_mask, const nodemask_t *nodemask, const char *fmt, ...)
{
struct va_format vaf;
va_list args;
@@ -4687,7 +4687,7 @@ check_retry_cpuset(int cpuset_mems_cookie, struct alloc_context *ac)
return false;
}
-static void check_alloc_stall_warn(gfp_t gfp_mask, nodemask_t *nodemask,
+static void check_alloc_stall_warn(gfp_t gfp_mask, const nodemask_t *nodemask,
unsigned int order, unsigned long alloc_start_time)
{
static DEFINE_SPINLOCK(alloc_stall_lock);
diff --git a/mm/show_mem.c b/mm/show_mem.c
index 43aca5a2ac99..1b721a8ade67 100644
--- a/mm/show_mem.c
+++ b/mm/show_mem.c
@@ -116,7 +116,8 @@ void si_meminfo_node(struct sysinfo *val, int nid)
* Determine whether the node should be displayed or not, depending on whether
* SHOW_MEM_FILTER_NODES was passed to show_free_areas().
*/
-static bool show_mem_node_skip(unsigned int flags, int nid, nodemask_t *nodemask)
+static bool show_mem_node_skip(unsigned int flags, int nid,
+ const nodemask_t *nodemask)
{
if (!(flags & SHOW_MEM_FILTER_NODES))
return false;
@@ -177,7 +178,8 @@ static bool node_has_managed_zones(pg_data_t *pgdat, int max_zone_idx)
* SHOW_MEM_FILTER_NODES: suppress nodes that are not allowed by current's
* cpuset.
*/
-static void show_free_areas(unsigned int filter, nodemask_t *nodemask, int max_zone_idx)
+static void show_free_areas(unsigned int filter, const nodemask_t *nodemask,
+ int max_zone_idx)
{
unsigned long free_pcp = 0;
int cpu, nid;
@@ -402,7 +404,8 @@ static void show_free_areas(unsigned int filter, nodemask_t *nodemask, int max_z
show_swap_cache_info();
}
-void __show_mem(unsigned int filter, nodemask_t *nodemask, int max_zone_idx)
+void __show_mem(unsigned int filter, const nodemask_t *nodemask,
+ int max_zone_idx)
{
unsigned long total = 0, reserved = 0, highmem = 0;
struct zone *zone;
diff --git a/mm/vmscan.c b/mm/vmscan.c
index e8a90911bf88..47d3f3361fb9 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -79,7 +79,7 @@ struct scan_control {
* Nodemask of nodes allowed by the caller. If NULL, all nodes
* are scanned.
*/
- nodemask_t *nodemask;
+ const nodemask_t *nodemask;
/*
* The memory cgroup that hit its limit and as a result is the
@@ -6599,7 +6599,7 @@ static bool allow_direct_reclaim(pg_data_t *pgdat)
* happens, the page allocator should not consider triggering the OOM killer.
*/
static bool throttle_direct_reclaim(gfp_t gfp_mask, struct zonelist *zonelist,
- nodemask_t *nodemask)
+ const nodemask_t *nodemask)
{
struct zoneref *z;
struct zone *zone;
@@ -6679,7 +6679,7 @@ static bool throttle_direct_reclaim(gfp_t gfp_mask, struct zonelist *zonelist,
}
unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
- gfp_t gfp_mask, nodemask_t *nodemask)
+ gfp_t gfp_mask, const nodemask_t *nodemask)
{
unsigned long nr_reclaimed;
struct scan_control sc = {
--
2.54.0
^ permalink raw reply related
* Re: [PATCH v3 2/4] mm/zswap: Implement proactive writeback
From: Yosry Ahmed @ 2026-06-08 22:27 UTC (permalink / raw)
To: Shakeel Butt
Cc: Hao Jia, Johannes Weiner, mhocko, tj, mkoutny, roman.gushchin,
Nhat Pham, akpm, chengming.zhou, muchun.song, cgroups, linux-mm,
linux-kernel, linux-doc, Hao Jia, youngjun.park
In-Reply-To: <aictKA0XWMWbxFdN@linux.dev>
> > > Youngjun is working on swap tiers. At the moment he is more interested in
> > > allowing a specific swap device to a memcg or not. I can imagine in future there
> > > will be use-cases where there will be a need to demote data on higher tier swap
> > > to lower tier swap. What would be the appropriate interface?
> > >
> > > BTW does zswap folks think of zswap as a top swap tier or something different?
> >
> > I haven't been following the swap tiers work closely, but personally I
> > do think of zswap as a top swap tier.
>
> Same for me though I imagine swap tiers would introduce some duplication i.e.
> different way (interface) to set limits for swap tiers for a given memcg.
>
> > Things will probably get more
> > blurry with memory tiers and compressed memory nodes though.
>
> I think there will still be distinction between byte addressable and fault on
> access devices.
Yeah, I think it makes sense to define "swap" as fault on access
(zswap, SSD, etc), and memory tiers as byte-addressable (even if you
put an SSD behind CXL and make it byte-addressable). But I also
remember seeing discussions about unifying memory tiers and swap in a
way, and it makes sense from a reclaim perspective (swap or demote
first?).
^ permalink raw reply
* Re: [PATCH v3 2/4] mm/zswap: Implement proactive writeback
From: Shakeel Butt @ 2026-06-08 22:22 UTC (permalink / raw)
To: Yosry Ahmed
Cc: Hao Jia, Johannes Weiner, mhocko, tj, mkoutny, roman.gushchin,
Nhat Pham, akpm, chengming.zhou, muchun.song, cgroups, linux-mm,
linux-kernel, linux-doc, Hao Jia, youngjun.park
In-Reply-To: <CAO9r8zNBJ-BsXyKFveA92jbwMu63uFVTY5CuT4fRHTBVcOjhPw@mail.gmail.com>
On Mon, Jun 08, 2026 at 01:19:32PM -0700, Yosry Ahmed wrote:
> On Mon, Jun 8, 2026 at 12:50 PM Shakeel Butt <shakeel.butt@linux.dev> wrote:
> >
> > +Youngjun
> >
> > On Mon, Jun 08, 2026 at 11:30:30AM -0700, Shakeel Butt wrote:
> > > On Wed, Jun 03, 2026 at 10:36:07PM -0700, Yosry Ahmed wrote:
> > > > > >> But doesn't it make more sense to specify the compressed size, which is
> > > > > >> ultimately the amount of memory you actually want to reclaim.
> > > > > >>
> > > > > >
> > > > > > I personally prefer compressed size to pre-compressed size. That's
> > > > > > kinda what user cares about, no?
> > > > > >
> > > > > > One thing we can do is let users prescribe a compressed size, but
> > > > > > internally, we can multiply that by the average compression ratio.
> > > > > > That gives us a guesstimate of how many pages we need to reclaim, and
> > > > > > you can follow the rest of your implementation as is (perhaps with
> > > > > > short-circuit when we reach the goal with fewer pages reclaimed).
> > > > >
> > > > > Got it. I will change it to use the compressed size in the next version.
> > > > >
> > > > > Yosry, Nhat, should we continue using the zswap_writeback_only key to
> > > > > trigger proactive writeback?
> > > >
> > > > I *really* want the memcg maintainers to chime in here, it's
> > > > ultimately their call.
> > > >
> > > > Michal? Johannes? Shakeel? Roman? Anyone? :D
> > >
> > > Between the options of having an explicit interface (i.e.
> > > memory.zswap.writeback*) or a key (i.e. zswap_writeback_only) to memory.reclaim
> > > interface, I prefer the key option. I have not looked into how much proactively
> > > reclaiming zswap memory or proactively triggering zswap writeback makes sense
> > > but from the perspective of memcg interface, I think the key option would give a
> > > more clean solution if we decide in the future that this whole thing was a bad
> > > idea.
> > >
> > > Next regarding future proofing zswap writeback trigger, do we expect any
> > > potential additions/changes/new-features for this interface? For example do we
> > > expect in future we may want to trigger the zswap writeback only from a specific
> > > node or lowest memory tier?
>
> The way I see it, zswap writeback is just a "special" type of
> proactive reclaim, but the goal is still proactively freeing cold
> memory. In that regard, I think it makes sense to have things like
> node-specific reclaim. Not sure about other extensions, but Hao
> initially suggested making this age-based, so I think the answer is
> yes.
>
> For both of these examples (node-specific reclaim, age-based reclaim),
> I think the same semantics could apply to memory.reclaim in general,
> which is why I suggested making it a part of memory.reclaim. I also
> like the idea of having a single proactive reclaim interface in
> general, but maybe we don't want to overload it too much.
IMHO it is fine.
>
> > Youngjun is working on swap tiers. At the moment he is more interested in
> > allowing a specific swap device to a memcg or not. I can imagine in future there
> > will be use-cases where there will be a need to demote data on higher tier swap
> > to lower tier swap. What would be the appropriate interface?
> >
> > BTW does zswap folks think of zswap as a top swap tier or something different?
>
> I haven't been following the swap tiers work closely, but personally I
> do think of zswap as a top swap tier.
Same for me though I imagine swap tiers would introduce some duplication i.e.
different way (interface) to set limits for swap tiers for a given memcg.
> Things will probably get more
> blurry with memory tiers and compressed memory nodes though.
I think there will still be distinction between byte addressable and fault on
access devices.
^ permalink raw reply
* Re: [PATCH v3 2/4] mm/zswap: Implement proactive writeback
From: Yosry Ahmed @ 2026-06-08 20:19 UTC (permalink / raw)
To: Shakeel Butt
Cc: Hao Jia, Johannes Weiner, mhocko, tj, mkoutny, roman.gushchin,
Nhat Pham, akpm, chengming.zhou, muchun.song, cgroups, linux-mm,
linux-kernel, linux-doc, Hao Jia, youngjun.park
In-Reply-To: <aicZ-5GX9De3MAU7@linux.dev>
On Mon, Jun 8, 2026 at 12:50 PM Shakeel Butt <shakeel.butt@linux.dev> wrote:
>
> +Youngjun
>
> On Mon, Jun 08, 2026 at 11:30:30AM -0700, Shakeel Butt wrote:
> > On Wed, Jun 03, 2026 at 10:36:07PM -0700, Yosry Ahmed wrote:
> > > > >> But doesn't it make more sense to specify the compressed size, which is
> > > > >> ultimately the amount of memory you actually want to reclaim.
> > > > >>
> > > > >
> > > > > I personally prefer compressed size to pre-compressed size. That's
> > > > > kinda what user cares about, no?
> > > > >
> > > > > One thing we can do is let users prescribe a compressed size, but
> > > > > internally, we can multiply that by the average compression ratio.
> > > > > That gives us a guesstimate of how many pages we need to reclaim, and
> > > > > you can follow the rest of your implementation as is (perhaps with
> > > > > short-circuit when we reach the goal with fewer pages reclaimed).
> > > >
> > > > Got it. I will change it to use the compressed size in the next version.
> > > >
> > > > Yosry, Nhat, should we continue using the zswap_writeback_only key to
> > > > trigger proactive writeback?
> > >
> > > I *really* want the memcg maintainers to chime in here, it's
> > > ultimately their call.
> > >
> > > Michal? Johannes? Shakeel? Roman? Anyone? :D
> >
> > Between the options of having an explicit interface (i.e.
> > memory.zswap.writeback*) or a key (i.e. zswap_writeback_only) to memory.reclaim
> > interface, I prefer the key option. I have not looked into how much proactively
> > reclaiming zswap memory or proactively triggering zswap writeback makes sense
> > but from the perspective of memcg interface, I think the key option would give a
> > more clean solution if we decide in the future that this whole thing was a bad
> > idea.
> >
> > Next regarding future proofing zswap writeback trigger, do we expect any
> > potential additions/changes/new-features for this interface? For example do we
> > expect in future we may want to trigger the zswap writeback only from a specific
> > node or lowest memory tier?
The way I see it, zswap writeback is just a "special" type of
proactive reclaim, but the goal is still proactively freeing cold
memory. In that regard, I think it makes sense to have things like
node-specific reclaim. Not sure about other extensions, but Hao
initially suggested making this age-based, so I think the answer is
yes.
For both of these examples (node-specific reclaim, age-based reclaim),
I think the same semantics could apply to memory.reclaim in general,
which is why I suggested making it a part of memory.reclaim. I also
like the idea of having a single proactive reclaim interface in
general, but maybe we don't want to overload it too much.
> Youngjun is working on swap tiers. At the moment he is more interested in
> allowing a specific swap device to a memcg or not. I can imagine in future there
> will be use-cases where there will be a need to demote data on higher tier swap
> to lower tier swap. What would be the appropriate interface?
>
> BTW does zswap folks think of zswap as a top swap tier or something different?
I haven't been following the swap tiers work closely, but personally I
do think of zswap as a top swap tier. Things will probably get more
blurry with memory tiers and compressed memory nodes though.
^ permalink raw reply
* Re: [PATCH v3 2/4] mm/zswap: Implement proactive writeback
From: Shakeel Butt @ 2026-06-08 19:50 UTC (permalink / raw)
To: Yosry Ahmed
Cc: Hao Jia, Johannes Weiner, mhocko, tj, mkoutny, roman.gushchin,
Nhat Pham, akpm, chengming.zhou, muchun.song, cgroups, linux-mm,
linux-kernel, linux-doc, Hao Jia, youngjun.park
In-Reply-To: <aicJBVT4pBvmyooT@linux.dev>
+Youngjun
On Mon, Jun 08, 2026 at 11:30:30AM -0700, Shakeel Butt wrote:
> On Wed, Jun 03, 2026 at 10:36:07PM -0700, Yosry Ahmed wrote:
> > > >> But doesn't it make more sense to specify the compressed size, which is
> > > >> ultimately the amount of memory you actually want to reclaim.
> > > >>
> > > >
> > > > I personally prefer compressed size to pre-compressed size. That's
> > > > kinda what user cares about, no?
> > > >
> > > > One thing we can do is let users prescribe a compressed size, but
> > > > internally, we can multiply that by the average compression ratio.
> > > > That gives us a guesstimate of how many pages we need to reclaim, and
> > > > you can follow the rest of your implementation as is (perhaps with
> > > > short-circuit when we reach the goal with fewer pages reclaimed).
> > >
> > > Got it. I will change it to use the compressed size in the next version.
> > >
> > > Yosry, Nhat, should we continue using the zswap_writeback_only key to
> > > trigger proactive writeback?
> >
> > I *really* want the memcg maintainers to chime in here, it's
> > ultimately their call.
> >
> > Michal? Johannes? Shakeel? Roman? Anyone? :D
>
> Between the options of having an explicit interface (i.e.
> memory.zswap.writeback*) or a key (i.e. zswap_writeback_only) to memory.reclaim
> interface, I prefer the key option. I have not looked into how much proactively
> reclaiming zswap memory or proactively triggering zswap writeback makes sense
> but from the perspective of memcg interface, I think the key option would give a
> more clean solution if we decide in the future that this whole thing was a bad
> idea.
>
> Next regarding future proofing zswap writeback trigger, do we expect any
> potential additions/changes/new-features for this interface? For example do we
> expect in future we may want to trigger the zswap writeback only from a specific
> node or lowest memory tier?
Youngjun is working on swap tiers. At the moment he is more interested in
allowing a specific swap device to a memcg or not. I can imagine in future there
will be use-cases where there will be a need to demote data on higher tier swap
to lower tier swap. What would be the appropriate interface?
BTW does zswap folks think of zswap as a top swap tier or something different?
^ permalink raw reply
* Re: [PATCH] cgroup/cpuset: Support multiple source/destination cpusets using pids pattern
From: Waiman Long @ 2026-06-08 18:49 UTC (permalink / raw)
To: Ridong Chen; +Cc: cgroups, Tejun Heo, Johannes Weiner, linux-kernel
In-Reply-To: <20260607031259.79541-1-ridong.chen@linux.dev>
On 6/6/26 11:12 PM, Ridong Chen wrote:
> When the cpuset controller is enabled/disabled in a parent cgroup, tasks
> from multiple child cpusets need to be migrated. The current code only
> handles a single source/destination pair.
>
> Support multiple source/destination cpusets by adopting the per-task
> processing pattern similar to the pids controller:
>
> 1) Perform per-task DL bandwidth reservation (dl_bw_alloc) directly in
> cpuset_can_attach() instead of batching into sum_migrate_dl_bw. This
> eliminates the sum_migrate_dl_bw and dl_bw_cpu fields from the cpuset
> struct.
>
> 2) Track attach_in_progress per-task per-destination cpuset to properly
> guard all involved cpusets from having their cpus/mems zeroed.
>
> 3) Use a shared cpuset_undo_attach() helper for both rollback-on-error
> in cpuset_can_attach() and for cpuset_cancel_attach().
>
> 4) Detect many-source migrations and force cpus_updated/mems_updated
> to true so all tasks get properly updated during attach.
>
> 5) Defer nr_deadline_tasks updates to cpuset_attach() (after migration
> is committed) to avoid a race with dl_rebuild_rd_accounting() that
> could see inconsistent values between can_attach and attach.
>
> Signed-off-by: Ridong Chen <ridong.chen@linux.dev>
> ---
> kernel/cgroup/cpuset-internal.h | 7 --
> kernel/cgroup/cpuset.c | 167 ++++++++++++++++----------------
> 2 files changed, 84 insertions(+), 90 deletions(-)
>
> diff --git a/kernel/cgroup/cpuset-internal.h b/kernel/cgroup/cpuset-internal.h
> index f7aaf01f7cd5..8f32cb97eb94 100644
> --- a/kernel/cgroup/cpuset-internal.h
> +++ b/kernel/cgroup/cpuset-internal.h
> @@ -167,13 +167,6 @@ struct cpuset {
> */
> int nr_deadline_tasks;
> int nr_migrate_dl_tasks;
> - /* DL bandwidth that needs destination reservation for this attach. */
> - u64 sum_migrate_dl_bw;
> - /*
> - * CPU used for temporary DL bandwidth allocation during attach;
> - * -1 if no DL bandwidth was allocated in the current attach.
> - */
> - int dl_bw_cpu;
>
> /* Invalid partition error code, not lock protected */
> enum prs_errcode prs_err;
> diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
> index e52a5a40d607..a6d96a39cdb1 100644
> --- a/kernel/cgroup/cpuset.c
> +++ b/kernel/cgroup/cpuset.c
> @@ -288,7 +288,6 @@ struct cpuset top_cpuset = {
> .flags = BIT(CS_CPU_EXCLUSIVE) |
> BIT(CS_MEM_EXCLUSIVE) | BIT(CS_SCHED_LOAD_BALANCE),
> .partition_root_state = PRS_ROOT,
> - .dl_bw_cpu = -1,
> };
>
> /**
> @@ -580,8 +579,6 @@ static struct cpuset *dup_or_alloc_cpuset(struct cpuset *cs)
> if (!trial)
> return NULL;
>
> - trial->dl_bw_cpu = -1;
> -
> /* Setup cpumask pointer array */
> cpumask_var_t *pmask[4] = {
> &trial->cpus_allowed,
> @@ -3026,31 +3023,36 @@ static int cpuset_can_attach_check(struct cpuset *cs, struct cpuset *oldcs,
> return 0;
> }
>
> -static int cpuset_reserve_dl_bw(struct cpuset *cs)
> +/*
> + * Undo DL bandwidth reservations and attach_in_progress increments done
> + * in cpuset_can_attach(). Used for both rollback on error and cancel_attach.
> + * If @stop_at is non-NULL, undo only for tasks before @stop_at in the tset.
> + */
> +static void cpuset_undo_attach(struct cgroup_taskset *tset,
> + struct task_struct *stop_at)
> {
> - int cpu, ret;
> -
> - if (!cs->sum_migrate_dl_bw)
> - return 0;
> + struct cgroup_subsys_state *css;
> + struct task_struct *task;
>
> - cpu = cpumask_any_and(cpu_active_mask, cs->effective_cpus);
> - if (unlikely(cpu >= nr_cpu_ids))
> - return -EINVAL;
> + cgroup_taskset_for_each(task, css, tset) {
> + struct cpuset *cs = css_cs(css);
>
> - ret = dl_bw_alloc(cpu, cs->sum_migrate_dl_bw);
> - if (ret)
> - return ret;
> + if (task == stop_at)
> + break;
>
> - cs->dl_bw_cpu = cpu;
> - return 0;
> + if (dl_task(task)) {
> + cs->nr_migrate_dl_tasks--;
> + if (dl_task_needs_bw_move(task, cs->effective_cpus)) {
> + int cpu = cpumask_any_and(cpu_active_mask,
> + cs->effective_cpus);
> + dl_bw_free(cpu, task->dl.dl_bw);
> + }
> + }
> + dec_attach_in_progress_locked(cs);
> + }
> }
>
> -static void reset_migrate_dl_data(struct cpuset *cs)
> -{
> - cs->nr_migrate_dl_tasks = 0;
> - cs->sum_migrate_dl_bw = 0;
> - cs->dl_bw_cpu = -1;
> -}
> +static bool attach_many_sources;
>
> /* Called by cgroups to determine if a cpuset is usable; cpuset_mutex held */
> static int cpuset_can_attach(struct cgroup_taskset *tset)
> @@ -3067,90 +3069,73 @@ static int cpuset_can_attach(struct cgroup_taskset *tset)
> cs = css_cs(css);
>
> mutex_lock(&cpuset_mutex);
> + attach_many_sources = false;
>
> /* Check to see if task is allowed in the cpuset */
> ret = cpuset_can_attach_check(cs, oldcs, &setsched_check);
> if (ret)
> goto out_unlock;
>
> - /*
> - * The cpuset_attach_old_cs is used mainly by cpuset_migrate_mm() to get
> - * the old_mems_allowed value. There are two ways that many-to-one
> - * cpuset migration can happen:
> - * 1) A multithread application with threads in different cpusets is
> - * wholely migrated to a new cpuset.
> - * 2) Disabling v2 cpuset controller will move all the tasks in child
> - * cpusets to the parent cpuset.
> - *
> - * In the former case, it is the mm setting of the group leader that
> - * really matters. So cpuset_attach_old_cs should track the oldcs of the
> - * group leader. It falls back to the oldcs of the first task if there
> - * is no group leader in the taskset. In the latter case, effective_mems
> - * of child cpusets must always be a subset of the parent. So no real
> - * page migration will be necessary no matter which child cpuset is
> - * selected as cpuset_attach_old_cs.
> - */
> cgroup_taskset_for_each(task, css, tset) {
> + struct cpuset *newcs = css_cs(css);
> + struct cpuset *new_oldcs = task_cs(task);
> +
> + if (newcs != cs || new_oldcs != oldcs) {
> + if (new_oldcs != oldcs)
> + attach_many_sources = true;
> + cs = newcs;
> + oldcs = new_oldcs;
> + ret = cpuset_can_attach_check(cs, oldcs,
> + &setsched_check);
> + if (ret)
> + goto out_rollback;
> + }
> +
> ret = task_can_attach(task);
> if (ret)
> - goto out_unlock;
> + goto out_rollback;
>
> - /* Update cpuset_attach_old_cs to the latest group leader */
> if (task == task->group_leader)
> cpuset_attach_old_cs = task_cs(task);
>
> if (setsched_check) {
> ret = security_task_setscheduler(task);
> if (ret)
> - goto out_unlock;
> + goto out_rollback;
> }
>
> if (dl_task(task)) {
> - /*
> - * Count all migrating DL tasks for cpuset task accounting.
> - * Only tasks that need a root-domain bandwidth move
> - * contribute to sum_migrate_dl_bw.
> - */
> cs->nr_migrate_dl_tasks++;
> - if (dl_task_needs_bw_move(task, cs->effective_cpus))
> - cs->sum_migrate_dl_bw += task->dl.dl_bw;
> + if (dl_task_needs_bw_move(task, cs->effective_cpus)) {
> + int cpu = cpumask_any_and(cpu_active_mask,
> + cs->effective_cpus);
> + if (unlikely(cpu >= nr_cpu_ids)) {
> + ret = -EINVAL;
> + goto out_rollback;
> + }
> + ret = dl_bw_alloc(cpu, task->dl.dl_bw);
> + if (ret)
> + goto out_rollback;
> + }
> }
> - }
> -
> - ret = cpuset_reserve_dl_bw(cs);
>
> -out_unlock:
> - if (ret) {
> - reset_migrate_dl_data(cs);
> - } else {
> - /*
> - * Mark attach is in progress. This makes validate_change() fail
> - * changes which zero cpus/mems_allowed.
> - */
> cs->attach_in_progress++;
> }
>
> + goto out_unlock;
> +
> +out_rollback:
> + cpuset_undo_attach(tset, task);
> +
> +out_unlock:
> mutex_unlock(&cpuset_mutex);
> return ret;
> }
>
> static void cpuset_cancel_attach(struct cgroup_taskset *tset)
> {
> - struct cgroup_subsys_state *css;
> - struct cpuset *cs;
> -
> - cgroup_taskset_first(tset, &css);
> - cs = css_cs(css);
> -
> mutex_lock(&cpuset_mutex);
> - dec_attach_in_progress_locked(cs);
> -
> - if (cs->dl_bw_cpu >= 0)
> - dl_bw_free(cs->dl_bw_cpu, cs->sum_migrate_dl_bw);
> -
> - if (cs->nr_migrate_dl_tasks)
> - reset_migrate_dl_data(cs);
> -
> + cpuset_undo_attach(tset, NULL);
> mutex_unlock(&cpuset_mutex);
> }
>
> @@ -3232,8 +3217,15 @@ static void cpuset_attach(struct cgroup_taskset *tset)
> mutex_lock(&cpuset_mutex);
> queue_task_work = false;
>
> - attach_cpus_updated = !cpumask_equal(cs->effective_cpus, oldcs->effective_cpus);
> - attach_mems_updated = !nodes_equal(cs->effective_mems, oldcs->effective_mems);
> + if (attach_many_sources) {
> + attach_cpus_updated = true;
> + attach_mems_updated = true;
> + } else {
> + attach_cpus_updated = !cpumask_equal(cs->effective_cpus,
> + oldcs->effective_cpus);
> + attach_mems_updated = !nodes_equal(cs->effective_mems,
> + oldcs->effective_mems);
> + }
>
> /*
> * In the default hierarchy, enabling cpuset in the child cgroups
> @@ -3250,20 +3242,29 @@ static void cpuset_attach(struct cgroup_taskset *tset)
> }
>
> cgroup_taskset_for_each(task, css, tset)
> - cpuset_attach_task(cs, task);
> + cpuset_attach_task(css_cs(css), task);
>
> out:
> if (queue_task_work)
> schedule_flush_migrate_mm();
> cs->old_mems_allowed = cpuset_attach_nodemask_to;
>
> - if (cs->nr_migrate_dl_tasks) {
> - cs->nr_deadline_tasks += cs->nr_migrate_dl_tasks;
> - oldcs->nr_deadline_tasks -= cs->nr_migrate_dl_tasks;
> - reset_migrate_dl_data(cs);
> - }
> + /*
> + * Update nr_deadline_tasks now that migration is committed.
> + * nr_migrate_dl_tasks was accumulated per-dst in can_attach but
> + * nr_deadline_tasks is deferred to here to avoid a race with
> + * dl_rebuild_rd_accounting() between can_attach and attach.
> + */
> + cgroup_taskset_for_each(task, css, tset) {
> + struct cpuset *dst_cs = css_cs(css);
>
> - dec_attach_in_progress_locked(cs);
> + if (dst_cs->nr_migrate_dl_tasks) {
> + dst_cs->nr_deadline_tasks += dst_cs->nr_migrate_dl_tasks;
> + oldcs->nr_deadline_tasks -= dst_cs->nr_migrate_dl_tasks;
> + dst_cs->nr_migrate_dl_tasks = 0;
> + }
> + dec_attach_in_progress_locked(dst_cs);
> + }
You are assuming that there is only one source cpuset. That may not be
true. I suppose that we may not track the set of destination cpusets and
they will be hit during task iteration. We will still need to track all
the source cpusets.
Cheers,
Longman
>
> mutex_unlock(&cpuset_mutex);
> }
^ permalink raw reply
* Re: [PATCH v3 2/4] mm/zswap: Implement proactive writeback
From: Shakeel Butt @ 2026-06-08 18:30 UTC (permalink / raw)
To: Yosry Ahmed
Cc: Hao Jia, Johannes Weiner, mhocko, tj, mkoutny, roman.gushchin,
Nhat Pham, akpm, chengming.zhou, muchun.song, cgroups, linux-mm,
linux-kernel, linux-doc, Hao Jia
In-Reply-To: <CAO9r8zM4SDdTgz9L2s1VfXL8K2VBjMD9ej2BTDxaGge1t2+quA@mail.gmail.com>
On Wed, Jun 03, 2026 at 10:36:07PM -0700, Yosry Ahmed wrote:
> > >> But doesn't it make more sense to specify the compressed size, which is
> > >> ultimately the amount of memory you actually want to reclaim.
> > >>
> > >
> > > I personally prefer compressed size to pre-compressed size. That's
> > > kinda what user cares about, no?
> > >
> > > One thing we can do is let users prescribe a compressed size, but
> > > internally, we can multiply that by the average compression ratio.
> > > That gives us a guesstimate of how many pages we need to reclaim, and
> > > you can follow the rest of your implementation as is (perhaps with
> > > short-circuit when we reach the goal with fewer pages reclaimed).
> >
> > Got it. I will change it to use the compressed size in the next version.
> >
> > Yosry, Nhat, should we continue using the zswap_writeback_only key to
> > trigger proactive writeback?
>
> I *really* want the memcg maintainers to chime in here, it's
> ultimately their call.
>
> Michal? Johannes? Shakeel? Roman? Anyone? :D
Between the options of having an explicit interface (i.e.
memory.zswap.writeback*) or a key (i.e. zswap_writeback_only) to memory.reclaim
interface, I prefer the key option. I have not looked into how much proactively
reclaiming zswap memory or proactively triggering zswap writeback makes sense
but from the perspective of memcg interface, I think the key option would give a
more clean solution if we decide in the future that this whole thing was a bad
idea.
Next regarding future proofing zswap writeback trigger, do we expect any
potential additions/changes/new-features for this interface? For example do we
expect in future we may want to trigger the zswap writeback only from a specific
node or lowest memory tier?
^ permalink raw reply
* Re: [PATCH v3 1/4] mm/zswap: Make shrink_worker writeback cursor per-memcg
From: Nhat Pham @ 2026-06-08 18:01 UTC (permalink / raw)
To: Yosry Ahmed
Cc: Hao Jia, akpm, tj, hannes, shakeel.butt, mhocko, mkoutny,
chengming.zhou, muchun.song, roman.gushchin, cgroups, linux-mm,
linux-kernel, linux-doc, Hao Jia
In-Reply-To: <CAO9r8zN6VVZz7dpjNrh8n7wbLkqcrsROPm70MQQxO49HJSmMFw@mail.gmail.com>
On Mon, Jun 8, 2026 at 9:48 AM Yosry Ahmed <yosry@kernel.org> wrote:
>
> > But OTOH, this does seem like a recipe for inefficient reclaim. We
> > might exhaust hotter memory of a cgroup while sparing colder memory of
> > another cgroup... But maybe if they're all cold anyway, then who
> > cares, and eventually you'll get to the cold stuff of other child?
>
> Forgot to respond to this part, the unfairness is limited to the batch
> size per-invocation, so it should be fine as long as you don't divide
> the amount over 100 iterations for some reason. Also yes, all memory
> in zswap is cold, the relative coldness is not that important (e.g.
> compared to relative coldness during reclaim).
Ok then yeah, I think we should shelve per-memcg cursor for the next
version. Down the line, if we have more data that unfairness is an
issue, we can always fix it. One step at a time :)
^ permalink raw reply
* Re: [PATCH v2] cgroup/dmem: accept only one region per limit write
From: Natalie Vock @ 2026-06-08 16:51 UTC (permalink / raw)
To: Eric Chanudet, Maarten Lankhorst, Maxime Ripard, Tejun Heo,
Johannes Weiner, Michal Koutný
Cc: cgroups, dri-devel, linux-kernel, Albert Esteve
In-Reply-To: <20260608-cgroup-dmem-write-single-region-v2-1-b0cd6c4ccf1b@redhat.com>
On 6/8/26 17:53, Eric Chanudet wrote:
> Accept only one "region value" pair entry for the dmem.max, dmem.min,
> dmem.low files.
>
> This changes the UAPI that otherwise accepted multiple lines for setting
> multiple entries in one write. No existing user is known to rely on
> writing multiple regions in a single write.
>
> Processing multiple regions in dmemcg_limit_write() could quietly change
> first limits before failing on a later one and returning an error to the
> writer, with no indication some changes occurred.
>
> Acked-by: Tejun Heo <tj@kernel.org>
> Signed-off-by: Eric Chanudet <echanude@redhat.com>
Reviewed-by: Natalie Vock <natalie.vock@gmx.de>
Thanks,
Natalie
^ permalink raw reply
* Re: [PATCH v3 1/4] mm/zswap: Make shrink_worker writeback cursor per-memcg
From: Yosry Ahmed @ 2026-06-08 16:48 UTC (permalink / raw)
To: Nhat Pham
Cc: Hao Jia, akpm, tj, hannes, shakeel.butt, mhocko, mkoutny,
chengming.zhou, muchun.song, roman.gushchin, cgroups, linux-mm,
linux-kernel, linux-doc, Hao Jia
In-Reply-To: <CAKEwX=PF9hfERC_QMq+rjkSc-BsJyawMgTe+EhwR_86HiQKm=Q@mail.gmail.com>
> But OTOH, this does seem like a recipe for inefficient reclaim. We
> might exhaust hotter memory of a cgroup while sparing colder memory of
> another cgroup... But maybe if they're all cold anyway, then who
> cares, and eventually you'll get to the cold stuff of other child?
Forgot to respond to this part, the unfairness is limited to the batch
size per-invocation, so it should be fine as long as you don't divide
the amount over 100 iterations for some reason. Also yes, all memory
in zswap is cold, the relative coldness is not that important (e.g.
compared to relative coldness during reclaim).
^ permalink raw reply
* Re: [PATCH v3 1/4] mm/zswap: Make shrink_worker writeback cursor per-memcg
From: Yosry Ahmed @ 2026-06-08 16:44 UTC (permalink / raw)
To: Nhat Pham
Cc: Hao Jia, akpm, tj, hannes, shakeel.butt, mhocko, mkoutny,
chengming.zhou, muchun.song, roman.gushchin, cgroups, linux-mm,
linux-kernel, linux-doc, Hao Jia
In-Reply-To: <CAKEwX=PF9hfERC_QMq+rjkSc-BsJyawMgTe+EhwR_86HiQKm=Q@mail.gmail.com>
On Mon, Jun 8, 2026 at 9:23 AM Nhat Pham <nphamcs@gmail.com> wrote:
>
> On Mon, Jun 8, 2026 at 5:50 AM Hao Jia <jiahao.kernel@gmail.com> wrote:
> > On 2026/6/5 01:23, Nhat Pham wrote:
> > >
> >
> > Thanks for the suggestion!
> >
> > I ran some tests and found that neither the per-memcg cursor nor
> > different batch sizes have a significant impact on proactive writeback
> > performance. However, exactly as we suspected, without the per-memcg
> > cursor, the writeback distribution among child memcgs is highly unfair.
> >
> > Test Setup:
> >
> > zswap config: 18G capacity, LZ4 compression.
> > cgroup hierarchy: 1 parent test memcg with 10 child memcgs.
> > Allocation: Allocated 1600MB of anonymous pages in each child memcg.
> > To ensure compressibility, the first half of each page was filled with
> > random data and the second half with zeros.
> > Force to zswap: Ran echo "1600M" > memory.reclaim on each child memcg
> > to squeeze all their memory into zswap.
> > Trigger writeback: Ran echo "<size> zswap_writeback_only" >
> > memory.reclaim on the parent cgroup 200 times, with a 2-second interval
> > between each run.
> > Metric: Monitored the zswpwb_proactive metric in memory.stat to
> > observe the writeback volume.
> > **Note**: The size here refers to the uncompressed memory size. Also,
> > since the second-chance algorithm would cause many writebacks to fall
> > short of the target size, I **bypassed** it during these tests to avoid
> > interference.
> >
> > Without cursor (size: 1M, batch: 32)
> > child wb_pages wb_MB share%
> > child0 6368 24.88 12.50
> > child1 6368 24.88 12.50
> > child2 6368 24.88 12.50
> > child3 6368 24.88 12.50
> > child4 6368 24.88 12.50
> > child5 6368 24.88 12.50
> > child6 6368 24.88 12.50
> > child7 6368 24.88 12.50
> > child8 0 0.00 0.00
> > child9 0 0.00 0.00
> > Without cursor (size: 1M, batch: 128)
> > child wb_pages wb_MB share%
> > child0 25472 99.50 50.00
> > child1 25472 99.50 50.00
> > child2 0 0.00 0.00
> > child3 0 0.00 0.00
> > child4 0 0.00 0.00
> > child5 0 0.00 0.00
> > child6 0 0.00 0.00
> > child7 0 0.00 0.00
> > child8 0 0.00 0.00
> > child9 0 0.00 0.00
> > Without cursor (size: 6M, batch: 128)
> > child wb_pages wb_MB share%
> > child0 51200 200.00 16.67
> > child1 51200 200.00 16.67
> > child2 25600 100.00 8.33
> > child3 25600 100.00 8.33
> > child4 25600 100.00 8.33
> > child5 25600 100.00 8.33
> > child6 25600 100.00 8.33
> > child7 25600 100.00 8.33
> > child8 25600 100.00 8.33
> > child9 25600 100.00 8.33
> >
> >
> > With cursor (size: 1M, batch: 32)
> > child wb_pages wb_MB share%
> > child0 5120 20.00 10.00
> > child1 5120 20.00 10.00
> > child2 5120 20.00 10.00
> > child3 5120 20.00 10.00
> > child4 5120 20.00 10.00
> > child5 5120 20.00 10.00
> > child6 5120 20.00 10.00
> > child7 5120 20.00 10.00
> > child8 5120 20.00 10.00
> > child9 5120 20.00 10.00
> > With cursor (size: 1M, batch: 128)
> > child wb_pages wb_MB share%
> > child0 5120 20.00 10.00
> > child1 5120 20.00 10.00
> > child2 5120 20.00 10.00
> > child3 5120 20.00 10.00
> > child4 5120 20.00 10.00
> > child5 5120 20.00 10.00
> > child6 5120 20.00 10.00
> > child7 5120 20.00 10.00
> > child8 5120 20.00 10.00
> > child9 5120 20.00 10.00
Yes, the per-memcg cursor is more fair, and you can synthesize
scenarios that show that. However, I don't think this is a problem in
practice:
1. The unfairness is limited to the batch size per-invocation. If the
batch size is 128 pages (your highest one here), that's 0.5 MB (on
x86), which is fairly low? If the batch size is 32, it's even less.
2. Realistically, if you have a parent cgroup with with >10G of
memory, you wouldn't be reclaiming in steps of 1M. If you want to
reclaim 200MB, why are you doing it over 200 invocations? If you do it
in a single one (or over a few retries) the shares should become much
more even.
We're trying to fix a practical use case, not finding reasons why a
simple implementation won't work -- right?
More below (to Nhat's point).
>
> Yeah OTOH, we don't really make fairness an API contract here. When
> you set up a proactive reclaim scheme, if you decide to target a
> cgroup (and not its children separately), everything underneath it is
> fair game to the kernel in any split that we fancy. If you want true
> fairness or a desired split, you have to treat them as independent
> memory domains and set up proactive reclaim to hit each child cgroup
> separately (i.e one "echo > memory.reclaim" for each of them). This is
> necessary for example if each child represents a separate, isolated
> service/container/tenant. And maybe this is actually what you really
> want - hit the ancestor cgroup very lightly for the stuff it owns, but
> then dedidcate most of the reclaim effort at the leaf cgroups
> independently?
I would go a bit farther and claim that ideally fairness shouldn't
even be a factor. If you invoke proactive reclaim on a parent cgroup
with 100MB, you want to reclaim the coldest 100MB in that parent, no
matter what child they reside in. If one child cgroup has 100% hot
memory and one child cgroup has 100% cold memory, ideally you'd
reclaim all the cold memory from the second child.
However, the implementation of the LRUs and the coldness tracking
doesn't allow for doing this, so we "fallback" to reclaiming in
batches from each child because we don't really know where the coldest
pages overall are. If that changes in the future (somehow), I argue
that the correct thing to do is reclaim the absolute coldest memory at
the parent level.
If you want to reclaim evenly among the children, you can do that and
directly reclaim from the children.
>
> But OTOH, this does seem like a recipe for inefficient reclaim. We
> might exhaust hotter memory of a cgroup while sparing colder memory of
> another cgroup... But maybe if they're all cold anyway, then who
> cares, and eventually you'll get to the cold stuff of other child?
>
> Yosry, what's the concern here? Is it space overhead, or overall code
> complexity?
Mostly the complexity (e.g. the zombie memcg cleanup) and a tiny bit
the unnecessary space (8 bytes is not a lot, but these things add up).
^ permalink raw reply
* Re: [PATCH v2] cgroup/dmem: accept only one region per limit write
From: Maxime Ripard @ 2026-06-08 16:37 UTC (permalink / raw)
To: Eric Chanudet
Cc: cgroups, dri-devel, linux-kernel, Albert Esteve, Johannes Weiner,
Maarten Lankhorst, Maxime Ripard, Michal Koutný,
Natalie Vock, Tejun Heo
In-Reply-To: <20260608-cgroup-dmem-write-single-region-v2-1-b0cd6c4ccf1b@redhat.com>
On Mon, 8 Jun 2026 11:53:51 -0400, Eric Chanudet wrote:
> Accept only one "region value" pair entry for the dmem.max, dmem.min,
> dmem.low files.
>
> This changes the UAPI that otherwise accepted multiple lines for setting
> multiple entries in one write. No existing user is known to rely on
>
> [ ... ]
Reviewed-by: Maxime Ripard <mripard@kernel.org>
Thanks!
Maxime
^ permalink raw reply
* Re: [PATCH v3 1/4] mm/zswap: Make shrink_worker writeback cursor per-memcg
From: Nhat Pham @ 2026-06-08 16:23 UTC (permalink / raw)
To: Hao Jia
Cc: Yosry Ahmed, akpm, tj, hannes, shakeel.butt, mhocko, mkoutny,
chengming.zhou, muchun.song, roman.gushchin, cgroups, linux-mm,
linux-kernel, linux-doc, Hao Jia
In-Reply-To: <90730fa7-62e7-d5f4-b638-23b22a8509f2@gmail.com>
On Mon, Jun 8, 2026 at 5:50 AM Hao Jia <jiahao.kernel@gmail.com> wrote:
> On 2026/6/5 01:23, Nhat Pham wrote:
> >
>
> Thanks for the suggestion!
>
> I ran some tests and found that neither the per-memcg cursor nor
> different batch sizes have a significant impact on proactive writeback
> performance. However, exactly as we suspected, without the per-memcg
> cursor, the writeback distribution among child memcgs is highly unfair.
>
> Test Setup:
>
> zswap config: 18G capacity, LZ4 compression.
> cgroup hierarchy: 1 parent test memcg with 10 child memcgs.
> Allocation: Allocated 1600MB of anonymous pages in each child memcg.
> To ensure compressibility, the first half of each page was filled with
> random data and the second half with zeros.
> Force to zswap: Ran echo "1600M" > memory.reclaim on each child memcg
> to squeeze all their memory into zswap.
> Trigger writeback: Ran echo "<size> zswap_writeback_only" >
> memory.reclaim on the parent cgroup 200 times, with a 2-second interval
> between each run.
> Metric: Monitored the zswpwb_proactive metric in memory.stat to
> observe the writeback volume.
> **Note**: The size here refers to the uncompressed memory size. Also,
> since the second-chance algorithm would cause many writebacks to fall
> short of the target size, I **bypassed** it during these tests to avoid
> interference.
>
> Without cursor (size: 1M, batch: 32)
> child wb_pages wb_MB share%
> child0 6368 24.88 12.50
> child1 6368 24.88 12.50
> child2 6368 24.88 12.50
> child3 6368 24.88 12.50
> child4 6368 24.88 12.50
> child5 6368 24.88 12.50
> child6 6368 24.88 12.50
> child7 6368 24.88 12.50
> child8 0 0.00 0.00
> child9 0 0.00 0.00
> Without cursor (size: 1M, batch: 128)
> child wb_pages wb_MB share%
> child0 25472 99.50 50.00
> child1 25472 99.50 50.00
> child2 0 0.00 0.00
> child3 0 0.00 0.00
> child4 0 0.00 0.00
> child5 0 0.00 0.00
> child6 0 0.00 0.00
> child7 0 0.00 0.00
> child8 0 0.00 0.00
> child9 0 0.00 0.00
> Without cursor (size: 6M, batch: 128)
> child wb_pages wb_MB share%
> child0 51200 200.00 16.67
> child1 51200 200.00 16.67
> child2 25600 100.00 8.33
> child3 25600 100.00 8.33
> child4 25600 100.00 8.33
> child5 25600 100.00 8.33
> child6 25600 100.00 8.33
> child7 25600 100.00 8.33
> child8 25600 100.00 8.33
> child9 25600 100.00 8.33
>
>
> With cursor (size: 1M, batch: 32)
> child wb_pages wb_MB share%
> child0 5120 20.00 10.00
> child1 5120 20.00 10.00
> child2 5120 20.00 10.00
> child3 5120 20.00 10.00
> child4 5120 20.00 10.00
> child5 5120 20.00 10.00
> child6 5120 20.00 10.00
> child7 5120 20.00 10.00
> child8 5120 20.00 10.00
> child9 5120 20.00 10.00
> With cursor (size: 1M, batch: 128)
> child wb_pages wb_MB share%
> child0 5120 20.00 10.00
> child1 5120 20.00 10.00
> child2 5120 20.00 10.00
> child3 5120 20.00 10.00
> child4 5120 20.00 10.00
> child5 5120 20.00 10.00
> child6 5120 20.00 10.00
> child7 5120 20.00 10.00
> child8 5120 20.00 10.00
> child9 5120 20.00 10.00
>
Yeah OTOH, we don't really make fairness an API contract here. When
you set up a proactive reclaim scheme, if you decide to target a
cgroup (and not its children separately), everything underneath it is
fair game to the kernel in any split that we fancy. If you want true
fairness or a desired split, you have to treat them as independent
memory domains and set up proactive reclaim to hit each child cgroup
separately (i.e one "echo > memory.reclaim" for each of them). This is
necessary for example if each child represents a separate, isolated
service/container/tenant. And maybe this is actually what you really
want - hit the ancestor cgroup very lightly for the stuff it owns, but
then dedidcate most of the reclaim effort at the leaf cgroups
independently?
But OTOH, this does seem like a recipe for inefficient reclaim. We
might exhaust hotter memory of a cgroup while sparing colder memory of
another cgroup... But maybe if they're all cold anyway, then who
cares, and eventually you'll get to the cold stuff of other child?
Yosry, what's the concern here? Is it space overhead, or overall code
complexity?
^ permalink raw reply
* [PATCH v2] cgroup/dmem: accept only one region per limit write
From: Eric Chanudet @ 2026-06-08 15:53 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Natalie Vock, Tejun Heo,
Johannes Weiner, Michal Koutný
Cc: cgroups, dri-devel, linux-kernel, Albert Esteve, Eric Chanudet
Accept only one "region value" pair entry for the dmem.max, dmem.min,
dmem.low files.
This changes the UAPI that otherwise accepted multiple lines for setting
multiple entries in one write. No existing user is known to rely on
writing multiple regions in a single write.
Processing multiple regions in dmemcg_limit_write() could quietly change
first limits before failing on a later one and returning an error to the
writer, with no indication some changes occurred.
Acked-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Eric Chanudet <echanude@redhat.com>
---
Follow up from discussions on a previous thread[1].
If Albert's series[2] lands, I can cleanup and prepare some kunits for
these as well.
[1] https://lore.kernel.org/all/158bc103-7f99-4df4-8d3b-2da9b04ac0ed@lankhorst.se/
[2] https://lore.kernel.org/all/20260519-kunit_cgroups-v4-1-f6c2f498fae4@redhat.com/
---
Changes in v2:
- Handle buf == NULL by testing !buf first after strsep (Natalie)
- Don't allow extra spaces to separate key and value (Natalie)
Other cgroup files don't (rdma, misc), so stay consistent.
- Link to v1: https://lore.kernel.org/r/20260605-cgroup-dmem-write-single-region-v1-1-9137f296579c@redhat.com
---
kernel/cgroup/dmem.c | 69 +++++++++++++++++++---------------------------------
1 file changed, 25 insertions(+), 44 deletions(-)
diff --git a/kernel/cgroup/dmem.c b/kernel/cgroup/dmem.c
index 6430c7ce1e0372f59f1313163fb7630ce49ac1ef..39930c59cb769a505a5852a5644a371fd5596f59 100644
--- a/kernel/cgroup/dmem.c
+++ b/kernel/cgroup/dmem.c
@@ -734,57 +734,38 @@ static ssize_t dmemcg_limit_write(struct kernfs_open_file *of,
void (*apply)(struct dmem_cgroup_pool_state *, u64))
{
struct dmemcg_state *dmemcs = css_to_dmemcs(of_css(of));
- int err = 0;
-
- while (buf && !err) {
- struct dmem_cgroup_pool_state *pool = NULL;
- char *options, *region_name;
- struct dmem_cgroup_region *region;
- u64 new_limit;
-
- options = buf;
- buf = strchr(buf, '\n');
- if (buf)
- *buf++ = '\0';
-
- options = strstrip(options);
-
- /* eat empty lines */
- if (!options[0])
- continue;
-
- region_name = strsep(&options, " \t");
- if (!region_name[0])
- continue;
-
- if (!options || !*options)
- return -EINVAL;
+ struct dmem_cgroup_pool_state *pool;
+ struct dmem_cgroup_region *region;
+ char *region_name;
+ u64 new_limit;
+ int err;
- rcu_read_lock();
- region = dmemcg_get_region_by_name(region_name);
- rcu_read_unlock();
+ buf = strstrip(buf);
+ region_name = strsep(&buf, " \t");
+ if (!buf || !region_name[0])
+ return -EINVAL;
- if (!region)
- return -EINVAL;
+ rcu_read_lock();
+ region = dmemcg_get_region_by_name(region_name);
+ rcu_read_unlock();
+ if (!region)
+ return -EINVAL;
- err = dmemcg_parse_limit(options, &new_limit);
- if (err < 0)
- goto out_put;
+ err = dmemcg_parse_limit(buf, &new_limit);
+ if (err < 0)
+ goto out_put;
- pool = get_cg_pool_unlocked(dmemcs, region);
- if (IS_ERR(pool)) {
- err = PTR_ERR(pool);
- goto out_put;
- }
+ pool = get_cg_pool_unlocked(dmemcs, region);
+ if (IS_ERR(pool)) {
+ err = PTR_ERR(pool);
+ goto out_put;
+ }
- /* And commit */
- apply(pool, new_limit);
- dmemcg_pool_put(pool);
+ apply(pool, new_limit);
+ dmemcg_pool_put(pool);
out_put:
- kref_put(®ion->ref, dmemcg_free_region);
- }
-
+ kref_put(®ion->ref, dmemcg_free_region);
return err ?: nbytes;
}
---
base-commit: 640c57d6ca1346a1c2363a3f473b405af979e046
change-id: 20260605-cgroup-dmem-write-single-region-9bf05b6d995d
Best regards,
--
Eric Chanudet <echanude@redhat.com>
^ permalink raw reply related
* Re: [PATCH] cgroup/dmem: accept only one region per limit write
From: Maarten Lankhorst @ 2026-06-08 15:42 UTC (permalink / raw)
To: Maxime Ripard
Cc: Natalie Vock, Eric Chanudet, Tejun Heo, Johannes Weiner,
Michal Koutný, cgroups, dri-devel, linux-kernel,
Albert Esteve
In-Reply-To: <20260608-rational-cuscus-of-enhancement-eecbfa@houat>
Hello,
On 6/8/26 16:04, Maxime Ripard wrote:
> On Mon, Jun 08, 2026 at 03:13:56PM +0200, Maarten Lankhorst wrote:
>> Hey,
>>
>> On 6/8/26 14:42, Maxime Ripard wrote:
>>> On Sat, Jun 06, 2026 at 11:44:10PM +0200, Maarten Lankhorst wrote:
>>>> Hey,
>>>>
>>>> On 6/6/26 18:31, Natalie Vock wrote:
>>>>> On 6/6/26 00:44, Eric Chanudet wrote:
>>>>>> Accept only one "region value" pair entry for the dmem.max, dmem.min,
>>>>>> dmem.low files.>
>>>>>> This changes the UAPI that otherwise accepted multiple lines for setting
>>>>>> multiple entries in one write. No existing user is known to rely on
>>>>>> writing multiple regions in a single write.
>>>>>
>>>>> Ugh, shoot.
>>>>>
>>>>> For dmem.low specifically, there already are some userspace thingies floating around that may write more than one region/value pairs.
>>>>>
>>>>> These thingies all depend on that one patchset for dmemcg protection that I should really get around to merging[1]. Since the userspace utilities depend on not-yet-merged patches, they sort of have to expect stuff changing under their belts, so I wouldn't really consider those users a blocker by necessity.
>>>>>
>>>>> As I see it, we could go down one of two paths:
>>>>> 1. We go ahead with the patch as proposed, and I make sure that the users I know of adapt. Could be a bit icky wrt. "do not break userspace" rules, but since the already use non-merged UAPIs in one place, you can argue that these users kind of have to expect breakage.
>>>>> 2. We use the old handling allowing multiple lines for dmem.min and dmem.low only. This preserves compatibility but uglifies the code by quite a bit.
>>>>>
>>>>> All things considered, I think I personally would prefer going with 1. and taking the patch as proposed and just having one codepath handling every limit file. Just highlighting this so we don't do it on accident.
>>>>>
>>>>> [1] https://patchwork.freedesktop.org/series/163183/
>>>>>
>>>>
>>>> I prefer option 1 as well, but would like an ack from one of the core cgroup maintainers too,
>>>> and what Maxime's opinion on this as well.
>>>
>>> Option 1 works for me too if doable
>>>
>>> Maxime
>>
>>
>> I see this as an acked-by?
>>
>> I'll commit this patch to drm-misc-next if so.
>>
>> Fortunately it may not even break those scripts in the typical case
>> where only 1 region is registered, eg the most common laptop/desktop
>> case.
>
> Natalie had a bunch of comments afaik, so I was expecting a v2, but if
> you intend to merge it as is, you can add it if you want.
Yeah forgot about that for a second, will wait for v2!
Kind regards,
~Maarten Lankhorst
^ permalink raw reply
* Re: [PATCH] cgroup/dmem: accept only one region per limit write
From: Maxime Ripard @ 2026-06-08 14:04 UTC (permalink / raw)
To: Maarten Lankhorst
Cc: Natalie Vock, Eric Chanudet, Tejun Heo, Johannes Weiner,
Michal Koutný, cgroups, dri-devel, linux-kernel,
Albert Esteve
In-Reply-To: <15bab7c9-0857-40b9-963b-9923c0e7392c@lankhorst.se>
[-- Attachment #1: Type: text/plain, Size: 2514 bytes --]
On Mon, Jun 08, 2026 at 03:13:56PM +0200, Maarten Lankhorst wrote:
> Hey,
>
> On 6/8/26 14:42, Maxime Ripard wrote:
> > On Sat, Jun 06, 2026 at 11:44:10PM +0200, Maarten Lankhorst wrote:
> >> Hey,
> >>
> >> On 6/6/26 18:31, Natalie Vock wrote:
> >>> On 6/6/26 00:44, Eric Chanudet wrote:
> >>>> Accept only one "region value" pair entry for the dmem.max, dmem.min,
> >>>> dmem.low files.>
> >>>> This changes the UAPI that otherwise accepted multiple lines for setting
> >>>> multiple entries in one write. No existing user is known to rely on
> >>>> writing multiple regions in a single write.
> >>>
> >>> Ugh, shoot.
> >>>
> >>> For dmem.low specifically, there already are some userspace thingies floating around that may write more than one region/value pairs.
> >>>
> >>> These thingies all depend on that one patchset for dmemcg protection that I should really get around to merging[1]. Since the userspace utilities depend on not-yet-merged patches, they sort of have to expect stuff changing under their belts, so I wouldn't really consider those users a blocker by necessity.
> >>>
> >>> As I see it, we could go down one of two paths:
> >>> 1. We go ahead with the patch as proposed, and I make sure that the users I know of adapt. Could be a bit icky wrt. "do not break userspace" rules, but since the already use non-merged UAPIs in one place, you can argue that these users kind of have to expect breakage.
> >>> 2. We use the old handling allowing multiple lines for dmem.min and dmem.low only. This preserves compatibility but uglifies the code by quite a bit.
> >>>
> >>> All things considered, I think I personally would prefer going with 1. and taking the patch as proposed and just having one codepath handling every limit file. Just highlighting this so we don't do it on accident.
> >>>
> >>> [1] https://patchwork.freedesktop.org/series/163183/
> >>>
> >>
> >> I prefer option 1 as well, but would like an ack from one of the core cgroup maintainers too,
> >> and what Maxime's opinion on this as well.
> >
> > Option 1 works for me too if doable
> >
> > Maxime
>
>
> I see this as an acked-by?
>
> I'll commit this patch to drm-misc-next if so.
>
> Fortunately it may not even break those scripts in the typical case
> where only 1 region is registered, eg the most common laptop/desktop
> case.
Natalie had a bunch of comments afaik, so I was expecting a v2, but if
you intend to merge it as is, you can add it if you want.
Maxime
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 273 bytes --]
^ permalink raw reply
* Re: [PATCH] cgroup/dmem: accept only one region per limit write
From: Eric Chanudet @ 2026-06-08 13:30 UTC (permalink / raw)
To: Natalie Vock
Cc: Maarten Lankhorst, Maxime Ripard, Tejun Heo, Johannes Weiner,
Michal Koutný, cgroups, dri-devel, linux-kernel,
Albert Esteve
In-Reply-To: <271b1c16-3c3c-4a1e-b09e-c4361c63814c@gmx.de>
On Sat, Jun 06, 2026 at 06:31:53PM +0200, Natalie Vock wrote:
> On 6/6/26 00:44, Eric Chanudet wrote:
> > Accept only one "region value" pair entry for the dmem.max, dmem.min,
> > dmem.low files.>
> > This changes the UAPI that otherwise accepted multiple lines for setting
> > multiple entries in one write. No existing user is known to rely on
> > writing multiple regions in a single write.
>
> Ugh, shoot.
>
> For dmem.low specifically, there already are some userspace thingies
> floating around that may write more than one region/value pairs.
>
> These thingies all depend on that one patchset for dmemcg protection that I
> should really get around to merging[1]. Since the userspace utilities depend
> on not-yet-merged patches, they sort of have to expect stuff changing under
> their belts, so I wouldn't really consider those users a blocker by
> necessity.
>
> As I see it, we could go down one of two paths:
> 1. We go ahead with the patch as proposed, and I make sure that the users I
> know of adapt. Could be a bit icky wrt. "do not break userspace" rules, but
> since the already use non-merged UAPIs in one place, you can argue that
> these users kind of have to expect breakage.
> 2. We use the old handling allowing multiple lines for dmem.min and dmem.low
> only. This preserves compatibility but uglifies the code by quite a bit.
>
> All things considered, I think I personally would prefer going with 1. and
> taking the patch as proposed and just having one codepath handling every
> limit file. Just highlighting this so we don't do it on accident.
>
> [1] https://patchwork.freedesktop.org/series/163183/
>
> Some more review comments inline.
>
> >
> > Processing multiple regions in dmemcg_limit_write() could quietly change
> > first limits before failing on a later one and returning an error to the
> > writer, with no indication some changes occurred.
> >
> > Signed-off-by: Eric Chanudet <echanude@redhat.com>
> > ---
> > Follow up from discussions on a previous thread[1].
> > If Albert's series[2] lands, I can cleanup and prepare some kunits for
> > these as well.
> > [1] https://lore.kernel.org/all/158bc103-7f99-4df4-8d3b-2da9b04ac0ed@lankhorst.se/
> > [2] https://lore.kernel.org/all/20260519-kunit_cgroups-v4-1-f6c2f498fae4@redhat.com/
> > ---
> > kernel/cgroup/dmem.c | 70 +++++++++++++++++++---------------------------------
> > 1 file changed, 26 insertions(+), 44 deletions(-)
> >
> > diff --git a/kernel/cgroup/dmem.c b/kernel/cgroup/dmem.c
> > index 6430c7ce1e0372f59f1313163fb7630ce49ac1ef..113ee88e276296bccb4def546adf5cc175d7f0be 100644
> > --- a/kernel/cgroup/dmem.c
> > +++ b/kernel/cgroup/dmem.c
> > @@ -734,57 +734,39 @@ static ssize_t dmemcg_limit_write(struct kernfs_open_file *of,
> > void (*apply)(struct dmem_cgroup_pool_state *, u64))
> > {
> > struct dmemcg_state *dmemcs = css_to_dmemcs(of_css(of));
> > - int err = 0;
> > -
> > - while (buf && !err) {
> > - struct dmem_cgroup_pool_state *pool = NULL;
> > - char *options, *region_name;
> > - struct dmem_cgroup_region *region;
> > - u64 new_limit;
> > -
> > - options = buf;
> > - buf = strchr(buf, '\n');
> > - if (buf)
> > - *buf++ = '\0';
> > -
> > - options = strstrip(options);
> > -
> > - /* eat empty lines */
> > - if (!options[0])
> > - continue;
> > -
> > - region_name = strsep(&options, " \t");
> > - if (!region_name[0])
> > - continue;
> > -
> > - if (!options || !*options)
> > - return -EINVAL;
> > + struct dmem_cgroup_pool_state *pool;
> > + struct dmem_cgroup_region *region;
> > + char *region_name;
> > + u64 new_limit;
> > + int err;
> > - rcu_read_lock();
> > - region = dmemcg_get_region_by_name(region_name);
> > - rcu_read_unlock();
> > + buf = strstrip(buf);
> > + region_name = strsep(&buf, " \t");
> > + if (!region_name[0] || !buf)
>
> If buf is NULL, isn't strsep(&buf, ...) also NULL? region_name[0] would
> therefore be a NULL pointer deref. Flipping the order of the logical or
> should be enough to prevent this.
>
I can do a v2 with that today.
I added it if there are no delimiter found (e.g, if only the region name
is passed and strstrip() ate any trailing space). Although, buf can't be
NULL in the write callback iirc, it's either pre-allocated or
kmalloc'ed.
> > + return -EINVAL;
> > - if (!region)
> > - return -EINVAL;
> > + rcu_read_lock();
> > + region = dmemcg_get_region_by_name(region_name);
> > + rcu_read_unlock();
> > + if (!region)
> > + return -EINVAL;
> > - err = dmemcg_parse_limit(options, &new_limit);
> > - if (err < 0)
> > - goto out_put;
> > + buf = strstrip(buf);
>
> Do we start allowing extra spaces between region and limit as well? Would
> also be fine by me, it doesn't break anything, just highlighting that it's a
> change in behavior. Should perhaps be documented in the commit message, too.
>
> Also, you should be able to use skip_spaces() here for an equivalent result.
> I'm not strongly opinionated on either way, but using skip_spaces()
> indicates more clearly that this can only remove spaces at the start.
Same I can add to v2, I failed to notice it wasn't allowed in the
original logic.
Thank you for the review.
Best,
>
> Best,
> Natalie
>
> > + err = dmemcg_parse_limit(buf, &new_limit);
> > + if (err < 0)
> > + goto out_put;
> > - pool = get_cg_pool_unlocked(dmemcs, region);
> > - if (IS_ERR(pool)) {
> > - err = PTR_ERR(pool);
> > - goto out_put;
> > - }
> > + pool = get_cg_pool_unlocked(dmemcs, region);
> > + if (IS_ERR(pool)) {
> > + err = PTR_ERR(pool);
> > + goto out_put;
> > + }
> > - /* And commit */
> > - apply(pool, new_limit);
> > - dmemcg_pool_put(pool);
> > + apply(pool, new_limit);
> > + dmemcg_pool_put(pool);
> > out_put:
> > - kref_put(®ion->ref, dmemcg_free_region);
> > - }
> > -
> > + kref_put(®ion->ref, dmemcg_free_region);
> > return err ?: nbytes;
> > }
> >
> > ---
> > base-commit: 640c57d6ca1346a1c2363a3f473b405af979e046
> > change-id: 20260605-cgroup-dmem-write-single-region-9bf05b6d995d
> >
> > Best regards,
>
--
Eric Chanudet
^ permalink raw reply
* Re: [PATCH] mm: memcontrol-v1: use nofail allocations for soft limit trees
From: Michal Hocko @ 2026-06-08 13:29 UTC (permalink / raw)
To: Ruoyu Wang
Cc: Johannes Weiner, Roman Gushchin, Shakeel Butt, Muchun Song,
Andrew Morton, cgroups, linux-mm, linux-kernel
In-Reply-To: <CAK_7xqyyDqNW1+puMSp2LzxmOKxFUx-UO9uGiDKoL7ZTJ8+3ZQ@mail.gmail.com>
On Mon 08-06-26 16:34:48, Ruoyu Wang wrote:
> No, I have not observed this allocation failing in practice.
>
> This was found by static analysis and then checked by reading the code:
> memcg1_init() dereferences rtpn unconditionally after kzalloc_node(). I
> treated the soft-limit tree as mandatory memcg v1 init state and used
> __GFP_NOFAIL because continuing without it would not be useful.
This should have been part of the changelog because it provides an
insight into how have you reached your conclusion.
> I agree this is early boot init code, and I do not have a
> runtime failure report or fault-injection reproduction for it. If such
> allocations are considered not worth handling in this path, feel
> free to drop the patch.
Yes, there is simply no point in handling these failures because early
allocation failure like this one would very likely lead to massive
failure before userspace is brought up anyway so there is no practical
way to trigger the NULL ptr.
--
Michal Hocko
SUSE Labs
^ permalink raw reply
* Re: [PATCH] cgroup/dmem: accept only one region per limit write
From: Maarten Lankhorst @ 2026-06-08 13:13 UTC (permalink / raw)
To: Maxime Ripard
Cc: Natalie Vock, Eric Chanudet, Tejun Heo, Johannes Weiner,
Michal Koutný, cgroups, dri-devel, linux-kernel,
Albert Esteve
In-Reply-To: <20260608-glorious-fluorescent-salamander-93daec@houat>
Hey,
On 6/8/26 14:42, Maxime Ripard wrote:
> On Sat, Jun 06, 2026 at 11:44:10PM +0200, Maarten Lankhorst wrote:
>> Hey,
>>
>> On 6/6/26 18:31, Natalie Vock wrote:
>>> On 6/6/26 00:44, Eric Chanudet wrote:
>>>> Accept only one "region value" pair entry for the dmem.max, dmem.min,
>>>> dmem.low files.>
>>>> This changes the UAPI that otherwise accepted multiple lines for setting
>>>> multiple entries in one write. No existing user is known to rely on
>>>> writing multiple regions in a single write.
>>>
>>> Ugh, shoot.
>>>
>>> For dmem.low specifically, there already are some userspace thingies floating around that may write more than one region/value pairs.
>>>
>>> These thingies all depend on that one patchset for dmemcg protection that I should really get around to merging[1]. Since the userspace utilities depend on not-yet-merged patches, they sort of have to expect stuff changing under their belts, so I wouldn't really consider those users a blocker by necessity.
>>>
>>> As I see it, we could go down one of two paths:
>>> 1. We go ahead with the patch as proposed, and I make sure that the users I know of adapt. Could be a bit icky wrt. "do not break userspace" rules, but since the already use non-merged UAPIs in one place, you can argue that these users kind of have to expect breakage.
>>> 2. We use the old handling allowing multiple lines for dmem.min and dmem.low only. This preserves compatibility but uglifies the code by quite a bit.
>>>
>>> All things considered, I think I personally would prefer going with 1. and taking the patch as proposed and just having one codepath handling every limit file. Just highlighting this so we don't do it on accident.
>>>
>>> [1] https://patchwork.freedesktop.org/series/163183/
>>>
>>
>> I prefer option 1 as well, but would like an ack from one of the core cgroup maintainers too,
>> and what Maxime's opinion on this as well.
>
> Option 1 works for me too if doable
>
> Maxime
I see this as an acked-by?
I'll commit this patch to drm-misc-next if so.
Fortunately it may not even break those scripts in the typical case where only 1 region is registered, eg the most common laptop/desktop case.
Kind regards,
~Maarten Lankhorst
^ permalink raw reply
* Re: [PATCH v3 1/4] mm/zswap: Make shrink_worker writeback cursor per-memcg
From: Hao Jia @ 2026-06-08 12:50 UTC (permalink / raw)
To: Nhat Pham
Cc: Yosry Ahmed, akpm, tj, hannes, shakeel.butt, mhocko, mkoutny,
chengming.zhou, muchun.song, roman.gushchin, cgroups, linux-mm,
linux-kernel, linux-doc, Hao Jia
In-Reply-To: <CAKEwX=MQ3xXBAY-2H8vA+XSX5GHNBubJ2GCYAXGD+Hra++ZM7A@mail.gmail.com>
On 2026/6/5 01:23, Nhat Pham wrote:
> On Thu, Jun 4, 2026 at 6:06 AM Hao Jia <jiahao.kernel@gmail.com> wrote:
>>
>>
>>
>> On 2026/6/4 13:34, Yosry Ahmed wrote:
>>>>>> For instance, suppose a parent memcg has two children, memcg1 and memcg2,
>>>>>> each with 200MB of zswap (100MB inactive). Triggering proactive writeback on
>>>>>> the parent memcg will exhaust memcg1's inactive zswap pages. After that,
>>>>>> even though memcg2 still has plenty of inactive zswap pages, it will
>>>>>> continue to write back memcg1's active zswap pages. Writing back active
>>>>>> zswap pages causes the user-space agent to prematurely abort the writeback
>>>>>> because it detects that certain memcg metrics have exceeded predefined
>>>>>> thresholds.
>>>>>
>>>>> This will only happen if the reclaim size is smaller than the batch
>>>>> size, right? Otherwise the kernel should reclaim more or less equally
>>>>> from both memcgs?
>>>>>
>>>>
>>>> I gave it some thought. Not using a cursor could lead to unfairness
>>>> issues with certain writeback sizes:
>>>>
>>>> - If the writeback size is an odd multiple of WB_BATCH (e.g.,
>>>> triggering a writeback of 3 * WB_BATCH), with 2 child cgroups, the
>>>> writeback ratio might end up being 2:1.
>>>> - If a memcg has 5 child cgroups and a writeback of 2 * WB_BATCH is
>>>> triggered, it might repeatedly write back from only the first 2 child
>>>> cgroups.
>>>>
>>>> Although setting a smaller WB_BATCH might mitigate this unfairness, it
>>>> could hurt writeback efficiency. Let's just use per-memcg cursors to
>>>> completely fix these corner cases.
>>>
>>> Exactly, the batch size should be small enough that any unfairness is
>>> not a problem. I would honestly just do batching without a per-memcg
>>> cursor, unless we have numbers to prove that the efficiency is
>>> affected when we use a small batch size. Let's only introduce
>>> complexity when needed please.
>
> I'm impartial towards the complexity of per-memcg cursor. I don't
> think it's that big of a deal, but only if it's warranted.
>
> Hao, if you're convinced that doing small batch is not efficient,
> could you run some experiments to show the improvement bigger batchign
> and fairness? Maybe implement a small batch, no-memcg cursor first.
> Then implement a patch on top of it to add per-memcg cursor, and show
> how much performance win we can get from that patch on top of the
> patch series?
>
Thanks for the suggestion!
I ran some tests and found that neither the per-memcg cursor nor
different batch sizes have a significant impact on proactive writeback
performance. However, exactly as we suspected, without the per-memcg
cursor, the writeback distribution among child memcgs is highly unfair.
Test Setup:
zswap config: 18G capacity, LZ4 compression.
cgroup hierarchy: 1 parent test memcg with 10 child memcgs.
Allocation: Allocated 1600MB of anonymous pages in each child memcg.
To ensure compressibility, the first half of each page was filled with
random data and the second half with zeros.
Force to zswap: Ran echo "1600M" > memory.reclaim on each child memcg
to squeeze all their memory into zswap.
Trigger writeback: Ran echo "<size> zswap_writeback_only" >
memory.reclaim on the parent cgroup 200 times, with a 2-second interval
between each run.
Metric: Monitored the zswpwb_proactive metric in memory.stat to
observe the writeback volume.
**Note**: The size here refers to the uncompressed memory size. Also,
since the second-chance algorithm would cause many writebacks to fall
short of the target size, I **bypassed** it during these tests to avoid
interference.
Without cursor (size: 1M, batch: 32)
child wb_pages wb_MB share%
child0 6368 24.88 12.50
child1 6368 24.88 12.50
child2 6368 24.88 12.50
child3 6368 24.88 12.50
child4 6368 24.88 12.50
child5 6368 24.88 12.50
child6 6368 24.88 12.50
child7 6368 24.88 12.50
child8 0 0.00 0.00
child9 0 0.00 0.00
Without cursor (size: 1M, batch: 128)
child wb_pages wb_MB share%
child0 25472 99.50 50.00
child1 25472 99.50 50.00
child2 0 0.00 0.00
child3 0 0.00 0.00
child4 0 0.00 0.00
child5 0 0.00 0.00
child6 0 0.00 0.00
child7 0 0.00 0.00
child8 0 0.00 0.00
child9 0 0.00 0.00
Without cursor (size: 6M, batch: 128)
child wb_pages wb_MB share%
child0 51200 200.00 16.67
child1 51200 200.00 16.67
child2 25600 100.00 8.33
child3 25600 100.00 8.33
child4 25600 100.00 8.33
child5 25600 100.00 8.33
child6 25600 100.00 8.33
child7 25600 100.00 8.33
child8 25600 100.00 8.33
child9 25600 100.00 8.33
With cursor (size: 1M, batch: 32)
child wb_pages wb_MB share%
child0 5120 20.00 10.00
child1 5120 20.00 10.00
child2 5120 20.00 10.00
child3 5120 20.00 10.00
child4 5120 20.00 10.00
child5 5120 20.00 10.00
child6 5120 20.00 10.00
child7 5120 20.00 10.00
child8 5120 20.00 10.00
child9 5120 20.00 10.00
With cursor (size: 1M, batch: 128)
child wb_pages wb_MB share%
child0 5120 20.00 10.00
child1 5120 20.00 10.00
child2 5120 20.00 10.00
child3 5120 20.00 10.00
child4 5120 20.00 10.00
child5 5120 20.00 10.00
child6 5120 20.00 10.00
child7 5120 20.00 10.00
child8 5120 20.00 10.00
child9 5120 20.00 10.00
Thakns,
Hao
^ permalink raw reply
* Re: [PATCH] cgroup/dmem: accept only one region per limit write
From: Maxime Ripard @ 2026-06-08 12:42 UTC (permalink / raw)
To: Maarten Lankhorst
Cc: Natalie Vock, Eric Chanudet, Tejun Heo, Johannes Weiner,
Michal Koutný, cgroups, dri-devel, linux-kernel,
Albert Esteve
In-Reply-To: <f00e7771-cd70-4c86-9fac-149897e02b12@lankhorst.se>
[-- Attachment #1: Type: text/plain, Size: 1931 bytes --]
On Sat, Jun 06, 2026 at 11:44:10PM +0200, Maarten Lankhorst wrote:
> Hey,
>
> On 6/6/26 18:31, Natalie Vock wrote:
> > On 6/6/26 00:44, Eric Chanudet wrote:
> >> Accept only one "region value" pair entry for the dmem.max, dmem.min,
> >> dmem.low files.>
> >> This changes the UAPI that otherwise accepted multiple lines for setting
> >> multiple entries in one write. No existing user is known to rely on
> >> writing multiple regions in a single write.
> >
> > Ugh, shoot.
> >
> > For dmem.low specifically, there already are some userspace thingies floating around that may write more than one region/value pairs.
> >
> > These thingies all depend on that one patchset for dmemcg protection that I should really get around to merging[1]. Since the userspace utilities depend on not-yet-merged patches, they sort of have to expect stuff changing under their belts, so I wouldn't really consider those users a blocker by necessity.
> >
> > As I see it, we could go down one of two paths:
> > 1. We go ahead with the patch as proposed, and I make sure that the users I know of adapt. Could be a bit icky wrt. "do not break userspace" rules, but since the already use non-merged UAPIs in one place, you can argue that these users kind of have to expect breakage.
> > 2. We use the old handling allowing multiple lines for dmem.min and dmem.low only. This preserves compatibility but uglifies the code by quite a bit.
> >
> > All things considered, I think I personally would prefer going with 1. and taking the patch as proposed and just having one codepath handling every limit file. Just highlighting this so we don't do it on accident.
> >
> > [1] https://patchwork.freedesktop.org/series/163183/
> >
>
> I prefer option 1 as well, but would like an ack from one of the core cgroup maintainers too,
> and what Maxime's opinion on this as well.
Option 1 works for me too if doable
Maxime
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 273 bytes --]
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox