]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blobdiff - mm/memcontrol.c
ASoC: amd: fix for pcm_read() error
[mirror_ubuntu-hirsute-kernel.git] / mm / memcontrol.c
index e2de77b5bcc2fb2afe109447ec754e17b4b17d7c..a98a5a53166583e497f2afe90b859d48fceb6899 100644 (file)
@@ -1080,13 +1080,9 @@ static __always_inline struct mem_cgroup *get_active_memcg(void)
 
        rcu_read_lock();
        memcg = active_memcg();
-       if (memcg) {
-               /* current->active_memcg must hold a ref. */
-               if (WARN_ON_ONCE(!css_tryget(&memcg->css)))
-                       memcg = root_mem_cgroup;
-               else
-                       memcg = current->active_memcg;
-       }
+       /* remote memcg must hold a ref. */
+       if (memcg && WARN_ON_ONCE(!css_tryget(&memcg->css)))
+               memcg = root_mem_cgroup;
        rcu_read_unlock();
 
        return memcg;
@@ -3194,9 +3190,17 @@ static void drain_obj_stock(struct memcg_stock_pcp *stock)
                unsigned int nr_bytes = stock->nr_bytes & (PAGE_SIZE - 1);
 
                if (nr_pages) {
+                       struct mem_cgroup *memcg;
+
                        rcu_read_lock();
-                       __memcg_kmem_uncharge(obj_cgroup_memcg(old), nr_pages);
+retry:
+                       memcg = obj_cgroup_memcg(old);
+                       if (unlikely(!css_tryget(&memcg->css)))
+                               goto retry;
                        rcu_read_unlock();
+
+                       __memcg_kmem_uncharge(memcg, nr_pages);
+                       css_put(&memcg->css);
                }
 
                /*
@@ -3300,24 +3304,21 @@ void obj_cgroup_uncharge(struct obj_cgroup *objcg, size_t size)
 
 #endif /* CONFIG_MEMCG_KMEM */
 
-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
 /*
- * Because page_memcg(head) is not set on compound tails, set it now.
+ * Because page_memcg(head) is not set on tails, set it now.
  */
-void mem_cgroup_split_huge_fixup(struct page *head)
+void split_page_memcg(struct page *head, unsigned int nr)
 {
        struct mem_cgroup *memcg = page_memcg(head);
        int i;
 
-       if (mem_cgroup_disabled())
+       if (mem_cgroup_disabled() || !memcg)
                return;
 
-       for (i = 1; i < HPAGE_PMD_NR; i++) {
-               css_get(&memcg->css);
-               head[i].memcg_data = (unsigned long)memcg;
-       }
+       for (i = 1; i < nr; i++)
+               head[i].memcg_data = head->memcg_data;
+       css_get_many(&memcg->css, nr - 1);
 }
-#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
 
 #ifdef CONFIG_MEMCG_SWAP
 /**
@@ -5637,10 +5638,8 @@ static int mem_cgroup_move_account(struct page *page,
                        __mod_lruvec_state(from_vec, NR_ANON_MAPPED, -nr_pages);
                        __mod_lruvec_state(to_vec, NR_ANON_MAPPED, nr_pages);
                        if (PageTransHuge(page)) {
-                               __mod_lruvec_state(from_vec, NR_ANON_THPS,
-                                                  -nr_pages);
-                               __mod_lruvec_state(to_vec, NR_ANON_THPS,
-                                                  nr_pages);
+                               __dec_lruvec_state(from_vec, NR_ANON_THPS);
+                               __inc_lruvec_state(to_vec, NR_ANON_THPS);
                        }
 
                }
@@ -6271,6 +6270,8 @@ static ssize_t memory_high_write(struct kernfs_open_file *of,
        if (err)
                return err;
 
+       page_counter_set_high(&memcg->memory, high);
+
        for (;;) {
                unsigned long nr_pages = page_counter_read(&memcg->memory);
                unsigned long reclaimed;
@@ -6294,10 +6295,7 @@ static ssize_t memory_high_write(struct kernfs_open_file *of,
                        break;
        }
 
-       page_counter_set_high(&memcg->memory, high);
-
        memcg_wb_domain_size_changed(memcg);
-
        return nbytes;
 }
 
@@ -6761,7 +6759,19 @@ int mem_cgroup_charge(struct page *page, struct mm_struct *mm, gfp_t gfp_mask)
        memcg_check_events(memcg, page);
        local_irq_enable();
 
-       if (PageSwapCache(page)) {
+       /*
+        * Cgroup1's unified memory+swap counter has been charged with the
+        * new swapcache page, finish the transfer by uncharging the swap
+        * slot. The swap slot would also get uncharged when it dies, but
+        * it can stick around indefinitely and we'd count the page twice
+        * the entire time.
+        *
+        * Cgroup2 has separate resource counters for memory and swap,
+        * so this is a non-issue here. Memory and swap charge lifetimes
+        * correspond 1:1 to page and swap slot lifetimes: we charge the
+        * page to memory here, and uncharge swap when the slot is freed.
+        */
+       if (do_memsw_account() && PageSwapCache(page)) {
                swp_entry_t entry = { .val = page_private(page) };
                /*
                 * The swap entry might not get freed for a long time,