diff options
author | Michal Hocko <mhocko@suse.com> | 2018-02-21 17:46:01 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-02-21 18:35:43 -0500 |
commit | 698d0831ba87b92ae10b15e8203cfd59f5a59a35 (patch) | |
tree | 278028f8b10798d696543a5249432f85eec1b855 /mm/vmalloc.c | |
parent | bdefe01a6b14bde268741435ac854fda4ef7e847 (diff) |
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@linux-foundation.org: coding-style fixes]
Link: http://lkml.kernel.org/r/20180212095019.GX21609@dhcp22.suse.cz
Fixes: 19809c2da28a ("mm, vmalloc: use __GFP_HIGHMEM implicitly”)
Signed-off-by: Michal Hocko <mhocko@suse.com>
Reported-by: Kai Heng Feng <kai.heng.feng@canonical.com>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Laura Abbott <labbott@redhat.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/vmalloc.c')
-rw-r--r-- | mm/vmalloc.c | 10 |
1 files changed, 7 insertions, 3 deletions
diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 673942094328..ebff729cc956 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c | |||
@@ -1943,11 +1943,15 @@ void *vmalloc_exec(unsigned long size) | |||
1943 | } | 1943 | } |
1944 | 1944 | ||
1945 | #if defined(CONFIG_64BIT) && defined(CONFIG_ZONE_DMA32) | 1945 | #if defined(CONFIG_64BIT) && defined(CONFIG_ZONE_DMA32) |
1946 | #define GFP_VMALLOC32 GFP_DMA32 | GFP_KERNEL | 1946 | #define GFP_VMALLOC32 (GFP_DMA32 | GFP_KERNEL) |
1947 | #elif defined(CONFIG_64BIT) && defined(CONFIG_ZONE_DMA) | 1947 | #elif defined(CONFIG_64BIT) && defined(CONFIG_ZONE_DMA) |
1948 | #define GFP_VMALLOC32 GFP_DMA | GFP_KERNEL | 1948 | #define GFP_VMALLOC32 (GFP_DMA | GFP_KERNEL) |
1949 | #else | 1949 | #else |
1950 | #define GFP_VMALLOC32 GFP_KERNEL | 1950 | /* |
1951 | * 64b systems should always have either DMA or DMA32 zones. For others | ||
1952 | * GFP_DMA32 should do the right thing and use the normal zone. | ||
1953 | */ | ||
1954 | #define GFP_VMALLOC32 GFP_DMA32 | GFP_KERNEL | ||
1951 | #endif | 1955 | #endif |
1952 | 1956 | ||
1953 | /** | 1957 | /** |