Linux cgroups development
 help / color / mirror / Atom feed
* [tj-cgroup:for-next] BUILD SUCCESS d3b0a7f21119f5a66cb76aa28fb8cc13206aaf7d
From: kernel test robot @ 2026-05-13 10:42 UTC (permalink / raw)
  To: Tejun Heo; +Cc: cgroups

tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git for-next
branch HEAD: d3b0a7f21119f5a66cb76aa28fb8cc13206aaf7d  Merge branch 'for-7.2' into for-next

elapsed time: 1010m

configs tested: 191
configs skipped: 10

The following configs have been built successfully.
More configs may be tested in the coming days.

tested configs:
alpha                             allnoconfig    gcc-15.2.0
alpha                            allyesconfig    gcc-15.2.0
alpha                               defconfig    gcc-15.2.0
arc                              allmodconfig    clang-16
arc                              allmodconfig    gcc-15.2.0
arc                               allnoconfig    gcc-15.2.0
arc                              allyesconfig    clang-23
arc                              allyesconfig    gcc-15.2.0
arc                                 defconfig    gcc-15.2.0
arc                   randconfig-001-20260513    gcc-14.3.0
arc                   randconfig-002-20260513    gcc-14.3.0
arm                               allnoconfig    clang-23
arm                               allnoconfig    gcc-15.2.0
arm                              allyesconfig    clang-16
arm                              allyesconfig    gcc-15.2.0
arm                                 defconfig    gcc-15.2.0
arm                   randconfig-001-20260513    gcc-14.3.0
arm                   randconfig-002-20260513    gcc-14.3.0
arm                   randconfig-003-20260513    gcc-14.3.0
arm                   randconfig-004-20260513    gcc-14.3.0
arm64                            allmodconfig    clang-19
arm64                            allmodconfig    clang-23
arm64                             allnoconfig    gcc-15.2.0
arm64                               defconfig    gcc-15.2.0
arm64                 randconfig-001-20260513    gcc-12.5.0
arm64                 randconfig-002-20260513    gcc-12.5.0
arm64                 randconfig-003-20260513    gcc-12.5.0
arm64                 randconfig-004-20260513    gcc-12.5.0
csky                             allmodconfig    gcc-15.2.0
csky                              allnoconfig    gcc-15.2.0
csky                                defconfig    gcc-15.2.0
csky                  randconfig-001-20260513    gcc-12.5.0
csky                  randconfig-002-20260513    gcc-12.5.0
hexagon                          allmodconfig    clang-17
hexagon                          allmodconfig    gcc-15.2.0
hexagon                           allnoconfig    clang-23
hexagon                           allnoconfig    gcc-15.2.0
hexagon                             defconfig    gcc-15.2.0
hexagon               randconfig-001-20260513    gcc-8.5.0
hexagon               randconfig-002-20260513    gcc-8.5.0
i386                             allmodconfig    gcc-14
i386                              allnoconfig    gcc-14
i386                              allnoconfig    gcc-15.2.0
i386                             allyesconfig    gcc-14
i386        buildonly-randconfig-001-20260513    clang-20
i386        buildonly-randconfig-002-20260513    clang-20
i386        buildonly-randconfig-003-20260513    clang-20
i386        buildonly-randconfig-004-20260513    clang-20
i386        buildonly-randconfig-005-20260513    clang-20
i386        buildonly-randconfig-006-20260513    clang-20
i386                                defconfig    gcc-15.2.0
i386                  randconfig-001-20260513    clang-20
i386                  randconfig-002-20260513    clang-20
i386                  randconfig-003-20260513    clang-20
i386                  randconfig-004-20260513    clang-20
i386                  randconfig-005-20260513    clang-20
i386                  randconfig-006-20260513    clang-20
i386                  randconfig-007-20260513    clang-20
i386                  randconfig-011-20260513    clang-20
i386                  randconfig-012-20260513    clang-20
i386                  randconfig-012-20260513    gcc-14
i386                  randconfig-013-20260513    clang-20
i386                  randconfig-014-20260513    clang-20
i386                  randconfig-015-20260513    clang-20
i386                  randconfig-016-20260513    clang-20
i386                  randconfig-017-20260513    clang-20
loongarch                        allmodconfig    clang-19
loongarch                        allmodconfig    clang-23
loongarch                         allnoconfig    clang-23
loongarch                         allnoconfig    gcc-15.2.0
loongarch                           defconfig    clang-19
loongarch             randconfig-001-20260513    gcc-8.5.0
loongarch             randconfig-002-20260513    gcc-8.5.0
m68k                             allmodconfig    gcc-15.2.0
m68k                              allnoconfig    gcc-15.2.0
m68k                             allyesconfig    clang-16
m68k                             allyesconfig    gcc-15.2.0
m68k                                defconfig    clang-19
microblaze                        allnoconfig    gcc-15.2.0
microblaze                       allyesconfig    gcc-15.2.0
microblaze                          defconfig    clang-19
mips                             allmodconfig    gcc-15.2.0
mips                              allnoconfig    gcc-15.2.0
mips                             allyesconfig    gcc-15.2.0
nios2                            allmodconfig    clang-23
nios2                            allmodconfig    gcc-11.5.0
nios2                             allnoconfig    clang-23
nios2                             allnoconfig    gcc-11.5.0
nios2                               defconfig    clang-19
nios2                 randconfig-001-20260513    gcc-8.5.0
nios2                 randconfig-002-20260513    gcc-8.5.0
openrisc                         allmodconfig    clang-23
openrisc                         allmodconfig    gcc-15.2.0
openrisc                          allnoconfig    clang-23
openrisc                          allnoconfig    gcc-15.2.0
openrisc                            defconfig    gcc-15.2.0
parisc                           allmodconfig    gcc-15.2.0
parisc                            allnoconfig    clang-23
parisc                            allnoconfig    gcc-15.2.0
parisc                           allyesconfig    clang-19
parisc                           allyesconfig    gcc-15.2.0
parisc                              defconfig    gcc-15.2.0
parisc                randconfig-001-20260513    gcc-8.5.0
parisc                randconfig-002-20260513    gcc-8.5.0
parisc64                            defconfig    clang-19
powerpc                          allmodconfig    gcc-15.2.0
powerpc                           allnoconfig    clang-23
powerpc                           allnoconfig    gcc-15.2.0
powerpc                 mpc832x_rdb_defconfig    gcc-15.2.0
powerpc                 mpc834x_itx_defconfig    clang-16
powerpc                     rainier_defconfig    gcc-15.2.0
powerpc               randconfig-001-20260513    gcc-8.5.0
powerpc               randconfig-002-20260513    gcc-8.5.0
powerpc64             randconfig-001-20260513    gcc-8.5.0
powerpc64             randconfig-002-20260513    gcc-8.5.0
riscv                            allmodconfig    clang-23
riscv                             allnoconfig    clang-23
riscv                             allnoconfig    gcc-15.2.0
riscv                            allyesconfig    clang-16
riscv                               defconfig    gcc-15.2.0
riscv                 randconfig-001-20260513    gcc-15.2.0
riscv                 randconfig-002-20260513    gcc-15.2.0
s390                             allmodconfig    clang-18
s390                             allmodconfig    clang-19
s390                              allnoconfig    clang-23
s390                             allyesconfig    gcc-15.2.0
s390                                defconfig    gcc-15.2.0
s390                  randconfig-001-20260513    gcc-15.2.0
s390                  randconfig-002-20260513    gcc-15.2.0
sh                               allmodconfig    gcc-15.2.0
sh                                allnoconfig    clang-23
sh                                allnoconfig    gcc-15.2.0
sh                               allyesconfig    clang-19
sh                               allyesconfig    gcc-15.2.0
sh                                  defconfig    gcc-14
sh                    randconfig-001-20260513    gcc-15.2.0
sh                    randconfig-002-20260513    gcc-15.2.0
sparc                             allnoconfig    clang-23
sparc                             allnoconfig    gcc-15.2.0
sparc                               defconfig    gcc-15.2.0
sparc                 randconfig-001-20260513    gcc-11.5.0
sparc                 randconfig-002-20260513    gcc-11.5.0
sparc64                          allmodconfig    clang-23
sparc64                             defconfig    gcc-14
sparc64               randconfig-001-20260513    gcc-11.5.0
sparc64               randconfig-002-20260513    gcc-11.5.0
um                               allmodconfig    clang-19
um                                allnoconfig    clang-23
um                               allyesconfig    gcc-14
um                               allyesconfig    gcc-15.2.0
um                                  defconfig    gcc-14
um                             i386_defconfig    gcc-14
um                    randconfig-001-20260513    gcc-11.5.0
um                    randconfig-002-20260513    gcc-11.5.0
um                           x86_64_defconfig    gcc-14
x86_64                           allmodconfig    clang-20
x86_64                            allnoconfig    clang-20
x86_64                            allnoconfig    clang-23
x86_64                           allyesconfig    clang-20
x86_64      buildonly-randconfig-001-20260513    gcc-12
x86_64      buildonly-randconfig-002-20260513    gcc-12
x86_64      buildonly-randconfig-003-20260513    gcc-12
x86_64      buildonly-randconfig-004-20260513    gcc-12
x86_64      buildonly-randconfig-005-20260513    gcc-12
x86_64      buildonly-randconfig-006-20260513    gcc-12
x86_64                              defconfig    gcc-14
x86_64                                  kexec    clang-20
x86_64                randconfig-011-20260513    gcc-14
x86_64                randconfig-012-20260513    gcc-14
x86_64                randconfig-013-20260513    gcc-14
x86_64                randconfig-014-20260513    gcc-14
x86_64                randconfig-015-20260513    gcc-14
x86_64                randconfig-016-20260513    gcc-14
x86_64                randconfig-071-20260513    gcc-14
x86_64                randconfig-072-20260513    gcc-14
x86_64                randconfig-073-20260513    gcc-14
x86_64                randconfig-074-20260513    gcc-14
x86_64                randconfig-075-20260513    gcc-14
x86_64                randconfig-076-20260513    gcc-14
x86_64                               rhel-9.4    clang-20
x86_64                           rhel-9.4-bpf    gcc-14
x86_64                          rhel-9.4-func    clang-20
x86_64                    rhel-9.4-kselftests    clang-20
x86_64                         rhel-9.4-kunit    gcc-14
x86_64                           rhel-9.4-ltp    gcc-14
x86_64                          rhel-9.4-rust    clang-20
xtensa                            allnoconfig    clang-23
xtensa                            allnoconfig    gcc-15.2.0
xtensa                           allyesconfig    clang-23
xtensa                randconfig-001-20260513    gcc-11.5.0
xtensa                randconfig-002-20260513    gcc-11.5.0

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply

* [PATCH v2] cgroup/cpuset: Return only actually allocated CPUs during partition invalidation
From: Sun Shaojie @ 2026-05-13 10:37 UTC (permalink / raw)
  To: Waiman Long, Chen Ridong, Tejun Heo, Johannes Weiner,
	Michal Koutný
  Cc: cgroups, linux-kernel, sunshaojie

From: sunshaojie <sunshaojie@kylinos.cn>

In update_parent_effective_cpumask() with partcmd_invalidate, the CPUs
to return to the parent are computed as:

    adding = cpumask_and(tmp->addmask, xcpus, parent->effective_xcpus);

where xcpus = user_xcpus(cs) which returns cs->exclusive_cpus (if set)
or cs->cpus_allowed. When exclusive_cpus is not set, user_xcpus(cs) can
contain CPUs that were never actually granted to the partition due to
sibling exclusion in compute_excpus(). Consequently, the invalidation
may return CPUs to the parent that remain in use by sibling partitions,
causing overlapping effective_cpus and triggering the
WARN_ON_ONCE(1) in generate_sched_domains().

Use cs->effective_xcpus instead, which reflects the CPUs actually
granted to this partition.

Reproducer (on a 4-CPU machine):

    cd /sys/fs/cgroup
    mkdir a1 b1

    # a1 becomes partition root with CPUs 0-1
    echo "0-1" > a1/cpuset.cpus
    echo "root" > a1/cpuset.cpus.partition

    # b1 becomes partition root with CPUs 1-2, but sibling exclusion
    # reduces its effective_xcpus to CPU 2 only
    echo "1-2" > b1/cpuset.cpus
    echo "root" > b1/cpuset.cpus.partition

    # b1 changes cpus_allowed to 0-1 -> partition invalidation
    echo "0-1" > b1/cpuset.cpus

    # Expected: CPUs 2-3  (only CPU 2 returned from b1)
    # Actual:   CPUs 1-3  (CPU 0-1 returned, overlapping with a1)
    cat cpuset.cpus.effective

dmesg will also show a WARNING from generate_sched_domains() reporting
overlapping partition root effective_cpus.

Fixes: 2a3602030d80 ("cgroup/cpuset: Don't invalidate sibling partitions on cpuset.cpus conflict")
Signed-off-by: sunshaojie <sunshaojie@kylinos.cn>
Test-by: Chen Ridong <chenridong@huaweicloud.com>
Reviewed-by: Chen Ridong <chenridong@huaweicloud.com>

---
Changes in v2:
- Updated Fixes tag per review by Chen Ridong
---
 kernel/cgroup/cpuset.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 1335e437098e..2311470ef077 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -1715,7 +1715,8 @@ static int update_parent_effective_cpumask(struct cpuset *cs, int cmd,
 		 */
 		if (is_partition_valid(parent))
 			adding = cpumask_and(tmp->addmask,
-					     xcpus, parent->effective_xcpus);
+					     cs->effective_xcpus,
+					     parent->effective_xcpus);
 		if (old_prs > 0)
 			new_prs = -old_prs;
 
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH v3 07/12] mm, swap: support flexible batch freeing of slots in different memcgs
From: Kairui Song @ 2026-05-13  9:43 UTC (permalink / raw)
  To: Chris Li
  Cc: linux-mm, Andrew Morton, David Hildenbrand, Zi Yan, Baolin Wang,
	Barry Song, Hugh Dickins, Kemeng Shi, Nhat Pham, Baoquan He,
	Johannes Weiner, Youngjun Park, Chengming Zhou, Roman Gushchin,
	Shakeel Butt, Muchun Song, Qi Zheng, linux-kernel, cgroups,
	Yosry Ahmed, Lorenzo Stoakes, Dev Jain, Lance Yang, Michal Hocko,
	Michal Hocko, Suren Baghdasaryan, Axel Rasmussen
In-Reply-To: <CACePvbVnDrR6e7wvpF-nf1CWgoMdX4MTf7RSv2bCr28W6d8b2A@mail.gmail.com>

