diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 934c08de74f4..94398e024d3a 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -2403,7 +2403,7 @@ static void __split_huge_page_tail(struct page *head, int tail, } static void __split_huge_page(struct page *page, struct list_head *list, - pgoff_t end) + pgoff_t end, struct address_space *mapping) { struct page *head = compound_head(page); struct lruvec *lruvec; @@ -2476,6 +2476,16 @@ static void __split_huge_page(struct page *page, struct list_head *list, split_swap_cluster(entry); } + /* + * Drop the mapping while the head page is still locked and thus pins + * the inode. The loop below may free the after-split subpages -- + * including the head, when @page is a tail beyond EOF that the split + * dropped from the page cache -- which could otherwise let the inode, + * and @mapping, be freed before this unlock. + */ + if (mapping) + i_mmap_unlock_read(mapping); + for (i = 0; i < nr; i++) { struct page *subpage = head + i; if (subpage == page) @@ -2717,7 +2727,9 @@ int split_huge_page_to_list(struct page *page, struct list_head *list) } } - __split_huge_page(page, list, end); + __split_huge_page(page, list, end, mapping); + /* __split_huge_page() dropped the i_mmap lock */ + mapping = NULL; ret = 0; } else { spin_unlock(&ds_queue->split_queue_lock);