[patch 14/16] vmalloc: fix __GFP_HIGHMEM usage for vmalloc_32 on 32b systems

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Michal Hocko <mhocko@xxxxxxxx>
Subject: vmalloc: fix __GFP_HIGHMEM usage for vmalloc_32 on 32b systems

Kai Heng Feng has noticed that BUG_ON(PageHighMem(pg)) triggers in
drivers/media/common/saa7146/saa7146_core.c since 19809c2da28a ("mm,
vmalloc: use __GFP_HIGHMEM implicitly").  saa7146_vmalloc_build_pgtable
uses vmalloc_32 and it is reasonable to expect that the resulting page is
not in highmem.  The above commit aimed to add __GFP_HIGHMEM only for
those requests which do not specify any zone modifier gfp flag. 
vmalloc_32 relies on GFP_VMALLOC32 which should do the right thing. 
Except it has been missed that GFP_VMALLOC32 is an alias for GFP_KERNEL on
32b architectures.  Thanks to Matthew to notice this.

Fix the problem by unconditionally setting GFP_DMA32 in GFP_VMALLOC32 for
!64b arches (as a bailout).  This should do the right thing and use
ZONE_NORMAL which should be always below 4G on 32b systems.

Debugged by Matthew Wilcox.

[akpm@xxxxxxxxxxxxxxxxxxxx: coding-style fixes]
Link: http://lkml.kernel.org/r/20180212095019.GX21609@xxxxxxxxxxxxxx
Fixes: 19809c2da28a ("mm, vmalloc: use __GFP_HIGHMEM implicitly”)
Signed-off-by: Michal Hocko <mhocko@xxxxxxxx>
Reported-by: Kai Heng Feng <kai.heng.feng@xxxxxxxxxxxxx>
Cc: Matthew Wilcox <willy@xxxxxxxxxxxxx>
Cc: Laura Abbott <labbott@xxxxxxxxxx>
Cc: <stable@xxxxxxxxxxxxxxx>
Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx>
---

 mm/vmalloc.c |   10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff -puN mm/vmalloc.c~vmalloc-fix-__gfp_highmem-usage-for-vmalloc_32-on-32b-systems mm/vmalloc.c
--- a/mm/vmalloc.c~vmalloc-fix-__gfp_highmem-usage-for-vmalloc_32-on-32b-systems
+++ a/mm/vmalloc.c
@@ -1943,11 +1943,15 @@ void *vmalloc_exec(unsigned long size)
 }
 
 #if defined(CONFIG_64BIT) && defined(CONFIG_ZONE_DMA32)
-#define GFP_VMALLOC32 GFP_DMA32 | GFP_KERNEL
+#define GFP_VMALLOC32 (GFP_DMA32 | GFP_KERNEL)
 #elif defined(CONFIG_64BIT) && defined(CONFIG_ZONE_DMA)
-#define GFP_VMALLOC32 GFP_DMA | GFP_KERNEL
+#define GFP_VMALLOC32 (GFP_DMA | GFP_KERNEL)
 #else
-#define GFP_VMALLOC32 GFP_KERNEL
+/*
+ * 64b systems should always have either DMA or DMA32 zones. For others
+ * GFP_DMA32 should do the right thing and use the normal zone.
+ */
+#define GFP_VMALLOC32 GFP_DMA32 | GFP_KERNEL
 #endif
 
 /**
_



[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]