On Fri, May 8, 2026 at 12:01 PM Chris Li <chrisl@kernel.org> wrote:
>
> On Tue, Apr 21, 2026 at 7:16 AM Kairui Song via B4 Relay
> <devnull+kasong.tencent.com@kernel.org> wrote:
> >
> > From: Kairui Song <kasong@tencent.com>
> >
> > Instead of requiring the caller to ensure all slots are in the same
> > memcg, make the function handle different memcgs at once.
> >
> > This is both a micro optimization and required for removing the memcg
> > lookup in the page table layer, so it can be unified at the swap layer.
> >
> > We are not removing the memcg lookup in the page table in this commit.
> > It has to be done after the memcg lookup is deferred to the swap layer.
> >
> > Signed-off-by: Kairui Song <kasong@tencent.com>
>
> Overall, it looks good. Some nitpicks follow.
>
> Acked-by: Chris Li <chrisl@kernel.org>
>
> > ---
> >  mm/swapfile.c | 33 +++++++++++++++++++++++++++++----
> >  1 file changed, 29 insertions(+), 4 deletions(-)
> >
> > diff --git a/mm/swapfile.c b/mm/swapfile.c
> > index e1ad77a69e54..8d3d22c463f3 100644
> > --- a/mm/swapfile.c
> > +++ b/mm/swapfile.c
> > @@ -1872,21 +1872,46 @@ void __swap_cluster_free_entries(struct swap_info_struct *si,
> >                                  unsigned int ci_start, unsigned int nr_pages)
> >  {
> >         unsigned long old_tb;
> > +       unsigned int type = si->type;
> > +       unsigned short id = 0, id_cur;
>
> Nitpick: I'm tempted to rename a few variables to improve my
> understanding. Feel free to keep it as it is.
>
> id -> batch_id

Good idea.

>
> Nitpick: This line confused me a bit. Two offsets are mentioned here:
> "offset + ci_offset". One would assume that ci_offset is the offset of
> the ci, and the offset is the incremental one. It is the other way
> around.

This intermediate swap entry usage will be gone soon in a next commit
so I think it should be fine either way.

>
> > +               id_cur = lookup_swap_cgroup_id(entry);
> > +               if (id != id_cur) {
> > +                       if (id)
> > +                               mem_cgroup_uncharge_swap(swp_entry(type, offset + ci_batch),
> > +                                                        ci_off - ci_batch);
>
> With the above rename, this become:
> "... swp_entry(type, ci_offset + batch_off)," ; This combined the
> offset turn into the swap entry.
> "ci_off - batch_off". That is the running length from the beginning of batch.
>
> > +                       id = id_cur;
> > +                       ci_batch = ci_off;
> > +               }
> >         } while (++ci_off < ci_end);
> >
> > -       mem_cgroup_uncharge_swap(swp_entry(si->type, offset), nr_pages);
> > -       swap_range_free(si, offset, nr_pages);
> > +       if (id) {
>
> This becomes `if (batch_id)`, meaning if we have pending batching, we
> flush the current batch.

This part does look better. Thnaks!

>
> Chris
>

^ permalink raw reply

* [PATCH 5.15.y] blk-cgroup: Fix NULL deref caused by blkg_policy_data being installed before init
From: Robert Garcia @ 2026-05-13  8:10 UTC (permalink / raw)
  To: stable, Tejun Heo
  Cc: Jens Axboe, Breno Leitao, Josef Bacik, Robert Garcia, cgroups,
	linux-block, linux-kernel

From: Tejun Heo <tj@kernel.org>

[ Upstream commit ec14a87ee1999b19d8b7ed0fa95fea80644624ae ]

blk-iocost sometimes causes the following crash:

  BUG: kernel NULL pointer dereference, address: 00000000000000e0
  ...
  RIP: 0010:_raw_spin_lock+0x17/0x30
  Code: be 01 02 00 00 e8 79 38 39 ff 31 d2 89 d0 5d c3 0f 1f 00 0f 1f 44 00 00 55 48 89 e5 65 ff 05 48 d0 34 7e b9 01 00 00 00 31 c0 <f0> 0f b1 0f 75 02 5d c3 89 c6 e8 ea 04 00 00 5d c3 0f 1f 84 00 00
  RSP: 0018:ffffc900023b3d40 EFLAGS: 00010046
  RAX: 0000000000000000 RBX: 00000000000000e0 RCX: 0000000000000001
  RDX: ffffc900023b3d20 RSI: ffffc900023b3cf0 RDI: 00000000000000e0
  RBP: ffffc900023b3d40 R08: ffffc900023b3c10 R09: 0000000000000003
  R10: 0000000000000064 R11: 000000000000000a R12: ffff888102337000
  R13: fffffffffffffff2 R14: ffff88810af408c8 R15: ffff8881070c3600
  FS:  00007faaaf364fc0(0000) GS:ffff88842fdc0000(0000) knlGS:0000000000000000
  CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
  CR2: 00000000000000e0 CR3: 00000001097b1000 CR4: 0000000000350ea0
  Call Trace:
   <TASK>
   ioc_weight_write+0x13d/0x410
   cgroup_file_write+0x7a/0x130
   kernfs_fop_write_iter+0xf5/0x170
   vfs_write+0x298/0x370
   ksys_write+0x5f/0xb0
   __x64_sys_write+0x1b/0x20
   do_syscall_64+0x3d/0x80
   entry_SYSCALL_64_after_hwframe+0x46/0xb0

This happens because iocg->ioc is NULL. The field is initialized by
ioc_pd_init() and never cleared. The NULL deref is caused by
blkcg_activate_policy() installing blkg_policy_data before initializing it.

blkcg_activate_policy() was doing the following:

1. Allocate pd's for all existing blkg's and install them in blkg->pd[].
2. Initialize all pd's.
3. Online all pd's.

blkcg_activate_policy() only grabs the queue_lock and may release and
re-acquire the lock as allocation may need to sleep. ioc_weight_write()
grabs blkcg->lock and iterates all its blkg's. The two can race and if
ioc_weight_write() runs during #1 or between #1 and #2, it can encounter a
pd which is not initialized yet, leading to crash.

The crash can be reproduced with the following script:

  #!/bin/bash

  echo +io > /sys/fs/cgroup/cgroup.subtree_control
  systemd-run --unit touch-sda --scope dd if=/dev/sda of=/dev/null bs=1M count=1 iflag=direct
  echo 100 > /sys/fs/cgroup/system.slice/io.weight
  bash -c "echo '8:0 enable=1' > /sys/fs/cgroup/io.cost.qos" &
  sleep .2
  echo 100 > /sys/fs/cgroup/system.slice/io.weight

with the following patch applied:

> diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
> index fc49be622e05..38d671d5e10c 100644
> --- a/block/blk-cgroup.c
> +++ b/block/blk-cgroup.c
> @@ -1553,6 +1553,12 @@ int blkcg_activate_policy(struct gendisk *disk, const struct blkcg_policy *pol)
> 		pd->online = false;
> 	}
>
> +       if (system_state == SYSTEM_RUNNING) {
> +               spin_unlock_irq(&q->queue_lock);
> +               ssleep(1);
> +               spin_lock_irq(&q->queue_lock);
> +       }
> +
> 	/* all allocated, init in the same order */
> 	if (pol->pd_init_fn)
> 		list_for_each_entry_reverse(blkg, &q->blkg_list, q_node)

I don't see a reason why all pd's should be allocated, initialized and
onlined together. The only ordering requirement is that parent blkgs to be
initialized and onlined before children, which is guaranteed from the
walking order. Let's fix the bug by allocating, initializing and onlining pd
for each blkg and holding blkcg->lock over initialization and onlining. This
ensures that an installed blkg is always fully initialized and onlined
removing the the race window.

Signed-off-by: Tejun Heo <tj@kernel.org>
Reported-by: Breno Leitao <leitao@debian.org>
Fixes: 9d179b865449 ("blkcg: Fix multiple bugs in blkcg_activate_policy()")
Link: https://lore.kernel.org/r/ZN0p5_W-Q9mAHBVY@slm.duckdns.org
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Robert Garcia <rob_garcia@163.com>
---
 block/blk-cgroup.c | 32 ++++++++++++++++++--------------
 1 file changed, 18 insertions(+), 14 deletions(-)

diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index 61fdff5406b5..1179c4bee705 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -1337,7 +1337,7 @@ int blkcg_activate_policy(struct request_queue *q,
 retry:
 	spin_lock_irq(&q->queue_lock);
 
-	/* blkg_list is pushed at the head, reverse walk to allocate parents first */
+	/* blkg_list is pushed at the head, reverse walk to initialize parents first */
 	list_for_each_entry_reverse(blkg, &q->blkg_list, q_node) {
 		struct blkg_policy_data *pd;
 
@@ -1375,21 +1375,20 @@ int blkcg_activate_policy(struct request_queue *q,
 				goto enomem;
 		}
 
-		blkg->pd[pol->plid] = pd;
+		spin_lock(&blkg->blkcg->lock);
+
 		pd->blkg = blkg;
 		pd->plid = pol->plid;
-		pd->online = false;
-	}
+		blkg->pd[pol->plid] = pd;
 
-	/* all allocated, init in the same order */
-	if (pol->pd_init_fn)
-		list_for_each_entry_reverse(blkg, &q->blkg_list, q_node)
-			pol->pd_init_fn(blkg->pd[pol->plid]);
+		if (pol->pd_init_fn)
+			pol->pd_init_fn(pd);
 
-	list_for_each_entry_reverse(blkg, &q->blkg_list, q_node) {
 		if (pol->pd_online_fn)
-			pol->pd_online_fn(blkg->pd[pol->plid]);
-		blkg->pd[pol->plid]->online = true;
+			pol->pd_online_fn(pd);
+		pd->online = true;
+
+		spin_unlock(&blkg->blkcg->lock);
 	}
 
 	__set_bit(pol->plid, q->blkcg_pols);
@@ -1406,14 +1405,19 @@ int blkcg_activate_policy(struct request_queue *q,
 	return ret;
 
 enomem:
-	/* alloc failed, nothing's initialized yet, free everything */
+	/* alloc failed, take down everything */
 	spin_lock_irq(&q->queue_lock);
 	list_for_each_entry(blkg, &q->blkg_list, q_node) {
 		struct blkcg *blkcg = blkg->blkcg;
+		struct blkg_policy_data *pd;
 
 		spin_lock(&blkcg->lock);
-		if (blkg->pd[pol->plid]) {
-			pol->pd_free_fn(blkg->pd[pol->plid]);
+		pd = blkg->pd[pol->plid];
+		if (pd) {
+			if (pd->online && pol->pd_offline_fn)
+				pol->pd_offline_fn(pd);
+			pd->online = false;
+			pol->pd_free_fn(pd);
 			blkg->pd[pol->plid] = NULL;
 		}
 		spin_unlock(&blkcg->lock);
-- 
2.34.1


^ permalink raw reply related

* Re: [PATCH 2/3] mm/zswap: Implement proactive writeback
From: Hao Jia @ 2026-05-13  8:04 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, Alexandre Ghiti
In-Reply-To: <CAKEwX=MOixJAUGiwUcMQa0Stvg-mR-MvpDRD8WA4YMtRvnUYTg@mail.gmail.com>



On 2026/5/12 23:47, Nhat Pham wrote:
> On Tue, May 12, 2026 at 2:32 AM Hao Jia <jiahao.kernel@gmail.com> wrote:
>>
>>
>>
>> On 2026/5/12 03:57, Yosry Ahmed wrote:
>>> On Mon, May 11, 2026 at 12:49 PM Nhat Pham <nphamcs@gmail.com> wrote:
>>>>
>>>> On Mon, May 11, 2026 at 3:52 AM Hao Jia <jiahao.kernel@gmail.com> wrote:
>>>>>
>>>>> From: Hao Jia <jiahao1@lixiang.com>
>>>>>
>>>>> Zswap currently writes back pages to backing swap devices reactively,
>>>>> triggered either by memory pressure via the shrinker or by the pool
>>>>> reaching its size limit. This reactive approach offers no precise
>>>>> control over when writeback happens, which can disturb latency-sensitive
>>>>> workloads, and it cannot direct writeback at a specific memory cgroup.
>>>>> However, there are scenarios where users might want to proactively
>>>>> write back cold pages from zswap to the backing swap device, for
>>>>> example, to free up memory for other applications or to prepare for
>>>>> upcoming memory-intensive workloads.
>>>>>
>>>>> Therefore, implement a proactive writeback mechanism for zswap by
>>>>> adding a new cgroup interface file memory.zswap.proactive_writeback
>>>>> within the memory controller.
>>>>
>>
>> Thanks Nhat, Yosry — let me address both comments together.
>>
>>>>
>>>> We already have memory.reclaim, no? Would that not work to create
>>>> headroom generally for your use case? Is there a reason why we are
>>>> treating zswap memory as special here?
>>>
>>
>> Apologies for the lack of detailed explanation in the patch description,
>> which led to the confusion.
>>
>> While we are already utilizing memory.reclaim, it does not fully address
>> our requirements.
>>
>> Our deployment runs a userspace proactive reclaimer that drives
>> memory.reclaim based on the system's runtime state (memory/CPU/IO
>> pressure, refault rate, ...) and workload-specific
>> policy. That first stage compresses cold anon pages into zswap. Entries
>> that then remain in zswap past a policy-defined age threshold are
>> considered "twice cold", and the reclaimer wants
>> to write them back to the backing swap device at a moment of its own
>> choosing, to further reclaim the DRAM still held by the compressed data.
>>
>> This is the "second-level offloading" pattern described in Meta's TMO
>> paper [1]. zswap proactive writeback is what this series introduces to
>> address that second-level offloading stage.
>>
>> [1] https://www.pdl.cmu.edu/ftp/NVM/tmo_asplos22.pdf
> 
> Yeah that's what we've been trying to work on as well :) We are
> working on a couple of improvements to the mechanism side of this path
> (cc Alex) - hopefully it will help your use case too!
> 
> Anyway, back to my original inquiry: I understand your use case. It's
> pretty similar to our goal. What I'm not getting is why is
> memory.reclaim (which you already use) not sufficient for zswap ->
> disk swap offloading too?
> 
> Zswap objects are organized into LRU and exposed to the shrinker
> interface. Echo-ing to memory.reclaim should also offload some zswap
> entries, correct? Are there still cold zswap entries that escape this,
> somehow?
> 

Yes, the memory.reclaim path does drive some zswap writeback, but
it is not enough for our case.

1. For a memcg that has reached steady state (a common case being
when memory.current is below the policy target), the userspace
reclaimer may not invoke memory.reclaim on it for a long time,
and so no second-level offloading happens through
memory.reclaim. In this state we want
memory.zswap.proactive_writeback to write back entries that
have sat in zswap past an age threshold, to further reclaim
the DRAM still held by the compressed data.

2. Even when memory.reclaim is running, the fraction of zswap
residency that ends up reaching the backing swap device is
still very small for many of our workloads, and the userspace
reclaimer has no way to participate in or control the
granularity of zswap writeback. So in our deployment we prefer
to leave the zswap shrinker disabled, decouple LRU -> zswap
from zswap -> swap, and use a dedicated proactive-writeback
interface that lifts the writeback policy into userspace where
it can evolve independently of the kernel.

Thanks,
Hao

> Furthermore, we already have a way to detect the "twice cold" entries
> you mentioned: the referenced bit. This is analogous to the way we
> treat uncompressed pages.
> 
>>
>>
>>> +1, why do we need to specifically proactively reclaim the compressed memory?
>>>
>>> Also, if we do need to minimize the compressed memory and force higher
>>> writeback rates, we can do so with memory.zswap.max, right?
>>
>> Here are a few reasons why memory.zswap.max is not enough:
>>
>> 1. Writing memory.zswap.max itself does not trigger any writeback
>> immediately. For a memcg that has reached steady state (on which the
>> userspace reclaimer is no longer invoking
>> memory.reclaim), after enough time has passed, the reclaimer has no good
>> way to trigger proactive writeback for second-level offloading by
>> lowering memory.zswap.max, because in steady
>> state nothing drives the zswap_store() -> shrink_memcg() path. The
>> userspace reclaimer still has no control over when proactive writeback
>> happens.
>>
>> 2. memory.zswap.max currently triggers zswap writeback via zswap_store()
>> -> shrink_memcg(), and each over-limit event can write back at most
>> NR_NODES entries. If zswap residency is far
>> above memory.zswap.max, converging to the target size requires at least
>> O(over-limit pages / NR_NODES) zswap_store() events, with no batching —
>> proactive writeback therefore has
>> significant latency.
>>
>> 3. memory.zswap.max is a stateful interface. If the userspace reclaimer
>> crashes for any reason mid-operation, it may leave memory.zswap.max at
>> some set value, putting the application in a
>>    persistently throttled bad state.
>>
>> 4. Once the userspace reclaimer has lowered memory.zswap.max, if the
>> workload is rapidly expanding and triggers memory reclaim via
>> memory.high / kswapd / etc., the actual amount written
>> back can exceed what was intended.
> 
> One more reason: IIRC, when you set memory.zswap.max to a value other
> than 0 max, every zswap store incurs a pretty expensive check
> (obj_cgroup_may_zswap), which does a force flush
> (__mem_cgroup_flush_stats). That was pretty expensive last time some
> of our internal services played with it. So yeah, it's not ideal...
> 
> (if you're using this, might wanna profile this as well).
> 
>>
>> Thanks,
>> Hao

^ permalink raw reply

* [tj-cgroup:for-7.2] BUILD SUCCESS 2a7d34eba5f5a9b889c0f24a28c3b603ba1e7b2b
From: kernel test robot @ 2026-05-13  7:57 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: 2a7d34eba5f5a9b889c0f24a28c3b603ba1e7b2b  selftests/cgroup: check malloc return value in alloc_anon functions

elapsed time: 845m

configs tested: 189
configs skipped: 12

The following configs have been built successfully.
More configs may be tested in the coming days.

tested configs:
alpha                             allnoconfig    gcc-15.2.0
alpha                            allyesconfig    gcc-15.2.0
alpha                               defconfig    gcc-15.2.0
arc                              allmodconfig    clang-16
arc                              allmodconfig    gcc-15.2.0
arc                               allnoconfig    gcc-15.2.0
arc                              allyesconfig    clang-23
arc                              allyesconfig    gcc-15.2.0
arc                                 defconfig    gcc-15.2.0
arc                   randconfig-001-20260513    gcc-14.3.0
arc                   randconfig-002-20260513    gcc-14.3.0
arm                               allnoconfig    clang-23
arm                               allnoconfig    gcc-15.2.0
arm                              allyesconfig    clang-16
arm                              allyesconfig    gcc-15.2.0
arm                                 defconfig    gcc-15.2.0
arm                   randconfig-001-20260513    gcc-14.3.0
arm                   randconfig-002-20260513    gcc-14.3.0
arm                   randconfig-003-20260513    gcc-14.3.0
arm                   randconfig-004-20260513    gcc-14.3.0
arm64                            allmodconfig    clang-19
arm64                            allmodconfig    clang-23
arm64                             allnoconfig    gcc-15.2.0
arm64                               defconfig    gcc-15.2.0
arm64                 randconfig-001-20260513    gcc-12.5.0
arm64                 randconfig-002-20260513    gcc-12.5.0
arm64                 randconfig-003-20260513    gcc-12.5.0
arm64                 randconfig-004-20260513    gcc-12.5.0
csky                             allmodconfig    gcc-15.2.0
csky                              allnoconfig    gcc-15.2.0
csky                                defconfig    gcc-15.2.0
csky                  randconfig-001-20260513    gcc-12.5.0
csky                  randconfig-002-20260513    gcc-12.5.0
hexagon                          allmodconfig    clang-17
hexagon                          allmodconfig    gcc-15.2.0
hexagon                           allnoconfig    clang-23
hexagon                           allnoconfig    gcc-15.2.0
hexagon                             defconfig    gcc-15.2.0
hexagon               randconfig-001-20260513    gcc-8.5.0
hexagon               randconfig-002-20260513    gcc-8.5.0
i386                             allmodconfig    gcc-14
i386                              allnoconfig    gcc-14
i386                              allnoconfig    gcc-15.2.0
i386                             allyesconfig    gcc-14
i386        buildonly-randconfig-001-20260513    clang-20
i386        buildonly-randconfig-002-20260513    clang-20
i386        buildonly-randconfig-003-20260513    clang-20
i386        buildonly-randconfig-004-20260513    clang-20
i386        buildonly-randconfig-005-20260513    clang-20
i386        buildonly-randconfig-006-20260513    clang-20
i386                                defconfig    gcc-15.2.0
i386                  randconfig-001-20260513    clang-20
i386                  randconfig-002-20260513    clang-20
i386                  randconfig-003-20260513    clang-20
i386                  randconfig-004-20260513    clang-20
i386                  randconfig-005-20260513    clang-20
i386                  randconfig-006-20260513    clang-20
i386                  randconfig-007-20260513    clang-20
i386                  randconfig-011-20260513    clang-20
i386                  randconfig-012-20260513    clang-20
i386                  randconfig-012-20260513    gcc-14
i386                  randconfig-013-20260513    clang-20
i386                  randconfig-014-20260513    clang-20
i386                  randconfig-015-20260513    clang-20
i386                  randconfig-016-20260513    clang-20
i386                  randconfig-017-20260513    clang-20
loongarch                        allmodconfig    clang-19
loongarch                        allmodconfig    clang-23
loongarch                         allnoconfig    clang-23
loongarch                         allnoconfig    gcc-15.2.0
loongarch                           defconfig    clang-19
loongarch             randconfig-001-20260513    gcc-8.5.0
loongarch             randconfig-002-20260513    gcc-8.5.0
m68k                             allmodconfig    gcc-15.2.0
m68k                              allnoconfig    gcc-15.2.0
m68k                             allyesconfig    clang-16
m68k                             allyesconfig    gcc-15.2.0
m68k                                defconfig    clang-19
microblaze                        allnoconfig    gcc-15.2.0
microblaze                       allyesconfig    gcc-15.2.0
microblaze                          defconfig    clang-19
mips                             allmodconfig    gcc-15.2.0
mips                              allnoconfig    gcc-15.2.0
mips                             allyesconfig    gcc-15.2.0
nios2                            allmodconfig    clang-23
nios2                            allmodconfig    gcc-11.5.0
nios2                             allnoconfig    clang-23
nios2                             allnoconfig    gcc-11.5.0
nios2                               defconfig    clang-19
nios2                 randconfig-001-20260513    gcc-8.5.0
nios2                 randconfig-002-20260513    gcc-8.5.0
openrisc                         allmodconfig    clang-23
openrisc                          allnoconfig    clang-23
openrisc                          allnoconfig    gcc-15.2.0
openrisc                            defconfig    gcc-15.2.0
parisc                           allmodconfig    gcc-15.2.0
parisc                            allnoconfig    clang-23
parisc                            allnoconfig    gcc-15.2.0
parisc                           allyesconfig    clang-19
parisc                           allyesconfig    gcc-15.2.0
parisc                              defconfig    gcc-15.2.0
parisc                randconfig-001-20260513    gcc-8.5.0
parisc                randconfig-002-20260513    gcc-8.5.0
parisc64                            defconfig    clang-19
powerpc                          allmodconfig    gcc-15.2.0
powerpc                           allnoconfig    clang-23
powerpc                           allnoconfig    gcc-15.2.0
powerpc                 mpc834x_itx_defconfig    clang-16
powerpc                     rainier_defconfig    gcc-15.2.0
powerpc               randconfig-001-20260513    gcc-8.5.0
powerpc               randconfig-002-20260513    gcc-8.5.0
powerpc64             randconfig-001-20260513    gcc-8.5.0
powerpc64             randconfig-002-20260513    gcc-8.5.0
riscv                            allmodconfig    clang-23
riscv                             allnoconfig    clang-23
riscv                             allnoconfig    gcc-15.2.0
riscv                            allyesconfig    clang-16
riscv                               defconfig    gcc-15.2.0
riscv                 randconfig-001-20260513    gcc-15.2.0
riscv                 randconfig-002-20260513    gcc-15.2.0
s390                             allmodconfig    clang-18
s390                             allmodconfig    clang-19
s390                              allnoconfig    clang-23
s390                             allyesconfig    gcc-15.2.0
s390                                defconfig    gcc-15.2.0
s390                  randconfig-001-20260513    gcc-15.2.0
s390                  randconfig-002-20260513    gcc-15.2.0
sh                               allmodconfig    gcc-15.2.0
sh                                allnoconfig    clang-23
sh                                allnoconfig    gcc-15.2.0
sh                               allyesconfig    clang-19
sh                               allyesconfig    gcc-15.2.0
sh                                  defconfig    gcc-14
sh                    randconfig-001-20260513    gcc-15.2.0
sh                    randconfig-002-20260513    gcc-15.2.0
sparc                             allnoconfig    clang-23
sparc                             allnoconfig    gcc-15.2.0
sparc                               defconfig    gcc-15.2.0
sparc                 randconfig-001-20260513    gcc-11.5.0
sparc                 randconfig-002-20260513    gcc-11.5.0
sparc64                          allmodconfig    clang-23
sparc64                             defconfig    gcc-14
sparc64               randconfig-001-20260513    gcc-11.5.0
sparc64               randconfig-002-20260513    gcc-11.5.0
um                               allmodconfig    clang-19
um                                allnoconfig    clang-23
um                               allyesconfig    gcc-14
um                               allyesconfig    gcc-15.2.0
um                                  defconfig    gcc-14
um                             i386_defconfig    gcc-14
um                    randconfig-001-20260513    gcc-11.5.0
um                    randconfig-002-20260513    gcc-11.5.0
um                           x86_64_defconfig    gcc-14
x86_64                           allmodconfig    clang-20
x86_64                            allnoconfig    clang-20
x86_64                            allnoconfig    clang-23
x86_64                           allyesconfig    clang-20
x86_64      buildonly-randconfig-001-20260513    gcc-12
x86_64      buildonly-randconfig-002-20260513    gcc-12
x86_64      buildonly-randconfig-003-20260513    gcc-12
x86_64      buildonly-randconfig-004-20260513    gcc-12
x86_64      buildonly-randconfig-005-20260513    gcc-12
x86_64      buildonly-randconfig-006-20260513    gcc-12
x86_64                              defconfig    gcc-14
x86_64                                  kexec    clang-20
x86_64                randconfig-011-20260513    gcc-14
x86_64                randconfig-012-20260513    gcc-14
x86_64                randconfig-013-20260513    gcc-14
x86_64                randconfig-014-20260513    gcc-14
x86_64                randconfig-015-20260513    gcc-14
x86_64                randconfig-016-20260513    gcc-14
x86_64                randconfig-071-20260513    gcc-14
x86_64                randconfig-072-20260513    gcc-14
x86_64                randconfig-073-20260513    gcc-14
x86_64                randconfig-074-20260513    gcc-14
x86_64                randconfig-075-20260513    gcc-14
x86_64                randconfig-076-20260513    gcc-14
x86_64                               rhel-9.4    clang-20
x86_64                           rhel-9.4-bpf    gcc-14
x86_64                          rhel-9.4-func    clang-20
x86_64                    rhel-9.4-kselftests    clang-20
x86_64                         rhel-9.4-kunit    gcc-14
x86_64                           rhel-9.4-ltp    gcc-14
x86_64                          rhel-9.4-rust    clang-20
xtensa                            allnoconfig    clang-23
xtensa                            allnoconfig    gcc-15.2.0
xtensa                           allyesconfig    clang-23
xtensa                randconfig-001-20260513    gcc-11.5.0
xtensa                randconfig-002-20260513    gcc-11.5.0

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply

* [PATCH 6.1.y] blk-cgroup: Fix NULL deref caused by blkg_policy_data being installed before init
From: Robert Garcia @ 2026-05-13  7:56 UTC (permalink / raw)
  To: stable, Tejun Heo
  Cc: Jens Axboe, Breno Leitao, Josef Bacik, Robert Garcia, cgroups,
	linux-block, linux-kernel

From: Tejun Heo <tj@kernel.org>

[ Upstream commit ec14a87ee1999b19d8b7ed0fa95fea80644624ae ]

blk-iocost sometimes causes the following crash:

  BUG: kernel NULL pointer dereference, address: 00000000000000e0
  ...
  RIP: 0010:_raw_spin_lock+0x17/0x30
  Code: be 01 02 00 00 e8 79 38 39 ff 31 d2 89 d0 5d c3 0f 1f 00 0f 1f 44 00 00 55 48 89 e5 65 ff 05 48 d0 34 7e b9 01 00 00 00 31 c0 <f0> 0f b1 0f 75 02 5d c3 89 c6 e8 ea 04 00 00 5d c3 0f 1f 84 00 00
  RSP: 0018:ffffc900023b3d40 EFLAGS: 00010046
  RAX: 0000000000000000 RBX: 00000000000000e0 RCX: 0000000000000001
  RDX: ffffc900023b3d20 RSI: ffffc900023b3cf0 RDI: 00000000000000e0
  RBP: ffffc900023b3d40 R08: ffffc900023b3c10 R09: 0000000000000003
  R10: 0000000000000064 R11: 000000000000000a R12: ffff888102337000
  R13: fffffffffffffff2 R14: ffff88810af408c8 R15: ffff8881070c3600
  FS:  00007faaaf364fc0(0000) GS:ffff88842fdc0000(0000) knlGS:0000000000000000
  CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
  CR2: 00000000000000e0 CR3: 00000001097b1000 CR4: 0000000000350ea0
  Call Trace:
   <TASK>
   ioc_weight_write+0x13d/0x410
   cgroup_file_write+0x7a/0x130
   kernfs_fop_write_iter+0xf5/0x170
   vfs_write+0x298/0x370
   ksys_write+0x5f/0xb0
   __x64_sys_write+0x1b/0x20
   do_syscall_64+0x3d/0x80
   entry_SYSCALL_64_after_hwframe+0x46/0xb0

This happens because iocg->ioc is NULL. The field is initialized by
ioc_pd_init() and never cleared. The NULL deref is caused by
blkcg_activate_policy() installing blkg_policy_data before initializing it.

blkcg_activate_policy() was doing the following:

1. Allocate pd's for all existing blkg's and install them in blkg->pd[].
2. Initialize all pd's.
3. Online all pd's.

blkcg_activate_policy() only grabs the queue_lock and may release and
re-acquire the lock as allocation may need to sleep. ioc_weight_write()
grabs blkcg->lock and iterates all its blkg's. The two can race and if
ioc_weight_write() runs during #1 or between #1 and #2, it can encounter a
pd which is not initialized yet, leading to crash.

The crash can be reproduced with the following script:

  #!/bin/bash

  echo +io > /sys/fs/cgroup/cgroup.subtree_control
  systemd-run --unit touch-sda --scope dd if=/dev/sda of=/dev/null bs=1M count=1 iflag=direct
  echo 100 > /sys/fs/cgroup/system.slice/io.weight
  bash -c "echo '8:0 enable=1' > /sys/fs/cgroup/io.cost.qos" &
  sleep .2
  echo 100 > /sys/fs/cgroup/system.slice/io.weight

with the following patch applied:

> diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
> index fc49be622e05..38d671d5e10c 100644
> --- a/block/blk-cgroup.c
> +++ b/block/blk-cgroup.c
> @@ -1553,6 +1553,12 @@ int blkcg_activate_policy(struct gendisk *disk, const struct blkcg_policy *pol)
> 		pd->online = false;
> 	}
>
> +       if (system_state == SYSTEM_RUNNING) {
> +               spin_unlock_irq(&q->queue_lock);
> +               ssleep(1);
> +               spin_lock_irq(&q->queue_lock);
> +       }
> +
> 	/* all allocated, init in the same order */
> 	if (pol->pd_init_fn)
> 		list_for_each_entry_reverse(blkg, &q->blkg_list, q_node)

I don't see a reason why all pd's should be allocated, initialized and
onlined together. The only ordering requirement is that parent blkgs to be
initialized and onlined before children, which is guaranteed from the
walking order. Let's fix the bug by allocating, initializing and onlining pd
for each blkg and holding blkcg->lock over initialization and onlining. This
ensures that an installed blkg is always fully initialized and onlined
removing the the race window.

Signed-off-by: Tejun Heo <tj@kernel.org>
Reported-by: Breno Leitao <leitao@debian.org>
Fixes: 9d179b865449 ("blkcg: Fix multiple bugs in blkcg_activate_policy()")
Link: https://lore.kernel.org/r/ZN0p5_W-Q9mAHBVY@slm.duckdns.org
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Robert Garcia <rob_garcia@163.com>
---
 block/blk-cgroup.c | 32 ++++++++++++++++++--------------
 1 file changed, 18 insertions(+), 14 deletions(-)

diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index f314192b6de8..ce074d9fb709 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -1392,7 +1392,7 @@ int blkcg_activate_policy(struct request_queue *q,
 retry:
 	spin_lock_irq(&q->queue_lock);
 
-	/* blkg_list is pushed at the head, reverse walk to allocate parents first */
+	/* blkg_list is pushed at the head, reverse walk to initialize parents first */
 	list_for_each_entry_reverse(blkg, &q->blkg_list, q_node) {
 		struct blkg_policy_data *pd;
 
@@ -1430,21 +1430,20 @@ int blkcg_activate_policy(struct request_queue *q,
 				goto enomem;
 		}
 
-		blkg->pd[pol->plid] = pd;
+		spin_lock(&blkg->blkcg->lock);
+
 		pd->blkg = blkg;
 		pd->plid = pol->plid;
-		pd->online = false;
-	}
+		blkg->pd[pol->plid] = pd;
 
-	/* all allocated, init in the same order */
-	if (pol->pd_init_fn)
-		list_for_each_entry_reverse(blkg, &q->blkg_list, q_node)
-			pol->pd_init_fn(blkg->pd[pol->plid]);
+		if (pol->pd_init_fn)
+			pol->pd_init_fn(pd);
 
-	list_for_each_entry_reverse(blkg, &q->blkg_list, q_node) {
 		if (pol->pd_online_fn)
-			pol->pd_online_fn(blkg->pd[pol->plid]);
-		blkg->pd[pol->plid]->online = true;
+			pol->pd_online_fn(pd);
+		pd->online = true;
+
+		spin_unlock(&blkg->blkcg->lock);
 	}
 
 	__set_bit(pol->plid, q->blkcg_pols);
@@ -1461,14 +1460,19 @@ int blkcg_activate_policy(struct request_queue *q,
 	return ret;
 
 enomem:
-	/* alloc failed, nothing's initialized yet, free everything */
+	/* alloc failed, take down everything */
 	spin_lock_irq(&q->queue_lock);
 	list_for_each_entry(blkg, &q->blkg_list, q_node) {
 		struct blkcg *blkcg = blkg->blkcg;
+		struct blkg_policy_data *pd;
 
 		spin_lock(&blkcg->lock);
-		if (blkg->pd[pol->plid]) {
-			pol->pd_free_fn(blkg->pd[pol->plid]);
+		pd = blkg->pd[pol->plid];
+		if (pd) {
+			if (pd->online && pol->pd_offline_fn)
+				pol->pd_offline_fn(pd);
+			pd->online = false;
+			pol->pd_free_fn(pd);
 			blkg->pd[pol->plid] = NULL;
 		}
 		spin_unlock(&blkcg->lock);
-- 
2.34.1


^ permalink raw reply related

* Re: [PATCH v2 10/10] sched/eevdf: Move to a single runqueue
From: Peter Zijlstra @ 2026-05-13  7:25 UTC (permalink / raw)
  To: K Prateek Nayak
  Cc: mingo, longman, chenridong, juri.lelli, vincent.guittot,
	dietmar.eggemann, rostedt, bsegall, mgorman, vschneid, tj, hannes,
	mkoutny, cgroups, linux-kernel, jstultz, qyousef
In-Reply-To: <dc4df15c-2f21-4141-ba7c-b2d8afbcd0c3@amd.com>

On Wed, May 13, 2026 at 12:31:05PM +0530, K Prateek Nayak wrote:
> Hello Peter,
> 
> On 5/12/2026 4:39 PM, Peter Zijlstra wrote:
> >> @@ -13819,6 +13831,12 @@ static void set_next_task_fair(struct rq *rq, struct task_struct *p, bool first)
> >>  		if (on_rq)
> >>  			weight = __calc_prop_weight(cfs_rq, se, weight);
> >>  	}
> >> +	/*
> >> +	 * Add throttle work if the bandwidth allocation above failed
> >> +	 * to grab any runtime and throttled the task's hierarchy.
> >> +	 */
> >> +	if (throttled_hierarchy(task_cfs_rq(p)))
> >> +		task_throttle_setup_work(p);
> > 
> > We already call into account_cfs_rq_runtime(); which basically does all
> > we need.
> > 
> > I think the distinction between account_cfs_rq_runtime() and
> > check_cfs_rq_runtime() no longer makes sense. We can throttle a cfs_rq
> > at any point now, since we no longer remove the cfs_rq, but rather we
> > make the tasks suspend themselves until the cfs_rq naturally dequeues
> > for being empty.
> > 
> > Something like so perhaps?
> 
> That makes sense! The task should naturally execute the task work when
> exiting out of the kernel / IRQ handler into the userspace so we should
> be good.
> 
> I'll rebase the below diff on tip, test it a bit, add a commit log, and
> send it your way if you don't mind or would you like to keep it with the
> flat_cg bits?

Nah, this seems like something that can be done independent. And thus is
should be. That flat patch is big enough as is.

^ permalink raw reply

* Re: [PATCH v2 00/10] sched: Flatten the pick
From: Peter Zijlstra @ 2026-05-13  7:25 UTC (permalink / raw)
  To: Vincent Guittot
  Cc: mingo, longman, chenridong, juri.lelli, dietmar.eggemann, rostedt,
	bsegall, mgorman, vschneid, tj, hannes, mkoutny, cgroups,
	linux-kernel, jstultz, kprateek.nayak, qyousef
In-Reply-To: <CAKfTPtBq6QO6yjL9SHWfL+pSoe=4_cddzYtqWGXtpLJmi8hSig@mail.gmail.com>

On Tue, May 12, 2026 at 08:32:12PM +0200, Vincent Guittot wrote:
> On Tue, 12 May 2026 at 20:25, Peter Zijlstra <peterz@infradead.org> wrote:
> >
> > On Tue, May 12, 2026 at 08:24:39PM +0200, Peter Zijlstra wrote:
> > > On Tue, May 12, 2026 at 11:20:40AM +0200, Peter Zijlstra wrote:
> > > > On Tue, May 12, 2026 at 10:42:33AM +0200, Vincent Guittot wrote:
> > > >
> > > > >
> > > > > I haven't reviewed the patches yet but I ran some tests with it while
> > > > > testing sched latency related changes for short slice wakeup
> > > > > preemption. I have some large hackbench regressions with this series
> > > > > on HMP system with and without EAS. those figures are unexpected
> > > > > because the benchs run on root cfs
> > > > >
> > > > > One example with hackbench 8 groups thread pipe
> > > > > tip/sched/core  tip/sched/core          +this patchset          +this patchset
> > > > > slice 2.8ms     16ms                    2.8ms                   16ms
> > > > > dragonboard rb5 with EAS
> > > > > 0,748(+/-4,6%)  0,621(+/-3.6%) +17%     1,915(+/-7.9%) -156%
> > > > > 0,689(+/- 9.1%) +8%
> > > > >
> > > > > radxa orion6 HMP without EAS
> > > > > 0,588(+/-5.8%)  0,677(+/-5.9%) -15%     1,505(+/-10%) -156%
> > > > > 1,071(+/-5.9%) -82%
> > > > >
> > > > > Increasing the slice partly removes regressions but tis is surprising
> > > > > because the bench runs at root cfs and I thought that results will not
> > > > > change in such a case
> > > > >
> > > > > I will review the patchset and try to get what is going wrong
> > > >
> > > > Yeah, that is unexpected. Let me go have another look too.
> > >
> > > So I can reproduce even without the last patch applied. I suspect it is
> > > in the cgroup mode patches somewhere. My first suspect is that concur
> > > mode thing doing bad things to track the 'global' nr_running thing.
> >
> > Argh, n/m PEBKAC. I'll try this again in the morning :/
> 
> Reverting the last patch is enough to recover performance

Yeah, I was on a fail-streak yesterday. I forgot to copy the kernel
image before reboot ...

Lets see if today is better :-)

^ permalink raw reply

* Re: [PATCH v2 10/10] sched/eevdf: Move to a single runqueue
From: K Prateek Nayak @ 2026-05-13  7:01 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: mingo, longman, chenridong, juri.lelli, vincent.guittot,
	dietmar.eggemann, rostedt, bsegall, mgorman, vschneid, tj, hannes,
	mkoutny, cgroups, linux-kernel, jstultz, qyousef
In-Reply-To: <20260512110932.GB1889694@noisy.programming.kicks-ass.net>

Hello Peter,

On 5/12/2026 4:39 PM, Peter Zijlstra wrote:
>> @@ -13819,6 +13831,12 @@ static void set_next_task_fair(struct rq *rq, struct task_struct *p, bool first)
>>  		if (on_rq)
>>  			weight = __calc_prop_weight(cfs_rq, se, weight);
>>  	}
>> +	/*
>> +	 * Add throttle work if the bandwidth allocation above failed
>> +	 * to grab any runtime and throttled the task's hierarchy.
>> +	 */
>> +	if (throttled_hierarchy(task_cfs_rq(p)))
>> +		task_throttle_setup_work(p);
> 
> We already call into account_cfs_rq_runtime(); which basically does all
> we need.
> 
> I think the distinction between account_cfs_rq_runtime() and
> check_cfs_rq_runtime() no longer makes sense. We can throttle a cfs_rq
> at any point now, since we no longer remove the cfs_rq, but rather we
> make the tasks suspend themselves until the cfs_rq naturally dequeues
> for being empty.
> 
> Something like so perhaps?

That makes sense! The task should naturally execute the task work when
exiting out of the kernel / IRQ handler into the userspace so we should
be good.

I'll rebase the below diff on tip, test it a bit, add a commit log, and
send it your way if you don't mind or would you like to keep it with the
flat_cg bits?

-- 
Thanks and Regards,
Prateek


^ permalink raw reply

* Re: [PATCH] cgroup/cpuset: Return only actually allocated CPUs during partition invalidation
From: Chen Ridong @ 2026-05-13  6:55 UTC (permalink / raw)
  To: Sun Shaojie, Waiman Long, Tejun Heo, Johannes Weiner,
	Michal Koutný
  Cc: cgroups, linux-kernel
In-Reply-To: <20260512090034.183133-1-sunshaojie@kylinos.cn>



On 2026/5/12 17:00, Sun Shaojie wrote:
> From: sunshaojie <sunshaojie@kylinos.cn>
> 
> In update_parent_effective_cpumask() with partcmd_invalidate, the CPUs
> to return to the parent are computed as:
> 
>     adding = cpumask_and(tmp->addmask, xcpus, parent->effective_xcpus);
> 
> where xcpus = user_xcpus(cs) which returns cs->exclusive_cpus (if set)
> or cs->cpus_allowed. When exclusive_cpus is not set, user_xcpus(cs) can
> contain CPUs that were never actually granted to the partition due to
> sibling exclusion in compute_excpus(). Consequently, the invalidation
> may return CPUs to the parent that remain in use by sibling partitions,
> causing overlapping effective_cpus and triggering the
> WARN_ON_ONCE(1) in generate_sched_domains().
> 
> Use cs->effective_xcpus instead, which reflects the CPUs actually
> granted to this partition.
> 
> Reproducer (on a 4-CPU machine):
> 
>     cd /sys/fs/cgroup
>     mkdir a1 b1
> 
>     # a1 becomes partition root with CPUs 0-1
>     echo "0-1" > a1/cpuset.cpus
>     echo "root" > a1/cpuset.cpus.partition
> 
>     # b1 becomes partition root with CPUs 1-2, but sibling exclusion
>     # reduces its effective_xcpus to CPU 2 only
>     echo "1-2" > b1/cpuset.cpus
>     echo "root" > b1/cpuset.cpus.partition
> 
>     # b1 changes cpus_allowed to 0-1 -> partition invalidation
>     echo "0-1" > b1/cpuset.cpus
> 
>     # Expected: CPUs 2-3  (only CPU 2 returned from b1)
>     # Actual:   CPUs 1-3  (CPU 0-1 returned, overlapping with a1)
>     cat cpuset.cpus.effective
> 

Thank you for providing the reproducer. I was able to reproduce the issue.

#cd /sys/fs/cgroup
#mkdir a1 b1
#
#echo "0-1" > a1/cpuset.cpus
#echo "root" > a1/cpuset.cpus.partition
#echo "1-2" > b1/cpuset.cpus
#echo "root" > b1/cpuset.cpus.partition
#echo "0-1" > b1/cpuset.cpus
#cat cpuset.cpus.effective
1-3


 WARNING: kernel/cgroup/cpuset.c:867 at
rebuild_sched_domains_locked+0x32c/0x510, CPU#3: bash/540
 Modules linked in:
 CPU: 3 UID: 0 PID: 540 Comm: bash Not tainted 7.1.0-rc2-next-20260508 #1122
PREEMPT(full)
 Call Trace:
  <TASK>
  ? kfree+0x1fb/0x540
  ? update_cpumasks_hier+0x34d/0xa30
  cpuset_update_sd_hk_unlock+0x7b/0x90
  cpuset_write_resmask+0x3f0/0xc70
  kernfs_fop_write_iter+0x14c/0x200
  vfs_write+0x362/0x510
  ksys_write+0x6b/0xe0
  do_syscall_64+0xba/0x5a0
  entry_SYSCALL_64_after_hwframe+0x4b/0x53

And this patch can fix this issue.

> dmesg will also show a WARNING from generate_sched_domains() reporting
> overlapping partition root effective_cpus.
> 
> Fixes: 0c7f293efc87 ("cgroup/cpuset: Add cpuset.cpus.exclusive.effective for v2")
> Signed-off-by: sunshaojie <sunshaojie@kylinos.cn>

I think the Fixes tag should point to commit 2a3602030d80 ("cgroup/cpuset: Don't
invalidate sibling partitions on cpuset.cpus conflict"). Before this commit, the
issue should not have been reproducible, since a1/b1 would have been invalidated
if they were in conflict. No warning is observed in dmesg when resetting to
commit 7cc1720589d8 ("cpuset: remove v1-specific code from generate_sched_domains").

Other than that, the patch looks good to me.

Test-by: Chen Ridong <chenridong@huaweicloud.com>
Reviewed-by: Chen Ridong <chenridong@huaweicloud.com>

> ---
>  kernel/cgroup/cpuset.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
> index 1335e437098e..2311470ef077 100644
> --- a/kernel/cgroup/cpuset.c
> +++ b/kernel/cgroup/cpuset.c
> @@ -1715,7 +1715,8 @@ static int update_parent_effective_cpumask(struct cpuset *cs, int cmd,
>  		 */
>  		if (is_partition_valid(parent))
>  			adding = cpumask_and(tmp->addmask,
> -					     xcpus, parent->effective_xcpus);
> +					     cs->effective_xcpus,
> +					     parent->effective_xcpus);
>  		if (old_prs > 0)
>  			new_prs = -old_prs;
>  

-- 
Best regards,
Ridong


^ permalink raw reply

* Re: [PATCH v3 05/12] mm, swap: unify large folio allocation
From: Kairui Song @ 2026-05-13  6:47 UTC (permalink / raw)
  To: Baolin Wang
  Cc: linux-mm, Andrew Morton, David Hildenbrand, Zi Yan, Barry Song,
	Hugh Dickins, Chris Li, Kemeng Shi, Nhat Pham, Baoquan He,
	Johannes Weiner, Youngjun Park, Chengming Zhou, Roman Gushchin,
	Shakeel Butt, Muchun Song, Qi Zheng, linux-kernel, cgroups,
	Yosry Ahmed, Lorenzo Stoakes, Dev Jain, Lance Yang, Michal Hocko,
	Michal Hocko, Suren Baghdasaryan, Axel Rasmussen
In-Reply-To: <d5341d37-5644-4446-a406-9a7251b83399@linux.alibaba.com>

On Tue, May 12, 2026 at 6:14 PM Baolin Wang
<baolin.wang@linux.alibaba.com> wrote:
>
> On 4/21/26 2:16 PM, Kairui Song via B4 Relay wrote:
> > From: Kairui Song <kasong@tencent.com>
> >
> > Now that direct large order allocation is supported in the swap cache,
> > both anon and shmem can use it instead of implementing their own methods.
> > This unifies the fallback and swap cache check, which also reduces the
> > TOCTOU race window of swap cache state: previously, high order swapin
> > required checking swap cache states first, then allocating and falling
> > back separately. Now all these steps happen in the same compact loop.
> >
> > Order fallback and statistics are also unified, callers just need to
> > check and pass the acceptable order bitmask.
> >
> > There is basically no behavior change. This only makes things more
> > unified and prepares for later commits. Cgroup and zero map checks can
> > also be moved into the compact loop, further reducing race windows and
> > redundancy
> >
> > Signed-off-by: Kairui Song <kasong@tencent.com>
> > ---
> >   mm/memory.c     |  77 ++++++------------------------
> >   mm/shmem.c      |  94 +++++++++---------------------------
> >   mm/swap.h       |  30 ++----------
> >   mm/swap_state.c | 145 ++++++++++----------------------------------------------
> >   mm/swapfile.c   |   3 +-
> >   5 files changed, 67 insertions(+), 282 deletions(-)
> >
> > diff --git a/mm/memory.c b/mm/memory.c
> > index ea6568571131..404734a5bcff 100644
> > --- a/mm/memory.c
> > +++ b/mm/memory.c
> > @@ -4593,26 +4593,6 @@ static vm_fault_t handle_pte_marker(struct vm_fault *vmf)
> >       return VM_FAULT_SIGBUS;
> >   }
> >
> > -static struct folio *__alloc_swap_folio(struct vm_fault *vmf)
> > -{
> > -     struct vm_area_struct *vma = vmf->vma;
> > -     struct folio *folio;
> > -     softleaf_t entry;
> > -
> > -     folio = vma_alloc_folio(GFP_HIGHUSER_MOVABLE, 0, vma, vmf->address);
> > -     if (!folio)
> > -             return NULL;
> > -
> > -     entry = softleaf_from_pte(vmf->orig_pte);
> > -     if (mem_cgroup_swapin_charge_folio(folio, vma->vm_mm,
> > -                                        GFP_KERNEL, entry)) {
> > -             folio_put(folio);
> > -             return NULL;
> > -     }
> > -
> > -     return folio;
> > -}
> > -
> >   #ifdef CONFIG_TRANSPARENT_HUGEPAGE
> >   /*
> >    * Check if the PTEs within a range are contiguous swap entries
> > @@ -4642,8 +4622,6 @@ static bool can_swapin_thp(struct vm_fault *vmf, pte_t *ptep, int nr_pages)
> >        */
> >       if (unlikely(swap_zeromap_batch(entry, nr_pages, NULL) != nr_pages))
> >               return false;
> > -     if (unlikely(non_swapcache_batch(entry, nr_pages) != nr_pages))
> > -             return false;
> >
> >       return true;
> >   }
> > @@ -4671,16 +4649,14 @@ static inline unsigned long thp_swap_suitable_orders(pgoff_t swp_offset,
> >       return orders;
> >   }
> >
> > -static struct folio *alloc_swap_folio(struct vm_fault *vmf)
> > +static unsigned long thp_swapin_suitable_orders(struct vm_fault *vmf)
> >   {
> >       struct vm_area_struct *vma = vmf->vma;
> >       unsigned long orders;
> > -     struct folio *folio;
> >       unsigned long addr;
> >       softleaf_t entry;
> >       spinlock_t *ptl;
> >       pte_t *pte;
> > -     gfp_t gfp;
> >       int order;
> >
> >       /*
> > @@ -4688,7 +4664,7 @@ static struct folio *alloc_swap_folio(struct vm_fault *vmf)
> >        * maintain the uffd semantics.
> >        */
> >       if (unlikely(userfaultfd_armed(vma)))
> > -             goto fallback;
> > +             return 0;
> >
> >       /*
> >        * A large swapped out folio could be partially or fully in zswap. We
> > @@ -4696,7 +4672,7 @@ static struct folio *alloc_swap_folio(struct vm_fault *vmf)
> >        * folio.
> >        */
> >       if (!zswap_never_enabled())
> > -             goto fallback;
> > +             return 0;
> >
> >       entry = softleaf_from_pte(vmf->orig_pte);
> >       /*
> > @@ -4710,12 +4686,12 @@ static struct folio *alloc_swap_folio(struct vm_fault *vmf)
> >                                         vmf->address, orders);
> >
> >       if (!orders)
> > -             goto fallback;
> > +             return 0;
> >
> >       pte = pte_offset_map_lock(vmf->vma->vm_mm, vmf->pmd,
> >                                 vmf->address & PMD_MASK, &ptl);
> >       if (unlikely(!pte))
> > -             goto fallback;
> > +             return 0;
> >
> >       /*
> >        * For do_swap_page, find the highest order where the aligned range is
> > @@ -4731,29 +4707,12 @@ static struct folio *alloc_swap_folio(struct vm_fault *vmf)
> >
> >       pte_unmap_unlock(pte, ptl);
> >
> > -     /* Try allocating the highest of the remaining orders. */
> > -     gfp = vma_thp_gfp_mask(vma);
> > -     while (orders) {
> > -             addr = ALIGN_DOWN(vmf->address, PAGE_SIZE << order);
> > -             folio = vma_alloc_folio(gfp, order, vma, addr);
> > -             if (folio) {
> > -                     if (!mem_cgroup_swapin_charge_folio(folio, vma->vm_mm,
> > -                                                         gfp, entry))
> > -                             return folio;
> > -                     count_mthp_stat(order, MTHP_STAT_SWPIN_FALLBACK_CHARGE);
> > -                     folio_put(folio);
> > -             }
> > -             count_mthp_stat(order, MTHP_STAT_SWPIN_FALLBACK);
> > -             order = next_order(&orders, order);
> > -     }
> > -
> > -fallback:
> > -     return __alloc_swap_folio(vmf);
> > +     return orders;
> >   }
> >   #else /* !CONFIG_TRANSPARENT_HUGEPAGE */
> > -static struct folio *alloc_swap_folio(struct vm_fault *vmf)
> > +static unsigned long thp_swapin_suitable_orders(struct vm_fault *vmf)
> >   {
> > -     return __alloc_swap_folio(vmf);
> > +     return 0;
> >   }
> >   #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
> >
> > @@ -4859,21 +4818,13 @@ vm_fault_t do_swap_page(struct vm_fault *vmf)
> >       if (folio)
> >               swap_update_readahead(folio, vma, vmf->address);
> >       if (!folio) {
> > -             if (data_race(si->flags & SWP_SYNCHRONOUS_IO)) {
> > -                     folio = alloc_swap_folio(vmf);
> > -                     if (folio) {
> > -                             /*
> > -                              * folio is charged, so swapin can only fail due
> > -                              * to raced swapin and return NULL.
> > -                              */
> > -                             swapcache = swapin_folio(entry, folio);
> > -                             if (swapcache != folio)
> > -                                     folio_put(folio);
> > -                             folio = swapcache;
> > -                     }
> > -             } else {
> > +             /* Swapin bypasses readahead for SWP_SYNCHRONOUS_IO devices */
> > +             if (data_race(si->flags & SWP_SYNCHRONOUS_IO))
> > +                     folio = swapin_entry(entry, GFP_HIGHUSER_MOVABLE,
> > +                                          thp_swapin_suitable_orders(vmf),
> > +                                          vmf, NULL, 0);
> > +             else
> >                       folio = swapin_readahead(entry, GFP_HIGHUSER_MOVABLE, vmf);
> > -             }
> >
> >               if (!folio) {
> >                       /*
> > diff --git a/mm/shmem.c b/mm/shmem.c
> > index 5916acf594a8..17e3da11bb1d 100644
> > --- a/mm/shmem.c
> > +++ b/mm/shmem.c
> > @@ -159,7 +159,7 @@ static unsigned long shmem_default_max_inodes(void)
> >
> >   static int shmem_swapin_folio(struct inode *inode, pgoff_t index,
> >                       struct folio **foliop, enum sgp_type sgp, gfp_t gfp,
> > -                     struct vm_area_struct *vma, vm_fault_t *fault_type);
> > +                     struct vm_fault *vmf, vm_fault_t *fault_type);
> >
> >   static inline struct shmem_sb_info *SHMEM_SB(struct super_block *sb)
> >   {
> > @@ -2017,68 +2017,24 @@ static struct folio *shmem_alloc_and_add_folio(struct vm_fault *vmf,
> >   }
> >
> >   static struct folio *shmem_swap_alloc_folio(struct inode *inode,
> > -             struct vm_area_struct *vma, pgoff_t index,
> > +             struct vm_fault *vmf, pgoff_t index,
> >               swp_entry_t entry, int order, gfp_t gfp)
> >   {
> > +     pgoff_t ilx;
> > +     struct folio *folio;
> > +     struct mempolicy *mpol;
> > +     unsigned long orders = BIT(order);
> >       struct shmem_inode_info *info = SHMEM_I(inode);
> > -     struct folio *new, *swapcache;
> > -     int nr_pages = 1 << order;
> > -     gfp_t alloc_gfp = gfp;
> > -
> > -     if (!IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE)) {
> > -             if (WARN_ON_ONCE(order))
> > -                     return ERR_PTR(-EINVAL);
> > -     } else if (order) {
> > -             /*
> > -              * If uffd is active for the vma, we need per-page fault
> > -              * fidelity to maintain the uffd semantics, then fallback
> > -              * to swapin order-0 folio, as well as for zswap case.
> > -              * Any existing sub folio in the swap cache also blocks
> > -              * mTHP swapin.
> > -              */
> > -             if ((vma && unlikely(userfaultfd_armed(vma))) ||
> > -                  !zswap_never_enabled() ||
> > -                  non_swapcache_batch(entry, nr_pages) != nr_pages)
> > -                     goto fallback;
> >
> > -             alloc_gfp = thp_limit_gfp_mask(vma_thp_gfp_mask(vma), gfp);
> > -     }
> > -retry:
> > -     new = shmem_alloc_folio(alloc_gfp, order, info, index);
> > -     if (!new) {
> > -             new = ERR_PTR(-ENOMEM);
> > -             goto fallback;
> > -     }
> > +     if ((vmf && unlikely(userfaultfd_armed(vmf->vma))) ||
> > +          !zswap_never_enabled())
> > +             orders = 0;
> >
> > -     if (mem_cgroup_swapin_charge_folio(new, vma ? vma->vm_mm : NULL,
> > -                                        alloc_gfp, entry)) {
> > -             folio_put(new);
> > -             new = ERR_PTR(-ENOMEM);
> > -             goto fallback;
> > -     }
> > +     mpol = shmem_get_pgoff_policy(info, index, order, &ilx);
> > +     folio = swapin_entry(entry, gfp, orders, vmf, mpol, ilx);
> > +     mpol_cond_put(mpol);
> >
> > -     swapcache = swapin_folio(entry, new);
> > -     if (swapcache != new) {
> > -             folio_put(new);
> > -             if (!swapcache) {
> > -                     /*
> > -                      * The new folio is charged already, swapin can
> > -                      * only fail due to another raced swapin.
> > -                      */
> > -                     new = ERR_PTR(-EEXIST);
> > -                     goto fallback;
> > -             }
> > -     }
> > -     return swapcache;
> > -fallback:
> > -     /* Order 0 swapin failed, nothing to fallback to, abort */
> > -     if (!order)
> > -             return new;
> > -     entry.val += index - round_down(index, nr_pages);
> > -     alloc_gfp = gfp;
> > -     nr_pages = 1;
> > -     order = 0;
> > -     goto retry;
> > +     return folio;
> >   }
>
> IIUC, in the __swap_cache_alloc() implementation in patch 4, when shmem
> swapin falls back to order 0, it doesn't adjust the swap entry value
> like here. Because the original swap entry may not correspond to the
> swap entry for the order 0 index.
>
> Of course, I haven't tested this yet, just pointing it out for you to
> double check.

Thanks for pointing it out. No worry, we have the below change in this
commit already:

                        /* Direct swapin skipping swap cache & readahead */
-                       folio = shmem_swap_alloc_folio(inode, vma, index,
-                                                      index_entry, order, gfp);
-                       if (IS_ERR(folio)) {
-                               error = PTR_ERR(folio);
-                               folio = NULL;
-                               goto failed;
-                       }
+                       folio = shmem_swap_alloc_folio(inode, vmf, index,
+                                                      swap, order, gfp);

It's using swap instead of index_entry now, so __swap_cache_alloc will
do the round down for large order instead and skip the round_down if
ordedr is zero. So we are fine here.

^ permalink raw reply

* Re: [PATCH v2 10/10] sched/eevdf: Move to a single runqueue
From: John Stultz @ 2026-05-13  5:00 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: mingo, longman, chenridong, juri.lelli, vincent.guittot,
	dietmar.eggemann, rostedt, bsegall, mgorman, vschneid, tj, hannes,
	mkoutny, cgroups, linux-kernel, kprateek.nayak, qyousef
In-Reply-To: <CANDhNCp1rcNYg29Fe66G6cuqHhDyXQ0oqccheSwfMuiNV-7Bgw@mail.gmail.com>

On Tue, May 12, 2026 at 9:51 PM John Stultz <jstultz@google.com> wrote:
>
> On Mon, May 11, 2026 at 5:07 AM Peter Zijlstra <peterz@infradead.org> wrote:
> >
> > Change fair/cgroup to a single runqueue.
> >
...
>
> I know Vincent was having some perf troubles with this patch, but
> booting on a 64 vCPU qemu environment, I'm seeing:
>
> [    5.688490] Oops: divide error: 0000 [#1] SMP NOPTI
> [    5.689457] CPU: 47 UID: 0 PID: 0 Comm: swapper/47 Not tainted
> 7.1.0-rc2-00026-g82a8ec6fb3f9 #38 PREEMPT(full)
> [    5.689457] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996),
> BIOS 1.17.0-debian-1.17.0-1 04/01/2014
> [    5.689457] RIP: 0010:wakeup_preempt_fair+0x1b7/0x430
> [    5.689457] Code: 74 0b 48 8b 52 28 48 39 d0 48 0f 47 c2 48 8b b9
> 90 00 00 00 48 8b b1 08 01 00 00 48 81 ff 00 00 10 00 74 09 48 c1 e0
> 14 31 9
> [    5.689457] RSP: 0000:ffffc9000021fd70 EFLAGS: 00010046
> [    5.689457] RAX: 000002ab98000000 RBX: ffff8881b8e2db40 RCX: ffffffff83022a80
> [    5.689457] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
> [    5.689457] RBP: 0000000000000001 R08: ffff88810cb14380 R09: ffffffff83022b00
> [    5.689457] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000002
> [    5.689457] R13: 0000000000000000 R14: ffff88810cb14300 R15: ffff8881b8e2da00
> [    5.689457] FS:  0000000000000000(0000) GS:ffff888235c2e000(0000)
> knlGS:0000000000000000
> [    5.689457] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> [    5.689457] CR2: 0000000000000000 CR3: 000000000304c001 CR4: 0000000000370ef0
> [    5.689457] Call Trace:
> [    5.689457]  <TASK>
> [    5.689457]  wakeup_preempt+0xa8/0xd0
> [    5.689457]  attach_one_task+0xec/0x150
> [    5.689457]  __schedule+0x1ad8/0x21c0
> [    5.689457]  schedule_idle+0x22/0x40
> [    5.689457]  cpu_startup_entry+0x29/0x30
> [    5.689457]  start_secondary+0xf7/0x100
> [    5.689457]  common_startup_64+0x13e/0x148
> [    5.689457]  </TASK>
> [    5.689457] Dumping ftrace buffer:
> [    5.689457]    (ftrace buffer empty)
> [    5.689457] ---[ end trace 0000000000000000 ]---
> [    5.689457] RIP: 0010:wakeup_preempt_fair+0x1b7/0x430
> [    5.689457] Code: 74 0b 48 8b 52 28 48 39 d0 48 0f 47 c2 48 8b b9
> 90 00 00 00 48 8b b1 08 01 00 00 48 81 ff 00 00 10 00 74 09 48 c1 e0
> 14 31 9
> [    5.689457] RSP: 0000:ffffc9000021fd70 EFLAGS: 00010046
> [    5.689457] RAX: 000002ab98000000 RBX: ffff8881b8e2db40 RCX: ffffffff83022a80
> [    5.689457] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
> [    5.689457] RBP: 0000000000000001 R08: ffff88810cb14380 R09: ffffffff83022b00
> [    5.689457] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000002
> [    5.689457] R13: 0000000000000000 R14: ffff88810cb14300 R15: ffff8881b8e2da00
> [    5.689457] FS:  0000000000000000(0000) GS:ffff888235c2e000(0000)
> knlGS:0000000000000000
> [    5.689457] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> [    5.689457] CR2: 0000000000000000 CR3: 000000000304c001 CR4: 0000000000370ef0
> [    5.689457] Kernel panic - not syncing: Fatal exception
>
> Which I bisected down to this last patch in the series.
>
> faddr2line gave me:
> __calc_delta at kernel/sched/fair.c:290
> (inlined by) calc_delta_fair at kernel/sched/fair.c:300
> (inlined by) update_protect_slice at kernel/sched/fair.c:1070
> (inlined by) wakeup_preempt_fair at kernel/sched/fair.c:9193
>
> This usually trips as the ww_mutex selftest starts at bootup.
>
> Unfortunately I still see it with the add-on changes you proposed to K
> Prateek's feedback here.
>
> I'll try to narrow it down further tomorrow.

As karma would have it, this does seem to depend on CONFIG_SCHED_PROXY_EXEC. :)
I'm guessing the switch in calc_delta_fair() to use se->h_load is
uncovering something proxy isn't handling properly with that value.

But I'll have more tomorrow.

thanks
-john

^ permalink raw reply

* Re: [PATCH v2 10/10] sched/eevdf: Move to a single runqueue
From: John Stultz @ 2026-05-13  4:51 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: mingo, longman, chenridong, juri.lelli, vincent.guittot,
	dietmar.eggemann, rostedt, bsegall, mgorman, vschneid, tj, hannes,
	mkoutny, cgroups, linux-kernel, kprateek.nayak, qyousef
In-Reply-To: <20260511120628.206700041@infradead.org>

On Mon, May 11, 2026 at 5:07 AM Peter Zijlstra <peterz@infradead.org> wrote:
>
> Change fair/cgroup to a single runqueue.
>
> Infamously fair/cgroup isn't working for a number of people; typically
> the complaint is latencies and/or overhead. The latency issue is due
> to the intermediate entries that represent a combination of tasks and
> thereby obfuscate the runnability of tasks.
>
> The approach here is to leave the cgroup hierarchy as is; including
> the intermediate enqueue/dequeue but move the actual EEVDF runqueue
> outside. This means things like the shares_weight approximation are
> fully preserved.
>
> That is, given a hierarchy like:
>
>         R
>         |
>         se--G1
>             / \
>       G2--se   se--G3
>      / \           |
> T1--se se--T2      se--T3
>
> This is fully maintained for load tracking, however the EEVDF parts of
> cfs_rq/se go unused for the intermediates and are instead connected
> like:
>
>      _R_
>     / | \
>    T1 T2 T3
>
> Since the effective weight of the entities is determined by the
> hierarchy, this gets recomputed on enqueue,set_next_task and tick.
>
> Notably, the effective weight (se->h_load) is computed from the
> hierarchical fraction: se->load / cfs_rq->load.
>
> Since EEVDF is now exclusive operating on rq->cfs, it needs to
> consider cfs_rq->h_nr_queued rather than cfs_rq->nr_queued. Similarly,
> only tasks can get delayed, simplifying some of the cgroup cleanup.
>
> One place where additional information was required was
> set_next_task() / put_prev_task(), where we need to track 'current'
> both in the hierarchical sense (cfs_rq->h_curr) and in the flat sense
> (cfs_rq->curr).
>
> As a result of only having a single level to pick from, much of the
> complications in pick_next_task() and preemption go away.
>
> Since many of the hierarchical operations are still there, this won't
> immediately fix the performance issues, but hopefully it will fix some
> of the latency issues.
>
> TODO: split struct cfs_rq / struct sched_entity
> TODO: try and get rid of h_curr
>
> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>

I know Vincent was having some perf troubles with this patch, but
booting on a 64 vCPU qemu environment, I'm seeing:

[    5.688490] Oops: divide error: 0000 [#1] SMP NOPTI
[    5.689457] CPU: 47 UID: 0 PID: 0 Comm: swapper/47 Not tainted
7.1.0-rc2-00026-g82a8ec6fb3f9 #38 PREEMPT(full)
[    5.689457] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996),
BIOS 1.17.0-debian-1.17.0-1 04/01/2014
[    5.689457] RIP: 0010:wakeup_preempt_fair+0x1b7/0x430
[    5.689457] Code: 74 0b 48 8b 52 28 48 39 d0 48 0f 47 c2 48 8b b9
90 00 00 00 48 8b b1 08 01 00 00 48 81 ff 00 00 10 00 74 09 48 c1 e0
14 31 9
[    5.689457] RSP: 0000:ffffc9000021fd70 EFLAGS: 00010046
[    5.689457] RAX: 000002ab98000000 RBX: ffff8881b8e2db40 RCX: ffffffff83022a80
[    5.689457] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
[    5.689457] RBP: 0000000000000001 R08: ffff88810cb14380 R09: ffffffff83022b00
[    5.689457] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000002
[    5.689457] R13: 0000000000000000 R14: ffff88810cb14300 R15: ffff8881b8e2da00
[    5.689457] FS:  0000000000000000(0000) GS:ffff888235c2e000(0000)
knlGS:0000000000000000
[    5.689457] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[    5.689457] CR2: 0000000000000000 CR3: 000000000304c001 CR4: 0000000000370ef0
[    5.689457] Call Trace:
[    5.689457]  <TASK>
[    5.689457]  wakeup_preempt+0xa8/0xd0
[    5.689457]  attach_one_task+0xec/0x150
[    5.689457]  __schedule+0x1ad8/0x21c0
[    5.689457]  schedule_idle+0x22/0x40
[    5.689457]  cpu_startup_entry+0x29/0x30
[    5.689457]  start_secondary+0xf7/0x100
[    5.689457]  common_startup_64+0x13e/0x148
[    5.689457]  </TASK>
[    5.689457] Dumping ftrace buffer:
[    5.689457]    (ftrace buffer empty)
[    5.689457] ---[ end trace 0000000000000000 ]---
[    5.689457] RIP: 0010:wakeup_preempt_fair+0x1b7/0x430
[    5.689457] Code: 74 0b 48 8b 52 28 48 39 d0 48 0f 47 c2 48 8b b9
90 00 00 00 48 8b b1 08 01 00 00 48 81 ff 00 00 10 00 74 09 48 c1 e0
14 31 9
[    5.689457] RSP: 0000:ffffc9000021fd70 EFLAGS: 00010046
[    5.689457] RAX: 000002ab98000000 RBX: ffff8881b8e2db40 RCX: ffffffff83022a80
[    5.689457] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
[    5.689457] RBP: 0000000000000001 R08: ffff88810cb14380 R09: ffffffff83022b00
[    5.689457] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000002
[    5.689457] R13: 0000000000000000 R14: ffff88810cb14300 R15: ffff8881b8e2da00
[    5.689457] FS:  0000000000000000(0000) GS:ffff888235c2e000(0000)
knlGS:0000000000000000
[    5.689457] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[    5.689457] CR2: 0000000000000000 CR3: 000000000304c001 CR4: 0000000000370ef0
[    5.689457] Kernel panic - not syncing: Fatal exception

Which I bisected down to this last patch in the series.

faddr2line gave me:
__calc_delta at kernel/sched/fair.c:290
(inlined by) calc_delta_fair at kernel/sched/fair.c:300
(inlined by) update_protect_slice at kernel/sched/fair.c:1070
(inlined by) wakeup_preempt_fair at kernel/sched/fair.c:9193

This usually trips as the ww_mutex selftest starts at bootup.

Unfortunately I still see it with the add-on changes you proposed to K
Prateek's feedback here.

I'll try to narrow it down further tomorrow.

thanks
-john

^ permalink raw reply

* [PATCH] selftests/cgroup: Fix error path leaks in test_percpu_basic
From: Yu Miao @ 2026-05-13  2:39 UTC (permalink / raw)
  To: Johannes Weiner, Michal Hocko, Roman Gushchin, Shakeel Butt,
	Tejun Heo, Michal Koutný, Shuah Khan
  Cc: Muchun Song, cgroups, linux-mm, linux-kselftest, linux-kernel,
	Yu Miao

When cg_name_indexed() returns NULL partway through the child creation
loop, the code returned -1 without running cleanup_children and cleanup.
That left the `parent` pathname allocation unreleased and did not remove
child cgroup directories already created under the parent. Fix by jumping
to cleanup_children instead of returning.

When cg_create() fails, `child` (the pathname from cg_name_indexed())
was not freed before cleanup_children. Fix by freeing `child` before
branching to cleanup_children.

Signed-off-by: Yu Miao <yumiao@kylinos.cn>
---
 tools/testing/selftests/cgroup/test_kmem.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/tools/testing/selftests/cgroup/test_kmem.c b/tools/testing/selftests/cgroup/test_kmem.c
index eeabd34bf083..12f59925500b 100644
--- a/tools/testing/selftests/cgroup/test_kmem.c
+++ b/tools/testing/selftests/cgroup/test_kmem.c
@@ -368,11 +368,15 @@ static int test_percpu_basic(const char *root)
 
 	for (i = 0; i < 1000; i++) {
 		child = cg_name_indexed(parent, "child", i);
-		if (!child)
-			return -1;
+		if (!child) {
+			ret = -1;
+			goto cleanup_children;
+		}
 
-		if (cg_create(child))
+		if (cg_create(child)) {
+			free(child);
 			goto cleanup_children;
+		}
 
 		free(child);
 	}
-- 
2.43.0


^ permalink raw reply related

* Re: [linus:master] [mm] 01b9da291c: stress-ng.switch.ops_per_sec 67.7% regression
From: Qi Zheng @ 2026-05-13  2:10 UTC (permalink / raw)
  To: Shakeel Butt, kernel test robot
  Cc: oe-lkp, lkp, linux-kernel, Andrew Morton, David Carlier,
	Allen Pais, Axel Rasmussen, Baoquan He, Chengming Zhou,
	Chen Ridong, David Hildenbrand, Hamza Mahfooz, Harry Yoo,
	Hugh Dickins, Imran Khan, Johannes Weiner, Kamalesh Babulal,
	Lance Yang, Liam Howlett, Lorenzo Stoakes, Michal Hocko,
	Michal Koutný, Mike Rapoport, Muchun Song, Muchun Song,
	Nhat Pham, Roman Gushchin, Suren Baghdasaryan, Usama Arif,
	Vlastimil Babka, Wei Xu, Yosry Ahmed, Yuanchu Xie, Zi Yan,
	Usama Arif, cgroups, linux-mm
In-Reply-To: <agNO8G8tPnPuVrGq@linux.dev>



On 5/13/26 12:03 AM, Shakeel Butt wrote:
> On Tue, May 12, 2026 at 08:56:52PM +0800, kernel test robot wrote:
>>
>>
>> Hello,
>>
>> kernel test robot noticed a 67.7% regression of stress-ng.switch.ops_per_sec on:
>>
>>
>> commit: 01b9da291c4969354807b52956f4aae1f41b4924 ("mm: memcontrol: convert objcg to be per-memcg per-node type")
>> https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git master
> 
> This is most probably due to shuffling of struct mem_cgroup and struct
> mem_cgroup_per_node members.

Another possibility is that after objcg was split into per-node, the
slab accounting fast path is still designed assuming only one current
objcg per CPU:

struct obj_stock_pcp {
     struct obj_cgroup *cached_objcg;
};

So it's may cause the following thrashing:

  CPU stock cached = memcg/node0 objcg
  free object tagged = memcg/node1 objcg
  => __refill_obj_stock --> objcg mismatch
      => drain_obj_stock()
      => cache switches to node1 objcg

  next local allocation tagged = node0 objcg
  => mismatch again
      => drain_obj_stock()


> 
> I will try to reproduce and will followup on this.

Thanks! I'll also try to reproduce it locally and work on a fix.



^ permalink raw reply

* Re: [PATCH 0/3] cgroup/rdma: add rdma.peak and rdma.events[.local]
From: Tao Cui @ 2026-05-13  1:51 UTC (permalink / raw)
  To: Tejun Heo; +Cc: hannes, mkoutny, cgroups
In-Reply-To: <8545cad8e29f27e927e76c7bbe1334ea@kernel.org>

Hello,tejun

Thank you very much for your review.

在 2026/5/13 1:49, Tejun Heo 写道:
> * Patches 2 and 3 don't extend the rpool-free condition in
>   uncharge_cg_locked() and rdmacg_resource_set_max() to the new event
>   counters, so a "set limit -> hit limit -> uncharge to 0 -> write
>   'max max'" sequence frees the rpool and zeros the counts.
> 
The rpool-free condition in both uncharge_cg_locked()
and rdmacg_resource_set_max() only checks peak but misses the event
counters (events_max, events_local_max, events_fail).  This means a
non-zero event counter can be silently discarded when the rpool is
freed.  I'll add a helper that checks all persistent data (peak +
event counters) and use it in both sites.

