On Sun, Apr 22, 2018 at 11:59:15AM +0200, Greg KH wrote:
On Sun, Apr 22, 2018 at 02:52:40AM -0700, Nathan Chancellor wrote:
On Sun, Apr 22, 2018 at 11:33:42AM +0200, gregkh@linuxfoundation.org wrote:
The patch below does not apply to the 4.4-stable tree. If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to stable@vger.kernel.org.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From abc1be13fd113ddef5e2d807a466286b864caed3 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox mawilcox@microsoft.com Date: Fri, 20 Apr 2018 14:56:20 -0700 Subject: [PATCH] mm/filemap.c: fix NULL pointer in page_cache_tree_insert()
f2fs specifies the __GFP_ZERO flag for allocating some of its pages. Unfortunately, the page cache also uses the mapping's GFP flags for allocating radix tree nodes. It always masked off the __GFP_HIGHMEM flag, and masks off __GFP_ZERO in some paths, but not all. That causes radix tree nodes to be allocated with a NULL list_head, which causes backtraces like:
__list_del_entry+0x30/0xd0 list_lru_del+0xac/0x1ac page_cache_tree_insert+0xd8/0x110
The __GFP_DMA and __GFP_DMA32 flags would also be able to sneak through if they are ever used. Fix them all by using GFP_RECLAIM_MASK at the innermost location, and remove it from earlier in the callchain.
Link: http://lkml.kernel.org/r/20180411060320.14458-2-willy@infradead.org Fixes: 449dd6984d0e ("mm: keep page cache radix tree nodes in check") Signed-off-by: Matthew Wilcox mawilcox@microsoft.com Reported-by: Chris Fries cfries@google.com Debugged-by: Minchan Kim minchan@kernel.org Acked-by: Johannes Weiner hannes@cmpxchg.org Acked-by: Michal Hocko mhocko@suse.com Reviewed-by: Jan Kara jack@suse.cz Cc: stable@vger.kernel.org Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org
diff --git a/mm/filemap.c b/mm/filemap.c index 9276bdb2343c..0604cb02e6f3 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -786,7 +786,7 @@ int replace_page_cache_page(struct page *old, struct page *new, gfp_t gfp_mask) VM_BUG_ON_PAGE(!PageLocked(new), new); VM_BUG_ON_PAGE(new->mapping, new);
- error = radix_tree_preload(gfp_mask & ~__GFP_HIGHMEM);
- error = radix_tree_preload(gfp_mask & GFP_RECLAIM_MASK); if (!error) { struct address_space *mapping = old->mapping; void (*freepage)(struct page *);
@@ -842,7 +842,7 @@ static int __add_to_page_cache_locked(struct page *page, return error; }
- error = radix_tree_maybe_preload(gfp_mask & ~__GFP_HIGHMEM);
- error = radix_tree_maybe_preload(gfp_mask & GFP_RECLAIM_MASK); if (error) { if (!huge) mem_cgroup_cancel_charge(page, memcg, false);
@@ -1585,8 +1585,7 @@ struct page *pagecache_get_page(struct address_space *mapping, pgoff_t offset, if (fgp_flags & FGP_ACCESSED) __SetPageReferenced(page);
err = add_to_page_cache_lru(page, mapping, offset,
gfp_mask & GFP_RECLAIM_MASK);
if (unlikely(err)) { put_page(page); page = NULL;err = add_to_page_cache_lru(page, mapping, offset, gfp_mask);
@@ -2387,7 +2386,7 @@ static int page_cache_read(struct file *file, pgoff_t offset, gfp_t gfp_mask) if (!page) return -ENOMEM;
ret = add_to_page_cache_lru(page, mapping, offset, gfp_mask & GFP_KERNEL);
if (ret == 0) ret = mapping->a_ops->readpage(file, page); else if (ret == -EEXIST)ret = add_to_page_cache_lru(page, mapping, offset, gfp_mask);
It looks like c20cd45eb017 ("mm: allow GFP_{FS,IO} for page_cache_read page cache allocation") came in during 4.5 and reorganized a few things around the last section.
If you pick that commit then this one, it will be clean (just tested on 4.4.128).
Ah yes, thanks!
Doesn't work for 3.18.y, let me go dig a bit into why that is...
Ick, 3.18.y is a mess in this area, I'll just leave that alone :)
greg k-h