> diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h > index f3b8c71870d8..1083be5d0362 100644 > --- a/include/linux/memcontrol.h > +++ b/include/linux/memcontrol.h [ ... ] > +#else /* CONFIG_BPF_SYSCALL */ > + > +static inline unsigned long > +bpf_memcg_get_high_delay(struct mem_cgroup *memcg) { return 0; } > +static inline bpf_memcg_below_low(struct mem_cgroup *memcg) { return false; } > +static inline bpf_memcg_below_min(struct mem_cgroup *memcg) { return false; } ^^^^^^^^^^^^^^^^^^^^ These two stubs are missing the bool return type. This will cause a compilation error when CONFIG_BPF_SYSCALL is not set. Should these be: static inline bool bpf_memcg_below_low(...) static inline bool bpf_memcg_below_min(...) > +static inline void memcontrol_bpf_online(struct mem_cgroup *memcg) { } > +static inline void memcontrol_bpf_offline(struct mem_cgroup *memcg) { } > + > +#endif /* CONFIG_BPF_SYSCALL */ [ ... ] > diff --git a/mm/bpf_memcontrol.c b/mm/bpf_memcontrol.c > index 716df49d7647..20c5c3552ce3 100644 > --- a/mm/bpf_memcontrol.c > +++ b/mm/bpf_memcontrol.c [ ... ] > +static int bpf_memcg_ops_reg(void *kdata, struct bpf_link *link) > +{ > + struct bpf_struct_ops_link *ops_link > + = container_of(link, struct bpf_struct_ops_link, link); > + struct memcg_bpf_ops *ops = kdata; > + struct mem_cgroup *memcg, *iter = NULL; > + int err = 0; > + > + memcg = mem_cgroup_get_from_ino(ops_link->cgroup_id); > + if (IS_ERR_OR_NULL(memcg)) > + return PTR_ERR(memcg); > + > + cgroup_lock(); > + while ((iter = mem_cgroup_iter(memcg, iter, NULL))) { > + if (READ_ONCE(iter->bpf_ops)) { > + mem_cgroup_iter_break(memcg, iter); > + err = -EBUSY; > + break; > + } > + WRITE_ONCE(iter->bpf_ops, ops); > + } > + if (err) > + clean_memcg_bpf_ops(memcg, NULL); ^^^^ When registration fails because a descendant cgroup already has a BPF program attached, this calls clean_memcg_bpf_ops() with NULL. Looking at clean_memcg_bpf_ops(): while ((iter = mem_cgroup_iter(memcg, iter, NULL))) { if (ops) { if (!WARN_ON(READ_ONCE(iter->bpf_ops) != ops)) WRITE_ONCE(iter->bpf_ops, NULL); } else WRITE_ONCE(iter->bpf_ops, NULL); // unconditional clear } With ops=NULL, this will unconditionally clear bpf_ops for all descendants in the hierarchy, including the cgroup that already had a different BPF program attached (which caused the -EBUSY error). This would incorrectly detach that existing program. Should this be clean_memcg_bpf_ops(memcg, ops) instead, so it only clears the ops that were written during this failed registration attempt? Note: This issue appears to be addressed in the subsequent commit 5f3bb9a8c33f ("mm/bpf: Add BPF_F_ALLOW_OVERRIDE support for memcg_bpf_ops") which completely rewrites the registration logic. > + cgroup_unlock(); > + > + mem_cgroup_put(memcg); > + return err; > +} --- AI reviewed your patch. Please fix the bug or email reply why it's not a bug. See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md CI run summary: https://github.com/kernel-patches/bpf/actions/runs/21352241149