> * rdmacg_event_locked() creates rpools in ancestors of over_cg via
>   get_cg_rpool_locked() just to host event counters. Those rpools have
>   usage_sum==0, num_max_cnt==max, peak==0, so the next real uncharge
>   through any such ancestor frees them.
> 
Agreed.  Using get_cg_rpool_locked() in the propagation loop was wrong
-- it allocates rpools in ancestors that never had any resource
configuration for the device, just to hold an event counter.  These
empty rpools then get freed on the next uncharge, losing the event
data.  I'll switch to find_cg_rpool_locked() so events are only
recorded in rpools that already exist.

> * Patch 3 says failcnt covers "this cgroup (or its descendants)" but
>   the code only increments the directly-requesting cgroup. Either the
>   description or the propagation is wrong.
> 
The description is wrong.  The code only increments failcnt in the
directly-requesting cgroup, not in its ancestors, which is consistent
with how pids.events.local tracks local attribution.  I'll fix the
commit message to say "originating from this cgroup" instead of
"originating from this cgroup or its descendants".

> * rdma.events / rdma.events.local print "mlx4_0 hca_handle.max 5
>   hca_object.max 0 " (trailing space). That doesn't match any of the
>   formats in Documentation/admin-guide/cgroup-v2.rst. rdma.current and
>   rdma.max are nested-keyed; the new files should be too:
>   "mlx4_0 hca_handle.max=5 hca_object.max=0".
> 
Will fix.  I'll switch to the nested-keyed format with '=' and remove
the trailing space so the output matches rdma.max / rdma.current:

    mlx4_0 hca_handle.max=5 hca_object.max=0

