ubsan: disable UBSAN_TRAP for all*config
[linux-2.6-microblaze.git] / mm / mlock.c
index 884b121..55b3b36 100644 (file)
@@ -105,26 +105,6 @@ void mlock_vma_page(struct page *page)
        }
 }
 
-/*
- * Isolate a page from LRU with optional get_page() pin.
- * Assumes lru_lock already held and page already pinned.
- */
-static bool __munlock_isolate_lru_page(struct page *page, bool getpage)
-{
-       if (PageLRU(page)) {
-               struct lruvec *lruvec;
-
-               lruvec = mem_cgroup_page_lruvec(page, page_pgdat(page));
-               if (getpage)
-                       get_page(page);
-               ClearPageLRU(page);
-               del_page_from_lru_list(page, lruvec, page_lru(page));
-               return true;
-       }
-
-       return false;
-}
-
 /*
  * Finish munlock after successful page isolation
  *
@@ -187,40 +167,24 @@ static void __munlock_isolation_failed(struct page *page)
 unsigned int munlock_vma_page(struct page *page)
 {
        int nr_pages;
-       pg_data_t *pgdat = page_pgdat(page);
 
        /* For try_to_munlock() and to serialize with page migration */
        BUG_ON(!PageLocked(page));
-
        VM_BUG_ON_PAGE(PageTail(page), page);
 
-       /*
-        * Serialize with any parallel __split_huge_page_refcount() which
-        * might otherwise copy PageMlocked to part of the tail pages before
-        * we clear it in the head page. It also stabilizes thp_nr_pages().
-        */
-       spin_lock_irq(&pgdat->lru_lock);
-
        if (!TestClearPageMlocked(page)) {
                /* Potentially, PTE-mapped THP: do not skip the rest PTEs */
-               nr_pages = 1;
-               goto unlock_out;
+               return 0;
        }
 
        nr_pages = thp_nr_pages(page);
-       __mod_zone_page_state(page_zone(page), NR_MLOCK, -nr_pages);
+       mod_zone_page_state(page_zone(page), NR_MLOCK, -nr_pages);
 
-       if (__munlock_isolate_lru_page(page, true)) {
-               spin_unlock_irq(&pgdat->lru_lock);
+       if (!isolate_lru_page(page))
                __munlock_isolated_page(page);
-               goto out;
-       }
-       __munlock_isolation_failed(page);
-
-unlock_out:
-       spin_unlock_irq(&pgdat->lru_lock);
+       else
+               __munlock_isolation_failed(page);
 
-out:
        return nr_pages - 1;
 }
 
@@ -298,12 +262,12 @@ static void __munlock_pagevec(struct pagevec *pvec, struct zone *zone)
        int nr = pagevec_count(pvec);
        int delta_munlocked = -nr;
        struct pagevec pvec_putback;
+       struct lruvec *lruvec = NULL;
        int pgrescued = 0;
 
        pagevec_init(&pvec_putback);
 
        /* Phase 1: page isolation */
-       spin_lock_irq(&zone->zone_pgdat->lru_lock);
        for (i = 0; i < nr; i++) {
                struct page *page = pvec->pages[i];
 
@@ -312,9 +276,12 @@ static void __munlock_pagevec(struct pagevec *pvec, struct zone *zone)
                         * We already have pin from follow_page_mask()
                         * so we can spare the get_page() here.
                         */
-                       if (__munlock_isolate_lru_page(page, false))
+                       if (TestClearPageLRU(page)) {
+                               lruvec = relock_page_lruvec_irq(page, lruvec);
+                               del_page_from_lru_list(page, lruvec,
+                                                       page_lru(page));
                                continue;
-                       else
+                       else
                                __munlock_isolation_failed(page);
                } else {
                        delta_munlocked++;
@@ -329,8 +296,12 @@ static void __munlock_pagevec(struct pagevec *pvec, struct zone *zone)
                pagevec_add(&pvec_putback, pvec->pages[i]);
                pvec->pages[i] = NULL;
        }
-       __mod_zone_page_state(zone, NR_MLOCK, delta_munlocked);
-       spin_unlock_irq(&zone->zone_pgdat->lru_lock);
+       if (lruvec) {
+               __mod_zone_page_state(zone, NR_MLOCK, delta_munlocked);
+               unlock_page_lruvec_irq(lruvec);
+       } else if (delta_munlocked) {
+               mod_zone_page_state(zone, NR_MLOCK, delta_munlocked);
+       }
 
        /* Now we can release pins of pages that we are not munlocking */
        pagevec_release(&pvec_putback);