OSDN Git Service

Merge tag 'nios2-v4.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/lftan...
[tomoyo/tomoyo-test1.git] / mm / huge_memory.c
index 87ab9b8..14ed6ee 100644 (file)
@@ -2355,26 +2355,13 @@ static void __split_huge_page_tail(struct page *head, int tail,
        struct page *page_tail = head + tail;
 
        VM_BUG_ON_PAGE(atomic_read(&page_tail->_mapcount) != -1, page_tail);
-       VM_BUG_ON_PAGE(page_ref_count(page_tail) != 0, page_tail);
 
        /*
-        * tail_page->_refcount is zero and not changing from under us. But
-        * get_page_unless_zero() may be running from under us on the
-        * tail_page. If we used atomic_set() below instead of atomic_inc() or
-        * atomic_add(), we would then run atomic_set() concurrently with
-        * get_page_unless_zero(), and atomic_set() is implemented in C not
-        * using locked ops. spin_unlock on x86 sometime uses locked ops
-        * because of PPro errata 66, 92, so unless somebody can guarantee
-        * atomic_set() here would be safe on all archs (and not only on x86),
-        * it's safer to use atomic_inc()/atomic_add().
+        * Clone page flags before unfreezing refcount.
+        *
+        * After successful get_page_unless_zero() might follow flags change,
+        * for exmaple lock_page() which set PG_waiters.
         */
-       if (PageAnon(head) && !PageSwapCache(head)) {
-               page_ref_inc(page_tail);
-       } else {
-               /* Additional pin to radix tree */
-               page_ref_add(page_tail, 2);
-       }
-
        page_tail->flags &= ~PAGE_FLAGS_CHECK_AT_PREP;
        page_tail->flags |= (head->flags &
                        ((1L << PG_referenced) |
@@ -2387,14 +2374,21 @@ static void __split_huge_page_tail(struct page *head, int tail,
                         (1L << PG_unevictable) |
                         (1L << PG_dirty)));
 
-       /*
-        * After clearing PageTail the gup refcount can be released.
-        * Page flags also must be visible before we make the page non-compound.
-        */
+       /* Page flags must be visible before we make the page non-compound. */
        smp_wmb();
 
+       /*
+        * Clear PageTail before unfreezing page refcount.
+        *
+        * After successful get_page_unless_zero() might follow put_page()
+        * which needs correct compound_head().
+        */
        clear_compound_head(page_tail);
 
+       /* Finally unfreeze refcount. Additional reference from page cache. */
+       page_ref_unfreeze(page_tail, 1 + (!PageAnon(head) ||
+                                         PageSwapCache(head)));
+
        if (page_is_young(head))
                set_page_young(page_tail);
        if (page_is_idle(head))
@@ -2407,6 +2401,12 @@ static void __split_huge_page_tail(struct page *head, int tail,
 
        page_tail->index = head->index + tail;
        page_cpupid_xchg_last(page_tail, page_cpupid_last(head));
+
+       /*
+        * always add to the tail because some iterators expect new
+        * pages to show after the currently processed elements - e.g.
+        * migrate_pages
+        */
        lru_add_page_tail(head, page_tail, lruvec, list);
 }
 
@@ -2450,7 +2450,7 @@ static void __split_huge_page(struct page *page, struct list_head *list,
        } else {
                /* Additional pin to radix tree */
                page_ref_add(head, 2);
-               spin_unlock(&head->mapping->tree_lock);
+               xa_unlock(&head->mapping->i_pages);
        }
 
        spin_unlock_irqrestore(zone_lru_lock(page_zone(head)), flags);
@@ -2658,15 +2658,15 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
        if (mapping) {
                void **pslot;
 
-               spin_lock(&mapping->tree_lock);
-               pslot = radix_tree_lookup_slot(&mapping->page_tree,
+               xa_lock(&mapping->i_pages);
+               pslot = radix_tree_lookup_slot(&mapping->i_pages,
                                page_index(head));
                /*
                 * Check if the head page is present in radix tree.
                 * We assume all tail are present too, if head is there.
                 */
                if (radix_tree_deref_slot_protected(pslot,
-                                       &mapping->tree_lock) != head)
+                                       &mapping->i_pages.xa_lock) != head)
                        goto fail;
        }
 
@@ -2700,7 +2700,7 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
                }
                spin_unlock(&pgdata->split_queue_lock);
 fail:          if (mapping)
-                       spin_unlock(&mapping->tree_lock);
+                       xa_unlock(&mapping->i_pages);
                spin_unlock_irqrestore(zone_lru_lock(page_zone(head)), flags);
                unfreeze_page(head);
                ret = -EBUSY;
@@ -2783,11 +2783,13 @@ static unsigned long deferred_split_scan(struct shrinker *shrink,
 
        list_for_each_safe(pos, next, &list) {
                page = list_entry((void *)pos, struct page, mapping);
-               lock_page(page);
+               if (!trylock_page(page))
+                       goto next;
                /* split_huge_page() removes page from list on success */
                if (!split_huge_page(page))
                        split++;
                unlock_page(page);
+next:
                put_page(page);
        }