> * Please document rdma.peak / rdma.events / rdma.events.local in
>   Documentation/admin-guide/cgroup-v2.rst.
> 
Will add in the next revision.

> * "failcnt" is cgroup-v1 vocabulary; pids.events.local uses
>   "fork_fail" for the same role.
> 
Agreed.  I'll rename "failcnt" to "fail" to follow the cgroup-v2
naming convention.

> * Event counters are atomic64_t but all updates are under
>   rdmacg_mutex. Plain u64 with READ_ONCE on the read side would do.
> 
I also noticed this.  I have a version using plain u64 with READ_ONCE
on the read side, and it is currently being tested locally.  Since the
change touches a hot path in the charge/uncharge code, I want to be
cautious and verify that there are no regressions before sending it
out.

> * Patch 1 reflows an unrelated comment ("No user of the rpool ...");
>   please drop the churn.
> 
Sorry for the noise.  I'll revert the comment reflow and keep the
original formatting.

I'll send v2 with all the fixes above.  Thank you for the thorough
review.

Thanks.

--
Tao

^ permalink raw reply

* Re: [PATCH v2 2/3] security: Expand task_setscheduler LSM hook to include CPU affinity mask
From: Aaron Tomlin @ 2026-05-12 19:48 UTC (permalink / raw)
  To: Paul Moore
  Cc: tsbogend, jmorris, serge, mingo, peterz, juri.lelli,
	vincent.guittot, stephen.smalley.work, casey, longman, tj, hannes,
	mkoutny, chenridong, dietmar.eggemann, rostedt, bsegall, mgorman,
	vschneid, kprateek.nayak, omosnace, kees, neelx, sean, chjohnst,
	steve, mproche, nick.lange, cgroups, linux-mips, linux-fsdevel,
	linux-security-module, selinux, linux-kernel
