Merge tag 'ptrace-cleanups-for-v5.18' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-microblaze.git] / mm / memcontrol.c
index 2aaa400..725f767 100644 (file)
@@ -53,6 +53,7 @@
 #include <linux/fs.h>
 #include <linux/seq_file.h>
 #include <linux/vmpressure.h>
+#include <linux/memremap.h>
 #include <linux/mm_inline.h>
 #include <linux/swap_cgroup.h>
 #include <linux/cpu.h>
@@ -254,7 +255,7 @@ struct mem_cgroup *vmpressure_to_memcg(struct vmpressure *vmpr)
 }
 
 #ifdef CONFIG_MEMCG_KMEM
-extern spinlock_t css_set_lock;
+static DEFINE_SPINLOCK(objcg_lock);
 
 bool mem_cgroup_kmem_disabled(void)
 {
@@ -298,9 +299,9 @@ static void obj_cgroup_release(struct percpu_ref *ref)
        if (nr_pages)
                obj_cgroup_uncharge_pages(objcg, nr_pages);
 
-       spin_lock_irqsave(&css_set_lock, flags);
+       spin_lock_irqsave(&objcg_lock, flags);
        list_del(&objcg->list);
-       spin_unlock_irqrestore(&css_set_lock, flags);
+       spin_unlock_irqrestore(&objcg_lock, flags);
 
        percpu_ref_exit(ref);
        kfree_rcu(objcg, rcu);
@@ -332,7 +333,7 @@ static void memcg_reparent_objcgs(struct mem_cgroup *memcg,
 
        objcg = rcu_replace_pointer(memcg->objcg, NULL, true);
 
-       spin_lock_irq(&css_set_lock);
+       spin_lock_irq(&objcg_lock);
 
        /* 1) Ready to reparent active objcg. */
        list_add(&objcg->list, &memcg->objcg_list);
@@ -342,53 +343,11 @@ static void memcg_reparent_objcgs(struct mem_cgroup *memcg,
        /* 3) Move already reparented objcgs to the parent's list */
        list_splice(&memcg->objcg_list, &parent->objcg_list);
 
-       spin_unlock_irq(&css_set_lock);
+       spin_unlock_irq(&objcg_lock);
 
        percpu_ref_kill(&objcg->refcnt);
 }
 
-/*
- * This will be used as a shrinker list's index.
- * The main reason for not using cgroup id for this:
- *  this works better in sparse environments, where we have a lot of memcgs,
- *  but only a few kmem-limited. Or also, if we have, for instance, 200
- *  memcgs, and none but the 200th is kmem-limited, we'd have to have a
- *  200 entry array for that.
- *
- * The current size of the caches array is stored in memcg_nr_cache_ids. It
- * will double each time we have to increase it.
- */
-static DEFINE_IDA(memcg_cache_ida);
-int memcg_nr_cache_ids;
-
-/* Protects memcg_nr_cache_ids */
-static DECLARE_RWSEM(memcg_cache_ids_sem);
-
-void memcg_get_cache_ids(void)
-{
-       down_read(&memcg_cache_ids_sem);
-}
-
-void memcg_put_cache_ids(void)
-{
-       up_read(&memcg_cache_ids_sem);
-}
-
-/*
- * MIN_SIZE is different than 1, because we would like to avoid going through
- * the alloc/free process all the time. In a small machine, 4 kmem-limited
- * cgroups is a reasonable guess. In the future, it could be a parameter or
- * tunable, but that is strictly not necessary.
- *
- * MAX_SIZE should be as large as the number of cgrp_ids. Ideally, we could get
- * this constant directly from cgroup, but it is understandable that this is
- * better kept as an internal representation in cgroup.c. In any case, the
- * cgrp_id space is not getting any smaller, and we don't have to necessarily
- * increase ours as well if it increases.
- */
-#define MEMCG_CACHES_MIN_SIZE 4
-#define MEMCG_CACHES_MAX_SIZE MEM_CGROUP_ID_MAX
-
 /*
  * A lot of the calls to the cache allocation functions are expected to be
  * inlined by the compiler. Since the calls to memcg_slab_pre_alloc_hook() are
@@ -629,6 +588,35 @@ static DEFINE_SPINLOCK(stats_flush_lock);
 static DEFINE_PER_CPU(unsigned int, stats_updates);
 static atomic_t stats_flush_threshold = ATOMIC_INIT(0);
 
+/*
+ * Accessors to ensure that preemption is disabled on PREEMPT_RT because it can
+ * not rely on this as part of an acquired spinlock_t lock. These functions are
+ * never used in hardirq context on PREEMPT_RT and therefore disabling preemtion
+ * is sufficient.
+ */
+static void memcg_stats_lock(void)
+{
+#ifdef CONFIG_PREEMPT_RT
+      preempt_disable();
+#else
+      VM_BUG_ON(!irqs_disabled());
+#endif
+}
+
+static void __memcg_stats_lock(void)
+{
+#ifdef CONFIG_PREEMPT_RT
+      preempt_disable();
+#endif
+}
+
+static void memcg_stats_unlock(void)
+{
+#ifdef CONFIG_PREEMPT_RT
+      preempt_enable();
+#endif
+}
+
 static inline void memcg_rstat_updated(struct mem_cgroup *memcg, int val)
 {
        unsigned int x;
@@ -705,6 +693,27 @@ void __mod_memcg_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx,
        pn = container_of(lruvec, struct mem_cgroup_per_node, lruvec);
        memcg = pn->memcg;
 
+       /*
+        * The caller from rmap relay on disabled preemption becase they never
+        * update their counter from in-interrupt context. For these two
+        * counters we check that the update is never performed from an
+        * interrupt context while other caller need to have disabled interrupt.
+        */
+       __memcg_stats_lock();
+       if (IS_ENABLED(CONFIG_DEBUG_VM) && !IS_ENABLED(CONFIG_PREEMPT_RT)) {
+               switch (idx) {
+               case NR_ANON_MAPPED:
+               case NR_FILE_MAPPED:
+               case NR_ANON_THPS:
+               case NR_SHMEM_PMDMAPPED:
+               case NR_FILE_PMDMAPPED:
+                       WARN_ON_ONCE(!in_task());
+                       break;
+               default:
+                       WARN_ON_ONCE(!irqs_disabled());
+               }
+       }
+
        /* Update memcg */
        __this_cpu_add(memcg->vmstats_percpu->state[idx], val);
 
@@ -712,6 +721,7 @@ void __mod_memcg_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx,
        __this_cpu_add(pn->lruvec_stats_percpu->state[idx], val);
 
        memcg_rstat_updated(memcg, val);
+       memcg_stats_unlock();
 }
 
 /**
@@ -794,8 +804,10 @@ void __count_memcg_events(struct mem_cgroup *memcg, enum vm_event_item idx,
        if (mem_cgroup_disabled())
                return;
 
+       memcg_stats_lock();
        __this_cpu_add(memcg->vmstats_percpu->events[idx], count);
        memcg_rstat_updated(memcg, count);
+       memcg_stats_unlock();
 }
 
 static unsigned long memcg_events(struct mem_cgroup *memcg, int event)
@@ -858,6 +870,9 @@ static bool mem_cgroup_event_ratelimit(struct mem_cgroup *memcg,
  */
 static void memcg_check_events(struct mem_cgroup *memcg, int nid)
 {
+       if (IS_ENABLED(CONFIG_PREEMPT_RT))
+               return;
+
        /* threshold event is triggered in finer grain than soft limit */
        if (unlikely(mem_cgroup_event_ratelimit(memcg,
                                                MEM_CGROUP_TARGET_THRESH))) {
@@ -1257,8 +1272,7 @@ struct lruvec *folio_lruvec_lock_irqsave(struct folio *folio,
  * @nr_pages: positive when adding or negative when removing
  *
  * This function must be called under lru_lock, just before a page is added
- * to or just after a page is removed from an lru list (that ordering being
- * so as to allow it to check that lru_size 0 is consistent with list_empty).
+ * to or just after a page is removed from an lru list.
  */
 void mem_cgroup_update_lru_size(struct lruvec *lruvec, enum lru_list lru,
                                int zid, int nr_pages)
@@ -1371,6 +1385,7 @@ struct memory_stat {
 static const struct memory_stat memory_stats[] = {
        { "anon",                       NR_ANON_MAPPED                  },
        { "file",                       NR_FILE_PAGES                   },
+       { "kernel",                     MEMCG_KMEM                      },
        { "kernel_stack",               NR_KERNEL_STACK_KB              },
        { "pagetables",                 NR_PAGETABLE                    },
        { "percpu",                     MEMCG_PERCPU_B                  },
@@ -1795,20 +1810,16 @@ static void memcg_oom_recover(struct mem_cgroup *memcg)
                __wake_up(&memcg_oom_waitq, TASK_NORMAL, 0, memcg);
 }
 
-enum oom_status {
-       OOM_SUCCESS,
-       OOM_FAILED,
-       OOM_ASYNC,
-       OOM_SKIPPED
-};
-
-static enum oom_status mem_cgroup_oom(struct mem_cgroup *memcg, gfp_t mask, int order)
+/*
+ * Returns true if successfully killed one or more processes. Though in some
+ * corner cases it can return true even without killing any process.
+ */
+static bool mem_cgroup_oom(struct mem_cgroup *memcg, gfp_t mask, int order)
 {
-       enum oom_status ret;
-       bool locked;
+       bool locked, ret;
 
        if (order > PAGE_ALLOC_COSTLY_ORDER)
-               return OOM_SKIPPED;
+               return false;
 
        memcg_memory_event(memcg, MEMCG_OOM);
 
@@ -1831,14 +1842,13 @@ static enum oom_status mem_cgroup_oom(struct mem_cgroup *memcg, gfp_t mask, int
         * victim and then we have to bail out from the charge path.
         */
        if (memcg->oom_kill_disable) {
-               if (!current->in_user_fault)
-                       return OOM_SKIPPED;
-               css_get(&memcg->css);
-               current->memcg_in_oom = memcg;
-               current->memcg_oom_gfp_mask = mask;
-               current->memcg_oom_order = order;
-
-               return OOM_ASYNC;
+               if (current->in_user_fault) {
+                       css_get(&memcg->css);
+                       current->memcg_in_oom = memcg;
+                       current->memcg_oom_gfp_mask = mask;
+                       current->memcg_oom_order = order;
+               }
+               return false;
        }
 
        mem_cgroup_mark_under_oom(memcg);
@@ -1849,10 +1859,7 @@ static enum oom_status mem_cgroup_oom(struct mem_cgroup *memcg, gfp_t mask, int
                mem_cgroup_oom_notify(memcg);
 
        mem_cgroup_unmark_under_oom(memcg);
-       if (mem_cgroup_out_of_memory(memcg, mask, order))
-               ret = OOM_SUCCESS;
-       else
-               ret = OOM_FAILED;
+       ret = mem_cgroup_out_of_memory(memcg, mask, order);
 
        if (locked)
                mem_cgroup_oom_unlock(memcg);
@@ -2085,45 +2092,47 @@ void unlock_page_memcg(struct page *page)
        folio_memcg_unlock(page_folio(page));
 }
 
-struct obj_stock {
+struct memcg_stock_pcp {
+       local_lock_t stock_lock;
+       struct mem_cgroup *cached; /* this never be root cgroup */
+       unsigned int nr_pages;
+
 #ifdef CONFIG_MEMCG_KMEM
        struct obj_cgroup *cached_objcg;
        struct pglist_data *cached_pgdat;
        unsigned int nr_bytes;
        int nr_slab_reclaimable_b;
        int nr_slab_unreclaimable_b;
-#else
-       int dummy[0];
 #endif
-};
-
-struct memcg_stock_pcp {
-       struct mem_cgroup *cached; /* this never be root cgroup */
-       unsigned int nr_pages;
-       struct obj_stock task_obj;
-       struct obj_stock irq_obj;
 
        struct work_struct work;
        unsigned long flags;
 #define FLUSHING_CACHED_CHARGE 0
 };
-static DEFINE_PER_CPU(struct memcg_stock_pcp, memcg_stock);
+static DEFINE_PER_CPU(struct memcg_stock_pcp, memcg_stock) = {
+       .stock_lock = INIT_LOCAL_LOCK(stock_lock),
+};
 static DEFINE_MUTEX(percpu_charge_mutex);
 
 #ifdef CONFIG_MEMCG_KMEM
-static void drain_obj_stock(struct obj_stock *stock);
+static struct obj_cgroup *drain_obj_stock(struct memcg_stock_pcp *stock);
 static bool obj_stock_flush_required(struct memcg_stock_pcp *stock,
                                     struct mem_cgroup *root_memcg);
+static void memcg_account_kmem(struct mem_cgroup *memcg, int nr_pages);
 
 #else
-static inline void drain_obj_stock(struct obj_stock *stock)
+static inline struct obj_cgroup *drain_obj_stock(struct memcg_stock_pcp *stock)
 {
+       return NULL;
 }
 static bool obj_stock_flush_required(struct memcg_stock_pcp *stock,
                                     struct mem_cgroup *root_memcg)
 {
        return false;
 }
+static void memcg_account_kmem(struct mem_cgroup *memcg, int nr_pages)
+{
+}
 #endif
 
 /**
@@ -2146,7 +2155,7 @@ static bool consume_stock(struct mem_cgroup *memcg, unsigned int nr_pages)
        if (nr_pages > MEMCG_CHARGE_BATCH)
                return ret;
 
-       local_irq_save(flags);
+       local_lock_irqsave(&memcg_stock.stock_lock, flags);
 
        stock = this_cpu_ptr(&memcg_stock);
        if (memcg == stock->cached && stock->nr_pages >= nr_pages) {
@@ -2154,7 +2163,7 @@ static bool consume_stock(struct mem_cgroup *memcg, unsigned int nr_pages)
                ret = true;
        }
 
-       local_irq_restore(flags);
+       local_unlock_irqrestore(&memcg_stock.stock_lock, flags);
 
        return ret;
 }
@@ -2183,6 +2192,7 @@ static void drain_stock(struct memcg_stock_pcp *stock)
 static void drain_local_stock(struct work_struct *dummy)
 {
        struct memcg_stock_pcp *stock;
+       struct obj_cgroup *old = NULL;
        unsigned long flags;
 
        /*
@@ -2190,28 +2200,25 @@ static void drain_local_stock(struct work_struct *dummy)
         * drain_stock races is that we always operate on local CPU stock
         * here with IRQ disabled
         */
-       local_irq_save(flags);
+       local_lock_irqsave(&memcg_stock.stock_lock, flags);
 
        stock = this_cpu_ptr(&memcg_stock);
-       drain_obj_stock(&stock->irq_obj);
-       if (in_task())
-               drain_obj_stock(&stock->task_obj);
+       old = drain_obj_stock(stock);
        drain_stock(stock);
        clear_bit(FLUSHING_CACHED_CHARGE, &stock->flags);
 
-       local_irq_restore(flags);
+       local_unlock_irqrestore(&memcg_stock.stock_lock, flags);
+       if (old)
+               obj_cgroup_put(old);
 }
 
 /*
  * Cache charges(val) to local per_cpu area.
  * This will be consumed by consume_stock() function, later.
  */
-static void refill_stock(struct mem_cgroup *memcg, unsigned int nr_pages)
+static void __refill_stock(struct mem_cgroup *memcg, unsigned int nr_pages)
 {
        struct memcg_stock_pcp *stock;
-       unsigned long flags;
-
-       local_irq_save(flags);
 
        stock = this_cpu_ptr(&memcg_stock);
        if (stock->cached != memcg) { /* reset if necessary */
@@ -2223,8 +2230,15 @@ static void refill_stock(struct mem_cgroup *memcg, unsigned int nr_pages)
 
        if (stock->nr_pages > MEMCG_CHARGE_BATCH)
                drain_stock(stock);
+}
 
-       local_irq_restore(flags);
+static void refill_stock(struct mem_cgroup *memcg, unsigned int nr_pages)
+{
+       unsigned long flags;
+
+       local_lock_irqsave(&memcg_stock.stock_lock, flags);
+       __refill_stock(memcg, nr_pages);
+       local_unlock_irqrestore(&memcg_stock.stock_lock, flags);
 }
 
 /*
@@ -2244,7 +2258,8 @@ static void drain_all_stock(struct mem_cgroup *root_memcg)
         * as well as workers from this path always operate on the local
         * per-cpu data. CPU up doesn't touch memcg_stock at all.
         */
-       curcpu = get_cpu();
+       migrate_disable();
+       curcpu = smp_processor_id();
        for_each_online_cpu(cpu) {
                struct memcg_stock_pcp *stock = &per_cpu(memcg_stock, cpu);
                struct mem_cgroup *memcg;
@@ -2267,7 +2282,7 @@ static void drain_all_stock(struct mem_cgroup *root_memcg)
                                schedule_work_on(cpu, &stock->work);
                }
        }
-       put_cpu();
+       migrate_enable();
        mutex_unlock(&percpu_charge_mutex);
 }
 
@@ -2541,7 +2556,6 @@ static int try_charge_memcg(struct mem_cgroup *memcg, gfp_t gfp_mask,
        int nr_retries = MAX_RECLAIM_RETRIES;
        struct mem_cgroup *mem_over_limit;
        struct page_counter *counter;
-       enum oom_status oom_status;
        unsigned long nr_reclaimed;
        bool passed_oom = false;
        bool may_swap = true;
@@ -2569,15 +2583,6 @@ retry:
                goto retry;
        }
 
-       /*
-        * Memcg doesn't have a dedicated reserve for atomic
-        * allocations. But like the global atomic pool, we need to
-        * put the burden of reclaim on regular allocation requests
-        * and let these go through as privileged allocations.
-        */
-       if (gfp_mask & __GFP_ATOMIC)
-               goto force;
-
        /*
         * Prevent unbounded recursion when reclaim operations need to
         * allocate memory. This might exceed the limits temporarily,
@@ -2644,15 +2649,20 @@ retry:
         * a forward progress or bypass the charge if the oom killer
         * couldn't make any progress.
         */
-       oom_status = mem_cgroup_oom(mem_over_limit, gfp_mask,
-                      get_order(nr_pages * PAGE_SIZE));
-       if (oom_status == OOM_SUCCESS) {
+       if (mem_cgroup_oom(mem_over_limit, gfp_mask,
+                          get_order(nr_pages * PAGE_SIZE))) {
                passed_oom = true;
                nr_retries = MAX_RECLAIM_RETRIES;
                goto retry;
        }
 nomem:
-       if (!(gfp_mask & __GFP_NOFAIL))
+       /*
+        * Memcg doesn't have a dedicated reserve for atomic
+        * allocations. But like the global atomic pool, we need to
+        * put the burden of reclaim on regular allocation requests
+        * and let these go through as privileged allocations.
+        */
+       if (!(gfp_mask & (__GFP_NOFAIL | __GFP_HIGH)))
                return -ENOMEM;
 force:
        /*
@@ -2688,7 +2698,7 @@ done_restock:
                        READ_ONCE(memcg->swap.high);
 
                /* Don't bother a random interrupted task */
-               if (in_interrupt()) {
+               if (!in_task()) {
                        if (mem_high) {
                                schedule_work(&memcg->high_work);
                                break;
@@ -2712,6 +2722,11 @@ done_restock:
                }
        } while ((memcg = parent_mem_cgroup(memcg)));
 
+       if (current->memcg_nr_pages_over_high > MEMCG_CHARGE_BATCH &&
+           !(current->flags & PF_MEMALLOC) &&
+           gfpflags_allow_blocking(gfp_mask)) {
+               mem_cgroup_handle_over_high();
+       }
        return 0;
 }
 
@@ -2748,20 +2763,6 @@ static void commit_charge(struct folio *folio, struct mem_cgroup *memcg)
        folio->memcg_data = (unsigned long)memcg;
 }
 
-static struct mem_cgroup *get_mem_cgroup_from_objcg(struct obj_cgroup *objcg)
-{
-       struct mem_cgroup *memcg;
-
-       rcu_read_lock();
-retry:
-       memcg = obj_cgroup_memcg(objcg);
-       if (unlikely(!css_tryget(&memcg->css)))
-               goto retry;
-       rcu_read_unlock();
-
-       return memcg;
-}
-
 #ifdef CONFIG_MEMCG_KMEM
 /*
  * The allocated objcg pointers array is not accounted directly.
@@ -2770,41 +2771,6 @@ retry:
  */
 #define OBJCGS_CLEAR_MASK      (__GFP_DMA | __GFP_RECLAIMABLE | __GFP_ACCOUNT)
 
-/*
- * Most kmem_cache_alloc() calls are from user context. The irq disable/enable
- * sequence used in this case to access content from object stock is slow.
- * To optimize for user context access, there are now two object stocks for
- * task context and interrupt context access respectively.
- *
- * The task context object stock can be accessed by disabling preemption only
- * which is cheap in non-preempt kernel. The interrupt context object stock
- * can only be accessed after disabling interrupt. User context code can
- * access interrupt object stock, but not vice versa.
- */
-static inline struct obj_stock *get_obj_stock(unsigned long *pflags)
-{
-       struct memcg_stock_pcp *stock;
-
-       if (likely(in_task())) {
-               *pflags = 0UL;
-               preempt_disable();
-               stock = this_cpu_ptr(&memcg_stock);
-               return &stock->task_obj;
-       }
-
-       local_irq_save(*pflags);
-       stock = this_cpu_ptr(&memcg_stock);
-       return &stock->irq_obj;
-}
-
-static inline void put_obj_stock(unsigned long flags)
-{
-       if (likely(in_task()))
-               preempt_enable();
-       else
-               local_irq_restore(flags);
-}
-
 /*
  * mod_objcg_mlstate() may be called with irq enabled, so
  * mod_memcg_lruvec_state() should be used.
@@ -2936,48 +2902,17 @@ __always_inline struct obj_cgroup *get_obj_cgroup_from_current(void)
        return objcg;
 }
 
-static int memcg_alloc_cache_id(void)
+static void memcg_account_kmem(struct mem_cgroup *memcg, int nr_pages)
 {
-       int id, size;
-       int err;
-
-       id = ida_simple_get(&memcg_cache_ida,
-                           0, MEMCG_CACHES_MAX_SIZE, GFP_KERNEL);
-       if (id < 0)
-               return id;
-
-       if (id < memcg_nr_cache_ids)
-               return id;
-
-       /*
-        * There's no space for the new id in memcg_caches arrays,
-        * so we have to grow them.
-        */
-       down_write(&memcg_cache_ids_sem);
-
-       size = 2 * (id + 1);
-       if (size < MEMCG_CACHES_MIN_SIZE)
-               size = MEMCG_CACHES_MIN_SIZE;
-       else if (size > MEMCG_CACHES_MAX_SIZE)
-               size = MEMCG_CACHES_MAX_SIZE;
-
-       err = memcg_update_all_list_lrus(size);
-       if (!err)
-               memcg_nr_cache_ids = size;
-
-       up_write(&memcg_cache_ids_sem);
-
-       if (err) {
-               ida_simple_remove(&memcg_cache_ida, id);
-               return err;
+       mod_memcg_state(memcg, MEMCG_KMEM, nr_pages);
+       if (!cgroup_subsys_on_dfl(memory_cgrp_subsys)) {
+               if (nr_pages > 0)
+                       page_counter_charge(&memcg->kmem, nr_pages);
+               else
+                       page_counter_uncharge(&memcg->kmem, -nr_pages);
        }
-       return id;
 }
 
-static void memcg_free_cache_id(int id)
-{
-       ida_simple_remove(&memcg_cache_ida, id);
-}
 
 /*
  * obj_cgroup_uncharge_pages: uncharge a number of kernel pages from a objcg
@@ -2991,8 +2926,7 @@ static void obj_cgroup_uncharge_pages(struct obj_cgroup *objcg,
 
        memcg = get_mem_cgroup_from_objcg(objcg);
 
-       if (!cgroup_subsys_on_dfl(memory_cgrp_subsys))
-               page_counter_uncharge(&memcg->kmem, nr_pages);
+       memcg_account_kmem(memcg, -nr_pages);
        refill_stock(memcg, nr_pages);
 
        css_put(&memcg->css);
@@ -3018,8 +2952,7 @@ static int obj_cgroup_charge_pages(struct obj_cgroup *objcg, gfp_t gfp,
        if (ret)
                goto out;
 
-       if (!cgroup_subsys_on_dfl(memory_cgrp_subsys))
-               page_counter_charge(&memcg->kmem, nr_pages);
+       memcg_account_kmem(memcg, nr_pages);
 out:
        css_put(&memcg->css);
 
@@ -3075,17 +3008,21 @@ void __memcg_kmem_uncharge_page(struct page *page, int order)
 void mod_objcg_state(struct obj_cgroup *objcg, struct pglist_data *pgdat,
                     enum node_stat_item idx, int nr)
 {
+       struct memcg_stock_pcp *stock;
+       struct obj_cgroup *old = NULL;
        unsigned long flags;
-       struct obj_stock *stock = get_obj_stock(&flags);
        int *bytes;
 
+       local_lock_irqsave(&memcg_stock.stock_lock, flags);
+       stock = this_cpu_ptr(&memcg_stock);
+
        /*
         * Save vmstat data in stock and skip vmstat array update unless
         * accumulating over a page of vmstat data or when pgdat or idx
         * changes.
         */
        if (stock->cached_objcg != objcg) {
-               drain_obj_stock(stock);
+               old = drain_obj_stock(stock);
                obj_cgroup_get(objcg);
                stock->nr_bytes = atomic_read(&objcg->nr_charged_bytes)
                                ? atomic_xchg(&objcg->nr_charged_bytes, 0) : 0;
@@ -3129,38 +3066,51 @@ void mod_objcg_state(struct obj_cgroup *objcg, struct pglist_data *pgdat,
        if (nr)
                mod_objcg_mlstate(objcg, pgdat, idx, nr);
 
-       put_obj_stock(flags);
+       local_unlock_irqrestore(&memcg_stock.stock_lock, flags);
+       if (old)
+               obj_cgroup_put(old);
 }
 
 static bool consume_obj_stock(struct obj_cgroup *objcg, unsigned int nr_bytes)
 {
+       struct memcg_stock_pcp *stock;
        unsigned long flags;
-       struct obj_stock *stock = get_obj_stock(&flags);
        bool ret = false;
 
+       local_lock_irqsave(&memcg_stock.stock_lock, flags);
+
+       stock = this_cpu_ptr(&memcg_stock);
        if (objcg == stock->cached_objcg && stock->nr_bytes >= nr_bytes) {
                stock->nr_bytes -= nr_bytes;
                ret = true;
        }
 
-       put_obj_stock(flags);
+       local_unlock_irqrestore(&memcg_stock.stock_lock, flags);
 
        return ret;
 }
 
-static void drain_obj_stock(struct obj_stock *stock)
+static struct obj_cgroup *drain_obj_stock(struct memcg_stock_pcp *stock)
 {
        struct obj_cgroup *old = stock->cached_objcg;
 
        if (!old)
-               return;
+               return NULL;
 
        if (stock->nr_bytes) {
                unsigned int nr_pages = stock->nr_bytes >> PAGE_SHIFT;
                unsigned int nr_bytes = stock->nr_bytes & (PAGE_SIZE - 1);
 
-               if (nr_pages)
-                       obj_cgroup_uncharge_pages(old, nr_pages);
+               if (nr_pages) {
+                       struct mem_cgroup *memcg;
+
+                       memcg = get_mem_cgroup_from_objcg(old);
+
+                       memcg_account_kmem(memcg, -nr_pages);
+                       __refill_stock(memcg, nr_pages);
+
+                       css_put(&memcg->css);
+               }
 
                /*
                 * The leftover is flushed to the centralized per-memcg value.
@@ -3195,8 +3145,12 @@ static void drain_obj_stock(struct obj_stock *stock)
                stock->cached_pgdat = NULL;
        }
 
-       obj_cgroup_put(old);
        stock->cached_objcg = NULL;
+       /*
+        * The `old' objects needs to be released by the caller via
+        * obj_cgroup_put() outside of memcg_stock_pcp::stock_lock.
+        */
+       return old;
 }
 
 static bool obj_stock_flush_required(struct memcg_stock_pcp *stock,
@@ -3204,13 +3158,8 @@ static bool obj_stock_flush_required(struct memcg_stock_pcp *stock,
 {
        struct mem_cgroup *memcg;
 
-       if (in_task() && stock->task_obj.cached_objcg) {
-               memcg = obj_cgroup_memcg(stock->task_obj.cached_objcg);
-               if (memcg && mem_cgroup_is_descendant(memcg, root_memcg))
-                       return true;
-       }
-       if (stock->irq_obj.cached_objcg) {
-               memcg = obj_cgroup_memcg(stock->irq_obj.cached_objcg);
+       if (stock->cached_objcg) {
+               memcg = obj_cgroup_memcg(stock->cached_objcg);
                if (memcg && mem_cgroup_is_descendant(memcg, root_memcg))
                        return true;
        }
@@ -3221,12 +3170,16 @@ static bool obj_stock_flush_required(struct memcg_stock_pcp *stock,
 static void refill_obj_stock(struct obj_cgroup *objcg, unsigned int nr_bytes,
                             bool allow_uncharge)
 {
+       struct memcg_stock_pcp *stock;
+       struct obj_cgroup *old = NULL;
        unsigned long flags;
-       struct obj_stock *stock = get_obj_stock(&flags);
        unsigned int nr_pages = 0;
 
+       local_lock_irqsave(&memcg_stock.stock_lock, flags);
+
+       stock = this_cpu_ptr(&memcg_stock);
        if (stock->cached_objcg != objcg) { /* reset if necessary */
-               drain_obj_stock(stock);
+               old = drain_obj_stock(stock);
                obj_cgroup_get(objcg);
                stock->cached_objcg = objcg;
                stock->nr_bytes = atomic_read(&objcg->nr_charged_bytes)
@@ -3240,7 +3193,9 @@ static void refill_obj_stock(struct obj_cgroup *objcg, unsigned int nr_bytes,
                stock->nr_bytes &= (PAGE_SIZE - 1);
        }
 
-       put_obj_stock(flags);
+       local_unlock_irqrestore(&memcg_stock.stock_lock, flags);
+       if (old)
+               obj_cgroup_put(old);
 
        if (nr_pages)
                obj_cgroup_uncharge_pages(objcg, nr_pages);
@@ -3625,28 +3580,23 @@ static u64 mem_cgroup_read_u64(struct cgroup_subsys_state *css,
 static int memcg_online_kmem(struct mem_cgroup *memcg)
 {
        struct obj_cgroup *objcg;
-       int memcg_id;
 
        if (cgroup_memory_nokmem)
                return 0;
 
-       BUG_ON(memcg->kmemcg_id >= 0);
-
-       memcg_id = memcg_alloc_cache_id();
-       if (memcg_id < 0)
-               return memcg_id;
+       if (unlikely(mem_cgroup_is_root(memcg)))
+               return 0;
 
        objcg = obj_cgroup_alloc();
-       if (!objcg) {
-               memcg_free_cache_id(memcg_id);
+       if (!objcg)
                return -ENOMEM;
-       }
+
        objcg->memcg = memcg;
        rcu_assign_pointer(memcg->objcg, objcg);
 
        static_branch_enable(&memcg_kmem_enabled_key);
 
-       memcg->kmemcg_id = memcg_id;
+       memcg->kmemcg_id = memcg->id.id;
 
        return 0;
 }
@@ -3654,9 +3604,11 @@ static int memcg_online_kmem(struct mem_cgroup *memcg)
 static void memcg_offline_kmem(struct mem_cgroup *memcg)
 {
        struct mem_cgroup *parent;
-       int kmemcg_id;
 
-       if (memcg->kmemcg_id == -1)
+       if (cgroup_memory_nokmem)
+               return;
+
+       if (unlikely(mem_cgroup_is_root(memcg)))
                return;
 
        parent = parent_mem_cgroup(memcg);
@@ -3665,19 +3617,13 @@ static void memcg_offline_kmem(struct mem_cgroup *memcg)
 
        memcg_reparent_objcgs(memcg, parent);
 
-       kmemcg_id = memcg->kmemcg_id;
-       BUG_ON(kmemcg_id < 0);
-
        /*
         * After we have finished memcg_reparent_objcgs(), all list_lrus
         * corresponding to this cgroup are guaranteed to remain empty.
         * The ordering is imposed by list_lru_node->lock taken by
-        * memcg_drain_all_list_lrus().
+        * memcg_reparent_list_lrus().
         */
-       memcg_drain_all_list_lrus(kmemcg_id, parent);
-
-       memcg_free_cache_id(kmemcg_id);
-       memcg->kmemcg_id = -1;
+       memcg_reparent_list_lrus(memcg, parent);
 }
 #else
 static int memcg_online_kmem(struct mem_cgroup *memcg)
@@ -3763,8 +3709,12 @@ static ssize_t mem_cgroup_write(struct kernfs_open_file *of,
                }
                break;
        case RES_SOFT_LIMIT:
-               memcg->soft_limit = nr_pages;
-               ret = 0;
+               if (IS_ENABLED(CONFIG_PREEMPT_RT)) {
+                       ret = -EOPNOTSUPP;
+               } else {
+                       memcg->soft_limit = nr_pages;
+                       ret = 0;
+               }
                break;
        }
        return ret ?: nbytes;
@@ -4740,6 +4690,9 @@ static ssize_t memcg_write_event_control(struct kernfs_open_file *of,
        char *endp;
        int ret;
 
+       if (IS_ENABLED(CONFIG_PREEMPT_RT))
+               return -EOPNOTSUPP;
+
        buf = strstrip(buf);
 
        efd = simple_strtoul(buf, &endp, 10);
@@ -5067,18 +5020,8 @@ struct mem_cgroup *mem_cgroup_from_id(unsigned short id)
 static int alloc_mem_cgroup_per_node_info(struct mem_cgroup *memcg, int node)
 {
        struct mem_cgroup_per_node *pn;
-       int tmp = node;
-       /*
-        * This routine is called against possible nodes.
-        * But it's BUG to call kmalloc() against offline node.
-        *
-        * TODO: this routine can waste much memory for nodes which will
-        *       never be onlined. It's better to use memory hotplug callback
-        *       function.
-        */
-       if (!node_state(node, N_NORMAL_MEMORY))
-               tmp = -1;
-       pn = kzalloc_node(sizeof(*pn), GFP_KERNEL, tmp);
+
+       pn = kzalloc_node(sizeof(*pn), GFP_KERNEL, node);
        if (!pn)
                return 1;
 
@@ -5090,8 +5033,6 @@ static int alloc_mem_cgroup_per_node_info(struct mem_cgroup *memcg, int node)
        }
 
        lruvec_init(&pn->lruvec);
-       pn->usage_in_excess = 0;
-       pn->on_tree = false;
        pn->memcg = memcg;
 
        memcg->nodeinfo[node] = pn;
@@ -5137,8 +5078,7 @@ static struct mem_cgroup *mem_cgroup_alloc(void)
                return ERR_PTR(error);
 
        memcg->id.id = idr_alloc(&mem_cgroup_idr, NULL,
-                                1, MEM_CGROUP_ID_MAX,
-                                GFP_KERNEL);
+                                1, MEM_CGROUP_ID_MAX + 1, GFP_KERNEL);
        if (memcg->id.id < 0) {
                error = memcg->id.id;
                goto fail;
@@ -5192,7 +5132,6 @@ mem_cgroup_css_alloc(struct cgroup_subsys_state *parent_css)
 {
        struct mem_cgroup *parent = mem_cgroup_from_css(parent_css);
        struct mem_cgroup *memcg, *old_memcg;
-       long error = -ENOMEM;
 
        old_memcg = set_active_memcg(parent);
        memcg = mem_cgroup_alloc();
@@ -5221,34 +5160,26 @@ mem_cgroup_css_alloc(struct cgroup_subsys_state *parent_css)
                return &memcg->css;
        }
 
-       /* The following stuff does not apply to the root */
-       error = memcg_online_kmem(memcg);
-       if (error)
-               goto fail;
-
        if (cgroup_subsys_on_dfl(memory_cgrp_subsys) && !cgroup_memory_nosocket)
                static_branch_inc(&memcg_sockets_enabled_key);
 
        return &memcg->css;
-fail:
-       mem_cgroup_id_remove(memcg);
-       mem_cgroup_free(memcg);
-       return ERR_PTR(error);
 }
 
 static int mem_cgroup_css_online(struct cgroup_subsys_state *css)
 {
        struct mem_cgroup *memcg = mem_cgroup_from_css(css);
 
+       if (memcg_online_kmem(memcg))
+               goto remove_id;
+
        /*
         * A memcg must be visible for expand_shrinker_info()
         * by the time the maps are allocated. So, we allocate maps
         * here, when for_each_mem_cgroup() can't skip it.
         */
-       if (alloc_shrinker_info(memcg)) {
-               mem_cgroup_id_remove(memcg);
-               return -ENOMEM;
-       }
+       if (alloc_shrinker_info(memcg))
+               goto offline_kmem;
 
        /* Online state pins memcg ID, memcg ID pins CSS */
        refcount_set(&memcg->id.ref, 1);
@@ -5258,6 +5189,11 @@ static int mem_cgroup_css_online(struct cgroup_subsys_state *css)
                queue_delayed_work(system_unbound_wq, &stats_flush_dwork,
                                   2UL*HZ);
        return 0;
+offline_kmem:
+       memcg_offline_kmem(memcg);
+remove_id:
+       mem_cgroup_id_remove(memcg);
+       return -ENOMEM;
 }
 
 static void mem_cgroup_css_offline(struct cgroup_subsys_state *css)
@@ -5315,9 +5251,6 @@ static void mem_cgroup_css_free(struct cgroup_subsys_state *css)
        cancel_work_sync(&memcg->high_work);
        mem_cgroup_remove_from_trees(memcg);
        free_shrinker_info(memcg);
-
-       /* Need to offline kmem if online_css() fails */
-       memcg_offline_kmem(memcg);
        mem_cgroup_free(memcg);
 }
 
@@ -5503,17 +5436,12 @@ static struct page *mc_handle_swap_pte(struct vm_area_struct *vma,
                return NULL;
 
        /*
-        * Handle MEMORY_DEVICE_PRIVATE which are ZONE_DEVICE page belonging to
-        * a device and because they are not accessible by CPU they are store
-        * as special swap entry in the CPU page table.
+        * Handle device private pages that are not accessible by the CPU, but
+        * stored as special swap entries in the page table.
         */
        if (is_device_private_entry(ent)) {
                page = pfn_swap_entry_to_page(ent);
-               /*
-                * MEMORY_DEVICE_PRIVATE means ZONE_DEVICE page and which have
-                * a refcount of 1 when free (unlike normal page)
-                */
-               if (!page_ref_add_unless(page, 1, 1))
+               if (!get_page_unless_zero(page))
                        return NULL;
                return page;
        }
@@ -6801,8 +6729,8 @@ static void uncharge_batch(const struct uncharge_gather *ug)
                page_counter_uncharge(&ug->memcg->memory, ug->nr_memory);
                if (do_memsw_account())
                        page_counter_uncharge(&ug->memcg->memsw, ug->nr_memory);
-               if (!cgroup_subsys_on_dfl(memory_cgrp_subsys) && ug->nr_kmem)
-                       page_counter_uncharge(&ug->memcg->kmem, ug->nr_kmem);
+               if (ug->nr_kmem)
+                       memcg_account_kmem(ug->memcg, -ug->nr_kmem);
                memcg_oom_recover(ug->memcg);
        }
 
@@ -6821,7 +6749,6 @@ static void uncharge_folio(struct folio *folio, struct uncharge_gather *ug)
        long nr_pages;
        struct mem_cgroup *memcg;
        struct obj_cgroup *objcg;
-       bool use_objcg = folio_memcg_kmem(folio);
 
        VM_BUG_ON_FOLIO(folio_test_lru(folio), folio);
 
@@ -6830,7 +6757,7 @@ static void uncharge_folio(struct folio *folio, struct uncharge_gather *ug)
         * folio memcg or objcg at this point, we have fully
         * exclusive access to the folio.
         */
-       if (use_objcg) {
+       if (folio_memcg_kmem(folio)) {
                objcg = __folio_objcg(folio);
                /*
                 * This get matches the put at the end of the function and
@@ -6858,7 +6785,7 @@ static void uncharge_folio(struct folio *folio, struct uncharge_gather *ug)
 
        nr_pages = folio_nr_pages(folio);
 
-       if (use_objcg) {
+       if (folio_memcg_kmem(folio)) {
                ug->nr_memory += nr_pages;
                ug->nr_kmem += nr_pages;
 
@@ -6968,7 +6895,7 @@ void mem_cgroup_sk_alloc(struct sock *sk)
                return;
 
        /* Do not associate the sock with unrelated interrupted task's memcg. */
-       if (in_interrupt())
+       if (!in_task())
                return;
 
        rcu_read_lock();
@@ -7053,7 +6980,7 @@ static int __init cgroup_memory(char *s)
                if (!strcmp(token, "nokmem"))
                        cgroup_memory_nokmem = true;
        }
-       return 0;
+       return 1;
 }
 __setup("cgroup.memory=", cgroup_memory);
 
@@ -7121,19 +7048,19 @@ static struct mem_cgroup *mem_cgroup_id_get_online(struct mem_cgroup *memcg)
 
 /**
  * mem_cgroup_swapout - transfer a memsw charge to swap
- * @page: page whose memsw charge to transfer
+ * @folio: folio whose memsw charge to transfer
  * @entry: swap entry to move the charge to
  *
- * Transfer the memsw charge of @page to @entry.
+ * Transfer the memsw charge of @folio to @entry.
  */
-void mem_cgroup_swapout(struct page *page, swp_entry_t entry)
+void mem_cgroup_swapout(struct folio *folio, swp_entry_t entry)
 {
        struct mem_cgroup *memcg, *swap_memcg;
        unsigned int nr_entries;
        unsigned short oldid;
 
-       VM_BUG_ON_PAGE(PageLRU(page), page);
-       VM_BUG_ON_PAGE(page_count(page), page);
+       VM_BUG_ON_FOLIO(folio_test_lru(folio), folio);
+       VM_BUG_ON_FOLIO(folio_ref_count(folio), folio);
 
        if (mem_cgroup_disabled())
                return;
@@ -7141,9 +7068,9 @@ void mem_cgroup_swapout(struct page *page, swp_entry_t entry)
        if (cgroup_subsys_on_dfl(memory_cgrp_subsys))
                return;
 
-       memcg = page_memcg(page);
+       memcg = folio_memcg(folio);
 
-       VM_WARN_ON_ONCE_PAGE(!memcg, page);
+       VM_WARN_ON_ONCE_FOLIO(!memcg, folio);
        if (!memcg)
                return;
 
@@ -7153,16 +7080,16 @@ void mem_cgroup_swapout(struct page *page, swp_entry_t entry)
         * ancestor for the swap instead and transfer the memory+swap charge.
         */
        swap_memcg = mem_cgroup_id_get_online(memcg);
-       nr_entries = thp_nr_pages(page);
+       nr_entries = folio_nr_pages(folio);
        /* Get references for the tail pages, too */
        if (nr_entries > 1)
                mem_cgroup_id_get_many(swap_memcg, nr_entries - 1);
        oldid = swap_cgroup_record(entry, mem_cgroup_id(swap_memcg),
                                   nr_entries);
-       VM_BUG_ON_PAGE(oldid, page);
+       VM_BUG_ON_FOLIO(oldid, folio);
        mod_memcg_state(swap_memcg, MEMCG_SWAP, nr_entries);
 
-       page->memcg_data = 0;
+       folio->memcg_data = 0;
 
        if (!mem_cgroup_is_root(memcg))
                page_counter_uncharge(&memcg->memory, nr_entries);
@@ -7179,9 +7106,10 @@ void mem_cgroup_swapout(struct page *page, swp_entry_t entry)
         * important here to have the interrupts disabled because it is the
         * only synchronisation we have for updating the per-CPU variables.
         */
-       VM_BUG_ON(!irqs_disabled());
+       memcg_stats_lock();
        mem_cgroup_charge_statistics(memcg, -nr_entries);
-       memcg_check_events(memcg, page_to_nid(page));
+       memcg_stats_unlock();
+       memcg_check_events(memcg, folio_nid(folio));
 
        css_put(&memcg->css);
 }