mm:free unused pages in kmalloc_order
Subsystems (2)
PATCH 1/1 mm:free unused pages in kmalloc_order
Environment using the slub allocator, 1G memory in my ARM32. kmalloc(1024, GFP_HIGHUSER) can allocate memory normally, kmalloc(64*1024, GFP_HIGHUSER) will cause a memory leak, because alloc_pages returns highmem physical pages, but it cannot be directly converted into a virtual address and return NULL, the pages has not been released. Usually driver developers will not use the GFP_HIGHUSER flag to allocate memory in kmalloc, but I think this memory leak is not perfect, it is best to be fixed. This is the first time I have posted a patch, there may be something wrong.
--- mm/slab_common.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
mm/slab_common.c +6 -2
@@ -819,8 +819,12 @@ void *kmalloc_order(size_t size, gfp_t flags, unsigned int order) page =alloc_pages (flags, order);if (likely (page)) { ret =page_address (page); -mod_node_page_state (page_pgdat (page),NR_SLAB_UNRECLAIMABLE_B , -PAGE_SIZE << order); +if (ret) +mod_node_page_state (page_pgdat (page), +NR_SLAB_UNRECLAIMABLE_B , +PAGE_SIZE << order); +else +__free_pages (page, order); } ret =kasan_kmalloc_large (ret, size, flags);/* As ret might get tagged, call kmemleak hook after KASAN. */
Signature · 1 line
2.17.1
Quoted 9 lines · Long Li
Environment using the slub allocator, 1G memory in my ARM32.
kmalloc(1024, GFP_HIGHUSER)can allocate memory normally,kmalloc(64*1024, GFP_HIGHUSER)will cause a memory leak, becausealloc_pagesreturns highmem physical pages, but it cannot be directly converted into a virtual address and return NULL, the pages has not been released. Usually driver developers will not use theGFP_HIGHUSERflag to allocate memory in kmalloc, but I think this memory leak is not perfect, it is best to be fixed. This is the first time I have posted a patch, there may be something wrong.
Slab used to disallow GFP_HIGHMEM allocations earlier than this, so you'd never get here. See one moron's patch here, 20 years ago ...
https://lore.kernel.org/lkml/[email protected]/
Things changed a bit since then. SLAB_LEVEL_MASK became GFP_SLAB_BUG_MASK, then GFP_SLAB_BUG_MASK moved to mm/internal.h. Nowadays, GFP_SLAB_BUG_MASK is checked only in new_slab(), and it is definitely skipped when we go through the kmalloc_large() patch.
Could you send a replacement patch which checks GFP_SLAB_BUG_MASK before calling alloc_pages()?
Quoted 20 lines
+++
b/mm/slab_common.cmm/slab_common.c +6
-2@@ -819,8 +819,12 @@ void *kmalloc_order(size_t size, gfp_t flags, unsigned int order) page =alloc_pages (flags, order);if (likely (page)) { ret =page_address (page); -mod_node_page_state (page_pgdat (page),NR_SLAB_UNRECLAIMABLE_B , -PAGE_SIZE << order); +if (ret) +mod_node_page_state (page_pgdat (page), +NR_SLAB_UNRECLAIMABLE_B , +PAGE_SIZE << order); +else +__free_pages (page, order); } ret =kasan_kmalloc_large (ret, size, flags);/* As ret might get tagged, call kmemleak hook after KASAN. */ Signature · 1 line
2.17.1
Quoted 1 line · Matthew Wilcox
Slab used to disallow
GFP_HIGHMEMallocations earlier than this,
It is still not allowed and not supported.
Quoted 9 lines · Long Li
Environment using the slub allocator, 1G memory in my ARM32.
kmalloc(1024, GFP_HIGHUSER)can allocate memory normally,kmalloc(64*1024, GFP_HIGHUSER)will cause a memory leak, becausealloc_pagesreturns highmem physical pages, but it cannot be directly converted into a virtual address and return NULL, the pages has not been released. Usually driver developers will not use theGFP_HIGHUSERflag to allocate memory in kmalloc, but I think this memory leak is not perfect, it is best to be fixed. This is the first time I have posted a patch, there may be something wrong.
Highmem is not supported by the slab allocators. Please ensure that there is a warning generated if someone attempts to do such an allocation. We used to check for that.
In order to make such allocations possible one would have to create yet another kmalloc array for high memory.
Quoted 11 lines · Christopher Lameter
Quoted 9 lines · Long Li
Environment using the slub allocator, 1G memory in my ARM32.
kmalloc(1024, GFP_HIGHUSER)can allocate memory normally,kmalloc(64*1024, GFP_HIGHUSER)will cause a memory leak, becausealloc_pagesreturns highmem physical pages, but it cannot be directly converted into a virtual address and return NULL, the pages has not been released. Usually driver developers will not use theGFP_HIGHUSERflag to allocate memory in kmalloc, but I think this memory leak is not perfect, it is best to be fixed. This is the first time I have posted a patch, there may be something wrong.
Quoted 3 lines
Highmem is not supported by the slab allocators. Please ensure that there is a warning generated if someone attempts to do such an allocation. We used to check for that.
Sounds like we need a test somewhere that checks this behaviour.
Quoted 2 lines
In order to make such allocations possible one would have to create yet another kmalloc array for high memory.
Not for this case because it goes straight to kmalloc_order(). What does make this particular case impossible is that we can't kmap() a compound page. We could vmap it, but why are we bothering?
Quoted 8 lines · Matthew Wilcox
Sounds like we need a test somewhere that checks this behaviour.
Quoted 2 lines
In order to make such allocations possible one would have to create yet another kmalloc array for high memory.
Not for this case because it goes straight to
kmalloc_order(). What does make this particular case impossible is that we can'tkmap()a compound page. We could vmap it, but why are we bothering?
Well yes it will work if the slab allocator falls back to the page allocator. Higher order allocation through kmalloc ;-). How much fun and uselessness ....
Why not call the page allocator directly and play with all the bits you want? Any regular small object allocation with GFP_HIGH will lead to strange effects if the bit is not checked.