Merge tag '4.13-fixes' of git://git.lwn.net/linux
[sfrench/cifs-2.6.git] / mm / huge_memory.c
index 88c6167f194db0ec07d707329569c2d4a9d34876..86975dec0ba160feadfb8aa0d13b8f2be943638d 100644 (file)
@@ -1575,8 +1575,8 @@ bool madvise_free_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma,
                get_page(page);
                spin_unlock(ptl);
                split_huge_page(page);
-               put_page(page);
                unlock_page(page);
+               put_page(page);
                goto out_unlocked;
        }
 
@@ -2203,7 +2203,7 @@ static void __split_huge_page_tail(struct page *head, int tail,
         * atomic_set() here would be safe on all archs (and not only on x86),
         * it's safer to use atomic_inc()/atomic_add().
         */
-       if (PageAnon(head)) {
+       if (PageAnon(head) && !PageSwapCache(head)) {
                page_ref_inc(page_tail);
        } else {
                /* Additional pin to radix tree */
@@ -2214,6 +2214,7 @@ static void __split_huge_page_tail(struct page *head, int tail,
        page_tail->flags |= (head->flags &
                        ((1L << PG_referenced) |
                         (1L << PG_swapbacked) |
+                        (1L << PG_swapcache) |
                         (1L << PG_mlocked) |
                         (1L << PG_uptodate) |
                         (1L << PG_active) |
@@ -2276,7 +2277,11 @@ static void __split_huge_page(struct page *page, struct list_head *list,
        ClearPageCompound(head);
        /* See comment in __split_huge_page_tail() */
        if (PageAnon(head)) {
-               page_ref_inc(head);
+               /* Additional pin to radix tree of swap cache */
+               if (PageSwapCache(head))
+                       page_ref_add(head, 2);
+               else
+                       page_ref_inc(head);
        } else {
                /* Additional pin to radix tree */
                page_ref_add(head, 2);
@@ -2385,6 +2390,21 @@ int page_trans_huge_mapcount(struct page *page, int *total_mapcount)
        return ret;
 }
 
+/* Racy check whether the huge page can be split */
+bool can_split_huge_page(struct page *page, int *pextra_pins)
+{
+       int extra_pins;
+
+       /* Additional pins from radix tree */
+       if (PageAnon(page))
+               extra_pins = PageSwapCache(page) ? HPAGE_PMD_NR : 0;
+       else
+               extra_pins = HPAGE_PMD_NR;
+       if (pextra_pins)
+               *pextra_pins = extra_pins;
+       return total_mapcount(page) == page_count(page) - extra_pins - 1;
+}
+
 /*
  * This function splits huge page into normal pages. @page can point to any
  * subpage of huge page to split. Split doesn't change the position of @page.
@@ -2432,7 +2452,6 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
                        ret = -EBUSY;
                        goto out;
                }
-               extra_pins = 0;
                mapping = NULL;
                anon_vma_lock_write(anon_vma);
        } else {
@@ -2444,8 +2463,6 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
                        goto out;
                }
 
-               /* Addidional pins from radix tree */
-               extra_pins = HPAGE_PMD_NR;
                anon_vma = NULL;
                i_mmap_lock_read(mapping);
        }
@@ -2454,7 +2471,7 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
         * Racy check if we can split the page, before freeze_page() will
         * split PMDs
         */
-       if (total_mapcount(head) != page_count(head) - extra_pins - 1) {
+       if (!can_split_huge_page(head, &extra_pins)) {
                ret = -EBUSY;
                goto out_unlock;
        }