memcg: take reference before releasing rcu_read_lock
[firefly-linux-kernel-4.4.55.git] / mm / swap.c
index 8a529a01e8fc79ebda8cfe30191fa9fb1d754b77..acd40bfffa8287cb0942297feb9dd0ceceb8e368 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -737,7 +737,7 @@ EXPORT_SYMBOL(__pagevec_release);
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 /* used by __split_huge_page_refcount() */
 void lru_add_page_tail(struct page *page, struct page *page_tail,
-                      struct lruvec *lruvec)
+                      struct lruvec *lruvec, struct list_head *list)
 {
        int uninitialized_var(active);
        enum lru_list lru;
@@ -749,7 +749,8 @@ void lru_add_page_tail(struct page *page, struct page *page_tail,
        VM_BUG_ON(NR_CPUS != 1 &&
                  !spin_is_locked(&lruvec_zone(lruvec)->lru_lock));
 
-       SetPageLRU(page_tail);
+       if (!list)
+               SetPageLRU(page_tail);
 
        if (page_evictable(page_tail)) {
                if (PageActive(page)) {
@@ -767,7 +768,11 @@ void lru_add_page_tail(struct page *page, struct page *page_tail,
 
        if (likely(PageLRU(page)))
                list_add_tail(&page_tail->lru, &page->lru);
-       else {
+       else if (list) {
+               /* page reclaim is reclaiming a huge page */
+               get_page(page_tail);
+               list_add_tail(&page_tail->lru, list);
+       } else {
                struct list_head *list_head;
                /*
                 * Head page has not yet been counted, as an hpage,