struct cgroup_rstat_cpu __percpu *rstat_cpu;
        struct list_head rstat_css_list;
 
+       /*
+        * A singly-linked list of cgroup structures to be rstat flushed.
+        * This is a scratch field to be used exclusively by
+        * cgroup_rstat_flush_locked() and protected by cgroup_rstat_lock.
+        */
+       struct cgroup   *rstat_flush_next;
+
        /* cgroup basic resource statistics */
        struct cgroup_base_stat last_bstat;
        struct cgroup_base_stat bstat;
 
        return pos;
 }
 
+/* Return a list of updated cgroups to be flushed */
+static struct cgroup *cgroup_rstat_updated_list(struct cgroup *root, int cpu)
+{
+       raw_spinlock_t *cpu_lock = per_cpu_ptr(&cgroup_rstat_cpu_lock, cpu);
+       struct cgroup *head, *tail, *next;
+       unsigned long flags;
+
+       /*
+        * The _irqsave() is needed because cgroup_rstat_lock is
+        * spinlock_t which is a sleeping lock on PREEMPT_RT. Acquiring
+        * this lock with the _irq() suffix only disables interrupts on
+        * a non-PREEMPT_RT kernel. The raw_spinlock_t below disables
+        * interrupts on both configurations. The _irqsave() ensures
+        * that interrupts are always disabled and later restored.
+        */
+       raw_spin_lock_irqsave(cpu_lock, flags);
+       head = tail = cgroup_rstat_cpu_pop_updated(NULL, root, cpu);
+       while (tail) {
+               next = cgroup_rstat_cpu_pop_updated(tail, root, cpu);
+               tail->rstat_flush_next = next;
+               tail = next;
+       }
+       raw_spin_unlock_irqrestore(cpu_lock, flags);
+       return head;
+}
+
 /*
  * A hook for bpf stat collectors to attach to and flush their stats.
  * Together with providing bpf kfuncs for cgroup_rstat_updated() and
        lockdep_assert_held(&cgroup_rstat_lock);
 
        for_each_possible_cpu(cpu) {
-               raw_spinlock_t *cpu_lock = per_cpu_ptr(&cgroup_rstat_cpu_lock,
-                                                      cpu);
-               struct cgroup *pos = NULL;
-               unsigned long flags;
+               struct cgroup *pos = cgroup_rstat_updated_list(cgrp, cpu);
 
-               /*
-                * The _irqsave() is needed because cgroup_rstat_lock is
-                * spinlock_t which is a sleeping lock on PREEMPT_RT. Acquiring
-                * this lock with the _irq() suffix only disables interrupts on
-                * a non-PREEMPT_RT kernel. The raw_spinlock_t below disables
-                * interrupts on both configurations. The _irqsave() ensures
-                * that interrupts are always disabled and later restored.
-                */
-               raw_spin_lock_irqsave(cpu_lock, flags);
-               while ((pos = cgroup_rstat_cpu_pop_updated(pos, cgrp, cpu))) {
+               for (; pos; pos = pos->rstat_flush_next) {
                        struct cgroup_subsys_state *css;
 
                        cgroup_base_stat_flush(pos, cpu);
                                css->ss->css_rstat_flush(css, cpu);
                        rcu_read_unlock();
                }
-               raw_spin_unlock_irqrestore(cpu_lock, flags);
 
                /* play nice and yield if necessary */
                if (need_resched() || spin_needbreak(&cgroup_rstat_lock)) {