]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - mm/swap_state.c
userfaultfd: hugetlbfs: prevent UFFDIO_COPY to fill beyond the end of i_size
[mirror_ubuntu-artful-kernel.git] / mm / swap_state.c
index 9c71b6b2562fee671e710347c7f4ff6ae54400ac..fe9309ba948c4e0dcdd4a3c00fbd472ab1c5f6b8 100644 (file)
@@ -219,6 +219,17 @@ int add_to_swap(struct page *page)
                 * clear SWAP_HAS_CACHE flag.
                 */
                goto fail;
+       /*
+        * Normally the page will be dirtied in unmap because its pte should be
+        * dirty. A special case is MADV_FREE page. The page'e pte could have
+        * dirty bit cleared but the page's SwapBacked bit is still set because
+        * clearing the dirty bit and SwapBacked bit has no lock protected. For
+        * such page, unmap will not set dirty bit for it, so page reclaim will
+        * not write the page out. This can cause data corruption when the page
+        * is swap in later. Always setting the dirty bit for the page solves
+        * the problem.
+        */
+       set_page_dirty(page);
 
        return 1;
 
@@ -412,14 +423,14 @@ struct page *__read_swap_cache_async(swp_entry_t entry, gfp_t gfp_mask,
  * the swap entry is no longer in use.
  */
 struct page *read_swap_cache_async(swp_entry_t entry, gfp_t gfp_mask,
-                       struct vm_area_struct *vma, unsigned long addr)
+               struct vm_area_struct *vma, unsigned long addr, bool do_poll)
 {
        bool page_was_allocated;
        struct page *retpage = __read_swap_cache_async(entry, gfp_mask,
                        vma, addr, &page_was_allocated);
 
        if (page_was_allocated)
-               swap_readpage(retpage);
+               swap_readpage(retpage, do_poll);
 
        return retpage;
 }
@@ -496,11 +507,13 @@ struct page *swapin_readahead(swp_entry_t entry, gfp_t gfp_mask,
        unsigned long start_offset, end_offset;
        unsigned long mask;
        struct blk_plug plug;
+       bool do_poll = true;
 
        mask = swapin_nr_pages(offset) - 1;
        if (!mask)
                goto skip;
 
+       do_poll = false;
        /* Read a page_cluster sized and aligned cluster around offset. */
        start_offset = offset & ~mask;
        end_offset = offset | mask;
@@ -511,7 +524,7 @@ struct page *swapin_readahead(swp_entry_t entry, gfp_t gfp_mask,
        for (offset = start_offset; offset <= end_offset ; offset++) {
                /* Ok, do the async read-ahead now */
                page = read_swap_cache_async(swp_entry(swp_type(entry), offset),
-                                               gfp_mask, vma, addr);
+                                               gfp_mask, vma, addr, false);
                if (!page)
                        continue;
                if (offset != entry_offset && likely(!PageTransCompound(page)))
@@ -522,7 +535,7 @@ struct page *swapin_readahead(swp_entry_t entry, gfp_t gfp_mask,
 
        lru_add_drain();        /* Push any new pages onto the LRU now */
 skip:
-       return read_swap_cache_async(entry, gfp_mask, vma, addr);
+       return read_swap_cache_async(entry, gfp_mask, vma, addr, do_poll);
 }
 
 int init_swap_address_space(unsigned int type, unsigned long nr_pages)