lkml.org 
[lkml]   [2016]   [Nov]   [29]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCHv5 05/36] thp: try to free page's buffers before attempt split
    Date
    We want page to be isolated from the rest of the system before spliting
    it. We rely on page count to be 2 for file pages to make sure nobody
    uses the page: one pin to caller, one to radix-tree.

    Filesystems with backing storage can have page count increased if it has
    buffers.

    Let's try to free them, before attempt split. And remove one guarding
    VM_BUG_ON_PAGE().

    Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
    ---
    include/linux/buffer_head.h | 1 +
    mm/huge_memory.c | 19 ++++++++++++++++++-
    2 files changed, 19 insertions(+), 1 deletion(-)

    diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
    index d67ab83823ad..fd4134ce9c54 100644
    --- a/include/linux/buffer_head.h
    +++ b/include/linux/buffer_head.h
    @@ -400,6 +400,7 @@ extern int __set_page_dirty_buffers(struct page *page);
    #else /* CONFIG_BLOCK */

    static inline void buffer_init(void) {}
    +static inline int page_has_buffers(struct page *page) { return 0; }
    static inline int try_to_free_buffers(struct page *page) { return 1; }
    static inline int inode_has_buffers(struct inode *inode) { return 0; }
    static inline void invalidate_inode_buffers(struct inode *inode) {}
    diff --git a/mm/huge_memory.c b/mm/huge_memory.c
    index 91dbab9644be..a15d566b14f6 100644
    --- a/mm/huge_memory.c
    +++ b/mm/huge_memory.c
    @@ -30,6 +30,7 @@
    #include <linux/userfaultfd_k.h>
    #include <linux/page_idle.h>
    #include <linux/shmem_fs.h>
    +#include <linux/buffer_head.h>

    #include <asm/tlb.h>
    #include <asm/pgalloc.h>
    @@ -2111,7 +2112,6 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)

    VM_BUG_ON_PAGE(is_huge_zero_page(page), page);
    VM_BUG_ON_PAGE(!PageLocked(page), page);
    - VM_BUG_ON_PAGE(!PageSwapBacked(page), page);
    VM_BUG_ON_PAGE(!PageCompound(page), page);

    if (PageAnon(head)) {
    @@ -2140,6 +2140,23 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
    goto out;
    }

    + /* Try to free buffers before attempt split */
    + if (!PageSwapBacked(head) && PagePrivate(page)) {
    + /*
    + * We cannot trigger writeback from here due possible
    + * recursion if triggered from vmscan, only wait.
    + *
    + * Caller can trigger writeback it on its own, if safe.
    + */
    + wait_on_page_writeback(head);
    +
    + if (page_has_buffers(head) && !try_to_release_page(head,
    + GFP_KERNEL)) {
    + ret = -EBUSY;
    + goto out;
    + }
    + }
    +
    /* Addidional pin from radix tree */
    extra_pins = 1;
    anon_vma = NULL;
    --
    2.10.2
    \
     
     \ /
      Last update: 2016-11-29 12:28    [W:2.090 / U:0.020 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site