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.
Unified · Split
| @@ -786,7 +786,7 @@ int replace_page_cache_page(struct page *old, struct page *new, gfp_t gfp_mask) · 785 unmodified lines | |||
| 786 | VM_BUG_ON_PAGE(!PageLocked(new), new); | 786 | VM_BUG_ON_PAGE(!PageLocked(new), new); |
| 787 | VM_BUG_ON_PAGE(new->mapping, new); | 787 | VM_BUG_ON_PAGE(new->mapping, new); |
| 788 | 788 | ||
| 789 | error = radix_tree_preload(gfp_mask & ~__GFP_HIGHMEM); | 789 | error = radix_tree_preload(gfp_mask & GFP_RECLAIM_MASK); |
| 790 | if (!error) { | 790 | if (!error) { |
| 791 | struct address_space *mapping = old->mapping; | 791 | struct address_space *mapping = old->mapping; |
| 792 | void (*freepage)(struct page *); | 792 | void (*freepage)(struct page *); |
| @@ -842,7 +842,7 @@ static int __add_to_page_cache_locked(struct page *page, · 49 unmodified lines | |||
| 842 | return error; | 842 | return error; |
| 843 | } | 843 | } |
| 844 | 844 | ||
| 845 | error = radix_tree_maybe_preload(gfp_mask & ~__GFP_HIGHMEM); | 845 | error = radix_tree_maybe_preload(gfp_mask & GFP_RECLAIM_MASK); |
| 846 | if (error) { | 846 | if (error) { |
| 847 | if (!huge) | 847 | if (!huge) |
| 848 | mem_cgroup_cancel_charge(page, memcg, false); | 848 | mem_cgroup_cancel_charge(page, memcg, false); |
| @@ -1585,8 +1585,7 @@ no_page: · 736 unmodified lines | |||
| 1585 | if (fgp_flags & FGP_ACCESSED) | 1585 | if (fgp_flags & FGP_ACCESSED) |
| 1586 | __SetPageReferenced(page); | 1586 | __SetPageReferenced(page); |
| 1587 | 1587 | ||
| 1588 | err = add_to_page_cache_lru(page, mapping, offset, | 1588 | err = add_to_page_cache_lru(page, mapping, offset, gfp_mask); |
| 1589 | gfp_mask & GFP_RECLAIM_MASK); | ||
| 1590 | if (unlikely(err)) { | 1589 | if (unlikely(err)) { |
| 1591 | put_page(page); | 1590 | put_page(page); |
| 1592 | page = NULL; | 1591 | page = NULL; |
| @@ -2387,7 +2386,7 @@ static int page_cache_read(struct file *file, pgoff_t offset, gfp_t gfp_mask) · 794 unmodified lines | |||
| 2387 | if (!page) | 2386 | if (!page) |
| 2388 | return -ENOMEM; | 2387 | return -ENOMEM; |
| 2389 | 2388 | ||
| 2390 | ret = add_to_page_cache_lru(page, mapping, offset, gfp_mask & GFP_KERNEL); | 2389 | ret = add_to_page_cache_lru(page, mapping, offset, gfp_mask); |
| 2391 | if (ret == 0) | 2390 | if (ret == 0) |
| 2392 | ret = mapping->a_ops->readpage(file, page); | 2391 | ret = mapping->a_ops->readpage(file, page); |
| 2393 | else if (ret == -EEXIST) | 2392 | else if (ret == -EEXIST) |