In-Reply-To: <CAHC9VhQthq7y2akbQSdJwBEex1MQYWG49wcJK3b8gSQuQ_d1cQ@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 2353 bytes --]

On Mon, May 11, 2026 at 04:28:09PM -0400, Paul Moore wrote:
[ ... ]
> > Signed-off-by: Aaron Tomlin <atomlin@atomlin.com>
> > ---
> >  arch/mips/kernel/mips-mt-fpaff.c | 30 +++++++++++++++++-------------
> >  fs/proc/base.c                   |  2 +-
> >  include/linux/lsm_hook_defs.h    |  3 ++-
> >  include/linux/security.h         | 11 +++++++----
> >  kernel/cgroup/cpuset.c           |  4 ++--
> >  kernel/sched/syscalls.c          |  4 ++--
> >  security/commoncap.c             |  7 +++++--
> >  security/security.c              | 11 ++++++-----
> >  security/selinux/hooks.c         |  3 ++-
> >  security/smack/smack_lsm.c       | 11 +++++++++--
> >  10 files changed, 53 insertions(+), 33 deletions(-)
> 
> I haven't looked too closely at this patch yet, but based on a quick
> glance, can you help me understand why it is included with the other
> two patches in one patchset?  The other two patches look like stable
> level kernel bug fixes, while this patch introduces functionality to
> an existing LSM hook; one of these is not like the others :)
> 
> Unless there is something critical that I'm missing here, I would
> suggest splitting this patch out from the other two bugfixes for
> separate handling.  If there is a patch dependency issue you can
> always mention that in the cover letter.

