]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - mm/swap.c
memcg: fix leak of accounting at failure path of hugepage collapsing
[mv-sheeva.git] / mm / swap.c
index 33f5292fe1325c388ee9db9de64b1b758f00036a..c02f93611a849e6c79bdbae2e13ee6e4cff6eb37 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -131,8 +131,12 @@ static void put_compound_page(struct page *page)
                        atomic_dec(&page->_count);
                        VM_BUG_ON(atomic_read(&page_head->_count) <= 0);
                        compound_unlock_irqrestore(page_head, flags);
-                       if (put_page_testzero(page_head))
-                               __put_compound_page(page_head);
+                       if (put_page_testzero(page_head)) {
+                               if (PageHead(page_head))
+                                       __put_compound_page(page_head);
+                               else
+                                       __put_single_page(page_head);
+                       }
                } else {
                        /* page_head is a dangling pointer */
                        VM_BUG_ON(PageTail(page));
@@ -475,6 +479,43 @@ void __pagevec_release(struct pagevec *pvec)
 
 EXPORT_SYMBOL(__pagevec_release);
 
+/* used by __split_huge_page_refcount() */
+void lru_add_page_tail(struct zone* zone,
+                      struct page *page, struct page *page_tail)
+{
+       int active;
+       enum lru_list lru;
+       const int file = 0;
+       struct list_head *head;
+
+       VM_BUG_ON(!PageHead(page));
+       VM_BUG_ON(PageCompound(page_tail));
+       VM_BUG_ON(PageLRU(page_tail));
+       VM_BUG_ON(!spin_is_locked(&zone->lru_lock));
+
+       SetPageLRU(page_tail);
+
+       if (page_evictable(page_tail, NULL)) {
+               if (PageActive(page)) {
+                       SetPageActive(page_tail);
+                       active = 1;
+                       lru = LRU_ACTIVE_ANON;
+               } else {
+                       active = 0;
+                       lru = LRU_INACTIVE_ANON;
+               }
+               update_page_reclaim_stat(zone, page_tail, file, active);
+               if (likely(PageLRU(page)))
+                       head = page->lru.prev;
+               else
+                       head = &zone->lru[lru].list;
+               __add_page_to_lru_list(zone, page_tail, lru, head);
+       } else {
+               SetPageUnevictable(page_tail);
+               add_page_to_lru_list(zone, page_tail, LRU_UNEVICTABLE);
+       }
+}
+
 /*
  * Add the passed pages to the LRU, then drop the caller's refcount
  * on them.  Reinitialises the caller's pagevec.