Hi Paul,

Thank you for taking the time to have a look.

You raise a perfectly valid point.

Please note, the cgroup-related BUG fix will be dropped from the next
iteration of this series. As per Waiman Long (on Cc), a solution for the
BUG was already proposed here [1].

However, I suspect the MIPS-related patch will need to remain coupled with
this feature patch. Because the first patch fundamentally alters the
signature of the security_task_setscheduler() hook, the MIPS FPU affinity
code must be updated concurrently to accommodate the new parameter.
Separating them into entirely different series would likely invite
bisection breakages or awkward merge conflicts, depending on the order in
which they are applied, no?

If this approach sounds sensible to you, I shall prepare a v2 series
reflecting this restructured grouping.

Please let me know your thoughts.

[1]: https://lore.kernel.org/lkml/20260509102031.97608-2-zhangguopeng@kylinos.cn/

Kind regards,
-- 
Aaron Tomlin

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply

* Re: [PATCH 1/3] cgroup/cpuset: Fix deadline bandwidth leak in cpuset_can_attach()
From: Aaron Tomlin @ 2026-05-12 19:37 UTC (permalink / raw)
  To: Waiman Long
  Cc: tsbogend, paul, jmorris, serge, mingo, peterz, juri.lelli,
	vincent.guittot, stephen.smalley.work, casey, tj, hannes, mkoutny,
	chenridong, dietmar.eggemann, rostedt, bsegall, mgorman, vschneid,
	kprateek.nayak, omosnace, kees, neelx, sean, chjohnst, steve,
	mproche, nick.lange, cgroups, linux-mips, linux-fsdevel,
	linux-security-module, selinux, linux-kernel
In-Reply-To: <354af9fc-1c70-4ee4-a0ff-8821bebec7b8@redhat.com>

On Mon, May 11, 2026 at 01:54:37PM -0400, Waiman Long wrote:
> Yes, it does look like the AI feedback is valid. I will take a further look
> into this.

Hi,

As promised [1], please find my suggested patch here [2].

[1]: https://lore.kernel.org/lkml/dif4xi73znyz3diguyxihzztgosvyj3bjeh3y3oidg4gnt2qpv@5nygeq3rk333/
[2]: https://lore.kernel.org/lkml/20260512010341.101419-1-atomlin@atomlin.com/

Kind regards,
-- 
Aaron Tomlin

^ permalink raw reply

* Re: [PATCH RFC 2/5] dma-heap: charge dma-buf memory via explicit memcg
From: T.J. Mercier @ 2026-05-12 18:53 UTC (permalink / raw)
  To: Christian König
  Cc: Albert Esteve, Tejun Heo, Johannes Weiner, Michal Koutný,
	Jonathan Corbet, Shuah Khan, Sumit Semwal, Michal Hocko,
	Roman Gushchin, Shakeel Butt, Muchun Song, Andrew Morton,
	Benjamin Gaignard, Brian Starkey, John Stultz, Christian Brauner,
	Paul Moore, James Morris, Serge E. Hallyn, Stephen Smalley,
	Ondrej Mosnacek, Shuah Khan, cgroups, linux-doc, linux-kernel,
	linux-media, dri-devel, linaro-mm-sig, linux-mm,
	linux-security-module, selinux, linux-kselftest, mripard,
	echanude
In-Reply-To: <8ef38815-6ae9-4359-86d4-042554357639@amd.com>

On Tue, May 12, 2026 at 3:14 AM Christian König
<christian.koenig@amd.com> wrote:
>
> On 5/12/26 11:10, Albert Esteve wrote:
> > On embedded platforms a central process often allocates dma-buf
> > memory on behalf of client applications. Without a way to
> > attribute the charge to the requesting client's cgroup, the
> > cost lands on the allocator, making per-cgroup memory limits
> > ineffective for the actual consumers.
> >
> > Add charge_pid_fd to struct dma_heap_allocation_data. When set to
> > a valid pidfd, DMA_HEAP_IOCTL_ALLOC resolves the target task's
> > memcg and charges the buffer there via mem_cgroup_charge_dmabuf()
> > inside dma_heap_buffer_alloc(). Without charge_pid_fd, and with
> > the mem_accounting module parameter enabled, the buffer is charged
> > to the allocator's own cgroup.
> >
> > Additionally, commit 3c227be90659 ("dma-buf: system_heap: account for
> > system heap allocation in memcg") adds __GFP_ACCOUNT to system-heap
> > page allocations. Keeping __GFP_ACCOUNT would charge the same pages
> > twice (once to kmem, once to MEMCG_DMABUF), thus remove it and route
> > all accounting through a single MEMCG_DMABUF path.
> >
> > Usage examples:
> >
> >   1. Central allocator charging to a client at allocation time.
> >      The allocator knows the client's PID (e.g., from binder's
> >      sender_pid) and uses pidfd to attribute the charge:
> >
> >        pid_t client_pid = txn->sender_pid;
> >        int pidfd = pidfd_open(client_pid, 0);
> >
> >        struct dma_heap_allocation_data alloc = {
> >            .len             = buffer_size,
> >            .fd_flags        = O_RDWR | O_CLOEXEC,
> >            .charge_pid_fd   = pidfd,
> >        };
> >        ioctl(heap_fd, DMA_HEAP_IOCTL_ALLOC, &alloc);
> >        close(pidfd);
> >        /* alloc.fd is now charged to client's cgroup */
> >
> >   2. Default allocation (no pidfd, mem_accounting=1).
> >      When charge_pid_fd is not set and the mem_accounting module
> >      parameter is enabled, the buffer is charged to the allocator's
> >      own cgroup:
> >
> >        struct dma_heap_allocation_data alloc = {
> >            .len      = buffer_size,
> >            .fd_flags = O_RDWR | O_CLOEXEC,
> >        };
> >        ioctl(heap_fd, DMA_HEAP_IOCTL_ALLOC, &alloc);
> >        /* charged to current process's cgroup */
> >
> > Current limitations:
> >
> >  - Single-owner model: a dma-buf carries one memcg charge regardless of
> >    how many processes share it. Means only the first owner (and exporter)
> >    of the shared buffer bears the charge.
> >  - Only memcg accounting supported. While this makes sense for system
> >    heap buffers, other heaps (e.g., CMA heaps) will require selectively
> >    charging also for the dmem controller.
>
> Well that doesn't looks soo bad, it at least seems to tackle the problem at hand for Android and some of other embedded use cases.

Yeah I think this might work. I know of 3 cases, and it trivially
solves the first two. The third requires some work on our end to
extend our userspace interfaces to include the pidfd but it seems
doable. I'm checking with our graphics folks.

1) Direct allocation from user (e.g. app -> allocation ioctl on
/dev/dma_heap/foo)
No changes required to userspace. mem_accounting=1 charges the app.

2) Single hop remote allocation (e.g. app -> AHardwareBuffer_allocate
-> gralloc)
gralloc has the caller's pid as described in the commit message. Open
a pidfd and pass it in the dma_heap_allocation_data.

3) Double hop remote allocation (e.g. app -> dequeueBuffer ->
SurfaceFlinger -> gralloc)
In this case gralloc knows SurfaceFlinger's pid, but not the app's. So
we need to add the app's pidfd to the SurfaceFlinger -> gralloc
interface, or transfer the memcg charge from SurfaceFlinger to the app
after the allocation.
It'd be nice to avoid the charge transfer option entirely, but if we
need it that doesn't seem so bad in this case because it's a bulk
charge for the entire dmabuf rather than per-page. So the exporter
doesn't need to get involved (we wouldn't need a new dma_buf_op) and
we wouldn't have to worry about looping and locking for each page.

> I'm just not sure if this is future prove and will work for all use cases, e.g. cloud gaming, native context for automotive etc...
>
> Essentially the problem boils down to two limitations:
> 1) a piece of memory can only be charged to one cgroup, the framework doesn't has a concept of charging shared memory to multiple groups

Yup, memcg already has this problem with pagecache and shmem.

> 2) when memory references in the form of file descriptors are passed between applications we have no way of changing the accounting to a different cgroup
>
> The passing of the memory reference already has a well defined uAPI and if we could solve those two limitations we not only solve the problem without introducing new uAPI (with potential new security risks) but also solve it for all other use cases which uses file descriptors as well as. E.g. memfd, accel and GPU drivers etc...
>
> On the other hand it is really nice to finally see this tackled for at least DMA-buf heaps.

I have a question about this part. Albert I guess you are interested
only in accounting dmabuf-heap allocations, or do you expect to add
__GFP_ACCOUNT or mem_cgroup_charge_dmabuf calls to other
non-dmabuf-heap exporters?

> On the GPU side I have seen just another try of a driver doing some kind of special driver specific accounting to solve this just a few weeks ago. And to be honest such single driver island approach have the tendency to break more often that they are working correctly.
>
> Regards,
> Christian.
>
> >
> > Signed-off-by: Albert Esteve <aesteve@redhat.com>
> > ---
> >  Documentation/admin-guide/cgroup-v2.rst |  5 ++--
> >  drivers/dma-buf/dma-buf.c               | 16 ++++---------
> >  drivers/dma-buf/dma-heap.c              | 42 ++++++++++++++++++++++++++++++---
> >  drivers/dma-buf/heaps/system_heap.c     |  2 --
> >  include/uapi/linux/dma-heap.h           |  6 +++++
> >  5 files changed, 53 insertions(+), 18 deletions(-)
> >
> > diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst
> > index 8bdbc2e866430..824d269531eb1 100644
> > --- a/Documentation/admin-guide/cgroup-v2.rst
> > +++ b/Documentation/admin-guide/cgroup-v2.rst
> > @@ -1636,8 +1636,9 @@ The following nested keys are defined.
> >               structures.
> >
> >         dmabuf (npn)
> > -             Amount of memory used for exported DMA buffers allocated by the cgroup.
> > -             Stays with the allocating cgroup regardless of how the buffer is shared.
> > +             Amount of memory used for exported DMA buffers allocated by or on
> > +             behalf of the cgroup. Stays with the allocating cgroup regardless
> > +             of how the buffer is shared.
> >
> >         workingset_refault_anon
> >               Number of refaults of previously evicted anonymous pages.
> > diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
> > index ce02377f48908..23fb758b78297 100644
> > --- a/drivers/dma-buf/dma-buf.c
> > +++ b/drivers/dma-buf/dma-buf.c
> > @@ -181,8 +181,11 @@ static void dma_buf_release(struct dentry *dentry)
> >        */
> >       BUG_ON(dmabuf->cb_in.active || dmabuf->cb_out.active);
> >
> > -     mem_cgroup_uncharge_dmabuf(dmabuf->memcg, PAGE_ALIGN(dmabuf->size) / PAGE_SIZE);
> > -     mem_cgroup_put(dmabuf->memcg);
> > +     if (dmabuf->memcg) {
> > +             mem_cgroup_uncharge_dmabuf(dmabuf->memcg,
> > +                                       PAGE_ALIGN(dmabuf->size) / PAGE_SIZE);
> > +             mem_cgroup_put(dmabuf->memcg);
> > +     }
> >
> >       dmabuf->ops->release(dmabuf);
> >
> > @@ -764,13 +767,6 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
> >               dmabuf->resv = resv;
> >       }
> >
> > -     dmabuf->memcg = get_mem_cgroup_from_mm(current->mm);
> > -     if (!mem_cgroup_charge_dmabuf(dmabuf->memcg, PAGE_ALIGN(dmabuf->size) / PAGE_SIZE,
> > -                                   GFP_KERNEL)) {
> > -             ret = -ENOMEM;
> > -             goto err_memcg;
> > -     }
> > -
> >       file->private_data = dmabuf;
> >       file->f_path.dentry->d_fsdata = dmabuf;
> >       dmabuf->file = file;
> > @@ -781,8 +777,6 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
> >
> >       return dmabuf;
> >
> > -err_memcg:
> > -     mem_cgroup_put(dmabuf->memcg);
> >  err_file:
> >       fput(file);
> >  err_module:
> > diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c
> > index ac5f8685a6494..ff6e259afcdc0 100644
> > --- a/drivers/dma-buf/dma-heap.c
> > +++ b/drivers/dma-buf/dma-heap.c
> > @@ -7,13 +7,17 @@
> >   */
> >
> >  #include <linux/cdev.h>
> > +#include <linux/cgroup.h>
> >  #include <linux/device.h>
> >  #include <linux/dma-buf.h>
> >  #include <linux/dma-heap.h>
> > +#include <linux/memcontrol.h>
> > +#include <linux/sched/mm.h>
> >  #include <linux/err.h>
> >  #include <linux/export.h>
> >  #include <linux/list.h>
> >  #include <linux/nospec.h>
> > +#include <linux/pidfd.h>
> >  #include <linux/syscalls.h>
> >  #include <linux/uaccess.h>
> >  #include <linux/xarray.h>
> > @@ -55,10 +59,12 @@ MODULE_PARM_DESC(mem_accounting,
> >                "Enable cgroup-based memory accounting for dma-buf heap allocations (default=false).");
> >
> >  static int dma_heap_buffer_alloc(struct dma_heap *heap, size_t len,
> > -                              u32 fd_flags,
> > -                              u64 heap_flags)
> > +                              u32 fd_flags, u64 heap_flags,
> > +                              struct mem_cgroup *charge_to)
> >  {
> >       struct dma_buf *dmabuf;
> > +     unsigned int nr_pages;
> > +     struct mem_cgroup *memcg = charge_to;
> >       int fd;
> >
> >       /*
> > @@ -73,6 +79,22 @@ static int dma_heap_buffer_alloc(struct dma_heap *heap, size_t len,
> >       if (IS_ERR(dmabuf))
> >               return PTR_ERR(dmabuf);
> >
> > +     nr_pages = len / PAGE_SIZE;
> > +
> > +     if (memcg)
> > +             css_get(&memcg->css);
> > +     else if (mem_accounting)
> > +             memcg = get_mem_cgroup_from_mm(current->mm);
> > +
> > +     if (memcg) {
> > +             if (!mem_cgroup_charge_dmabuf(memcg, nr_pages, GFP_KERNEL)) {
> > +                     mem_cgroup_put(memcg);
> > +                     dma_buf_put(dmabuf);
> > +                     return -ENOMEM;
> > +             }
> > +             dmabuf->memcg = memcg;
> > +     }
> > +
> >       fd = dma_buf_fd(dmabuf, fd_flags);
> >       if (fd < 0) {
> >               dma_buf_put(dmabuf);
> > @@ -102,6 +124,9 @@ static long dma_heap_ioctl_allocate(struct file *file, void *data)
> >  {
> >       struct dma_heap_allocation_data *heap_allocation = data;
> >       struct dma_heap *heap = file->private_data;
> > +     struct mem_cgroup *memcg = NULL;
> > +     struct task_struct *task;
> > +     unsigned int pidfd_flags;
> >       int fd;
> >
> >       if (heap_allocation->fd)
> > @@ -113,9 +138,20 @@ static long dma_heap_ioctl_allocate(struct file *file, void *data)
> >       if (heap_allocation->heap_flags & ~DMA_HEAP_VALID_HEAP_FLAGS)
> >               return -EINVAL;
> >
> > +     if (heap_allocation->charge_pid_fd) {
> > +             task = pidfd_get_task(heap_allocation->charge_pid_fd, &pidfd_flags);
> > +             if (IS_ERR(task))
> > +                     return PTR_ERR(task);
> > +
> > +             memcg = get_mem_cgroup_from_mm(task->mm);
> > +             put_task_struct(task);
> > +     }
> > +
> >       fd = dma_heap_buffer_alloc(heap, heap_allocation->len,
> >                                  heap_allocation->fd_flags,
> > -                                heap_allocation->heap_flags);
> > +                                heap_allocation->heap_flags,
> > +                                memcg);
> > +     mem_cgroup_put(memcg);
> >       if (fd < 0)
> >               return fd;
> >
> > diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/system_heap.c
> > index 03c2b87cb1112..95d7688167b93 100644
> > --- a/drivers/dma-buf/heaps/system_heap.c
> > +++ b/drivers/dma-buf/heaps/system_heap.c
> > @@ -385,8 +385,6 @@ static struct page *alloc_largest_available(unsigned long size,
> >               if (max_order < orders[i])
> >                       continue;
> >               flags = order_flags[i];
> > -             if (mem_accounting)
> > -                     flags |= __GFP_ACCOUNT;
> >               page = alloc_pages(flags, orders[i]);
> >               if (!page)
> >                       continue;
> > diff --git a/include/uapi/linux/dma-heap.h b/include/uapi/linux/dma-heap.h
> > index a4cf716a49fa6..e02b0f8cbc6a1 100644
> > --- a/include/uapi/linux/dma-heap.h
> > +++ b/include/uapi/linux/dma-heap.h
> > @@ -29,6 +29,10 @@
> >   *                   handle to the allocated dma-buf
> >   * @fd_flags:                file descriptor flags used when allocating
> >   * @heap_flags:              flags passed to heap
> > + * @charge_pid_fd:   optional pidfd of the process whose cgroup should be
> > + *                   charged for this allocation; 0 means charge the calling
> > + *                   process's cgroup
> > + * @__padding:               reserved, must be zero
> >   *
> >   * Provided by userspace as an argument to the ioctl
> >   */
> > @@ -37,6 +41,8 @@ struct dma_heap_allocation_data {
> >       __u32 fd;
> >       __u32 fd_flags;
> >       __u64 heap_flags;
> > +     __u32 charge_pid_fd;
> > +     __u32 __padding;
> >  };
> >
> >  #define DMA_HEAP_IOC_MAGIC           'H'
> >
>

^ permalink raw reply

* Re: [PATCH v2 00/10] sched: Flatten the pick
From: Tejun Heo @ 2026-05-12 18:45 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: mingo, longman, chenridong, juri.lelli, vincent.guittot,
	dietmar.eggemann, rostedt, bsegall, mgorman, vschneid, hannes,
	mkoutny, cgroups, linux-kernel, jstultz, kprateek.nayak, qyousef
In-Reply-To: <20260512081000.GL3102624@noisy.programming.kicks-ass.net>

Hello, Peter.

On Tue, May 12, 2026 at 10:10:00AM +0200, Peter Zijlstra wrote:
...
> Anyway, this is why I've been looking at these alternative weight
> schemes, to get the nominal fraction near 1 and make these problems go
> away. It is both the numerical issues and the disparity between levels
> (with root being at level 0 being the most obvious).

I see. I think what bothers me is that I'm unsure what the weight config
would mean when the shares are scaled by the number of active cpus in that
cgroup. Here's a simple example:

- There are 256 cpus.
- /cgroup-A has weight 100 and 128 active threads. No pinning.
- /cgroup-B has weight 100 and 256 active thredas. No pinning.

In the current code, assuming math holds up, cgroup-A and B would get about
the same shares - ~128 CPUs each. However, if we scale the share by active
CPUs in each cgroup, B's tasks would end up with the same weight as A's on
CPUs that they end up competing on, which would lead to ~ 1:3 distribution.
Is that the right reading of the code?

Thanks.

-- 
tejun

^ permalink raw reply

* Re: [PATCH v2 00/10] sched: Flatten the pick
From: Vincent Guittot @ 2026-05-12 18:32 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: mingo, longman, chenridong, juri.lelli, dietmar.eggemann, rostedt,
	bsegall, mgorman, vschneid, tj, hannes, mkoutny, cgroups,
	linux-kernel, jstultz, kprateek.nayak, qyousef
In-Reply-To: <20260512182530.GB2855641@noisy.programming.kicks-ass.net>

On Tue, 12 May 2026 at 20:25, Peter Zijlstra <peterz@infradead.org> wrote:
>
> On Tue, May 12, 2026 at 08:24:39PM +0200, Peter Zijlstra wrote:
> > On Tue, May 12, 2026 at 11:20:40AM +0200, Peter Zijlstra wrote:
> > > On Tue, May 12, 2026 at 10:42:33AM +0200, Vincent Guittot wrote:
> > >
> > > >
> > > > I haven't reviewed the patches yet but I ran some tests with it while
> > > > testing sched latency related changes for short slice wakeup
> > > > preemption. I have some large hackbench regressions with this series
> > > > on HMP system with and without EAS. those figures are unexpected
> > > > because the benchs run on root cfs
> > > >
> > > > One example with hackbench 8 groups thread pipe
> > > > tip/sched/core  tip/sched/core          +this patchset          +this patchset
> > > > slice 2.8ms     16ms                    2.8ms                   16ms
> > > > dragonboard rb5 with EAS
> > > > 0,748(+/-4,6%)  0,621(+/-3.6%) +17%     1,915(+/-7.9%) -156%
> > > > 0,689(+/- 9.1%) +8%
> > > >
> > > > radxa orion6 HMP without EAS
> > > > 0,588(+/-5.8%)  0,677(+/-5.9%) -15%     1,505(+/-10%) -156%
> > > > 1,071(+/-5.9%) -82%
> > > >
> > > > Increasing the slice partly removes regressions but tis is surprising
> > > > because the bench runs at root cfs and I thought that results will not
> > > > change in such a case
> > > >
> > > > I will review the patchset and try to get what is going wrong
> > >
> > > Yeah, that is unexpected. Let me go have another look too.
> >
> > So I can reproduce even without the last patch applied. I suspect it is
> > in the cgroup mode patches somewhere. My first suspect is that concur
> > mode thing doing bad things to track the 'global' nr_running thing.
>
> Argh, n/m PEBKAC. I'll try this again in the morning :/

Reverting the last patch is enough to recover performance

^ permalink raw reply

* Re: [PATCH v2 00/10] sched: Flatten the pick
From: Peter Zijlstra @ 2026-05-12 18:25 UTC (permalink / raw)
  To: Vincent Guittot
  Cc: mingo, longman, chenridong, juri.lelli, dietmar.eggemann, rostedt,
	bsegall, mgorman, vschneid, tj, hannes, mkoutny, cgroups,
	linux-kernel, jstultz, kprateek.nayak, qyousef
In-Reply-To: <20260512182439.GA2855641@noisy.programming.kicks-ass.net>

On Tue, May 12, 2026 at 08:24:39PM +0200, Peter Zijlstra wrote:
> On Tue, May 12, 2026 at 11:20:40AM +0200, Peter Zijlstra wrote:
> > On Tue, May 12, 2026 at 10:42:33AM +0200, Vincent Guittot wrote:
> > 
> > > 
> > > I haven't reviewed the patches yet but I ran some tests with it while
> > > testing sched latency related changes for short slice wakeup
> > > preemption. I have some large hackbench regressions with this series
> > > on HMP system with and without EAS. those figures are unexpected
> > > because the benchs run on root cfs
> > > 
> > > One example with hackbench 8 groups thread pipe
> > > tip/sched/core  tip/sched/core          +this patchset          +this patchset
> > > slice 2.8ms     16ms                    2.8ms                   16ms
> > > dragonboard rb5 with EAS
> > > 0,748(+/-4,6%)  0,621(+/-3.6%) +17%     1,915(+/-7.9%) -156%
> > > 0,689(+/- 9.1%) +8%
> > > 
> > > radxa orion6 HMP without EAS
> > > 0,588(+/-5.8%)  0,677(+/-5.9%) -15%     1,505(+/-10%) -156%
> > > 1,071(+/-5.9%) -82%
> > > 
> > > Increasing the slice partly removes regressions but tis is surprising
> > > because the bench runs at root cfs and I thought that results will not
> > > change in such a case
> > > 
> > > I will review the patchset and try to get what is going wrong
> > 
> > Yeah, that is unexpected. Let me go have another look too.
> 
> So I can reproduce even without the last patch applied. I suspect it is
> in the cgroup mode patches somewhere. My first suspect is that concur
> mode thing doing bad things to track the 'global' nr_running thing.

Argh, n/m PEBKAC. I'll try this again in the morning :/

^ permalink raw reply

* Re: [PATCH v2 00/10] sched: Flatten the pick
From: Peter Zijlstra @ 2026-05-12 18:24 UTC (permalink / raw)
  To: Vincent Guittot
  Cc: mingo, longman, chenridong, juri.lelli, dietmar.eggemann, rostedt,
	bsegall, mgorman, vschneid, tj, hannes, mkoutny, cgroups,
	linux-kernel, jstultz, kprateek.nayak, qyousef
In-Reply-To: <20260512092040.GN3102624@noisy.programming.kicks-ass.net>

On Tue, May 12, 2026 at 11:20:40AM +0200, Peter Zijlstra wrote:
> On Tue, May 12, 2026 at 10:42:33AM +0200, Vincent Guittot wrote:
> 
> > 
> > I haven't reviewed the patches yet but I ran some tests with it while
> > testing sched latency related changes for short slice wakeup
> > preemption. I have some large hackbench regressions with this series
> > on HMP system with and without EAS. those figures are unexpected
> > because the benchs run on root cfs
> > 
> > One example with hackbench 8 groups thread pipe
> > tip/sched/core  tip/sched/core          +this patchset          +this patchset
> > slice 2.8ms     16ms                    2.8ms                   16ms
> > dragonboard rb5 with EAS
> > 0,748(+/-4,6%)  0,621(+/-3.6%) +17%     1,915(+/-7.9%) -156%
> > 0,689(+/- 9.1%) +8%
> > 
> > radxa orion6 HMP without EAS
> > 0,588(+/-5.8%)  0,677(+/-5.9%) -15%     1,505(+/-10%) -156%
> > 1,071(+/-5.9%) -82%
> > 
> > Increasing the slice partly removes regressions but tis is surprising
> > because the bench runs at root cfs and I thought that results will not
> > change in such a case
> > 
> > I will review the patchset and try to get what is going wrong
> 
> Yeah, that is unexpected. Let me go have another look too.

So I can reproduce even without the last patch applied. I suspect it is
in the cgroup mode patches somewhere. My first suspect is that concur
mode thing doing bad things to track the 'global' nr_running thing.



^ permalink raw reply

* Re: [RFC PATCH v5 20/29] sched/deadline: Allow deeper hierarchies of RT cgroups
From: Tejun Heo @ 2026-05-12 18:20 UTC (permalink / raw)
  To: Yuri Andriaccio
  Cc: luca abeni, Peter Zijlstra, Yuri Andriaccio, Ingo Molnar,
	Juri Lelli, Vincent Guittot, Dietmar Eggemann, Steven Rostedt,
	Ben Segall, Mel Gorman, Valentin Schneider, linux-kernel, hannes,
	mkoutny, cgroups
In-Reply-To: <b549b3cb062f2823ba6d4723b7b9260b@kernel.org>

On Tue, May 12, 2026 at 08:19:02AM -1000, Tejun Heo wrote:
> How is a delegated subtree prevented from setting cpu.rt.min = 'root' and
> escaping its ancestors' cpu.rt.max budget?

Hmm.. I guess the same problem exists w/ separate rt controller too. If the
users on the system already started using rt, how do you enable the
controller from the top down with budgets already being used down in the
hierarchy?

Thanks.

-- 
tejun

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox