Skip to content

Commit 5660ee5

Browse files
committed
mm, slab: use frozen pages for large kmalloc
Since slab pages are now frozen, it makes sense to have large kmalloc() objects behave same as small kmalloc(), as the choice between the two is an implementation detail depending on allocation size. Notably, increasing refcount on a slab page containing kmalloc() object is not possible anymore, so it should be consistent for large kmalloc pages. Therefore, change large kmalloc to use the frozen pages API. Because of some unexpected fallout in the slab pages case (see commit b9c0e49 ("mm: decline to manipulate the refcount on a slab page"), implement the same kind of checks and warnings as part of this change. Notably, networking code using sendpage_ok() to determine whether the page refcount can be manipulated in the network stack should continue behaving correctly. Before this change, the function returns true for large kmalloc pages and page refcount can be manipulated. After this change, the function will return false. Acked-by: Roman Gushchin <[email protected]> Acked-by: Harry Yoo <[email protected]> Signed-off-by: Vlastimil Babka <[email protected]>
1 parent e2d18cb commit 5660ee5

File tree

2 files changed

+6
-4
lines changed

2 files changed

+6
-4
lines changed

include/linux/mm.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1325,6 +1325,8 @@ static inline void get_page(struct page *page)
13251325
struct folio *folio = page_folio(page);
13261326
if (WARN_ON_ONCE(folio_test_slab(folio)))
13271327
return;
1328+
if (WARN_ON_ONCE(folio_test_large_kmalloc(folio)))
1329+
return;
13281330
folio_get(folio);
13291331
}
13301332

@@ -1419,7 +1421,7 @@ static inline void put_page(struct page *page)
14191421
{
14201422
struct folio *folio = page_folio(page);
14211423

1422-
if (folio_test_slab(folio))
1424+
if (folio_test_slab(folio) || folio_test_large_kmalloc(folio))
14231425
return;
14241426

14251427
folio_put(folio);

mm/slub.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4271,9 +4271,9 @@ static void *___kmalloc_large_node(size_t size, gfp_t flags, int node)
42714271
flags |= __GFP_COMP;
42724272

42734273
if (node == NUMA_NO_NODE)
4274-
folio = (struct folio *)alloc_pages_noprof(flags, order);
4274+
folio = (struct folio *)alloc_frozen_pages_noprof(flags, order);
42754275
else
4276-
folio = (struct folio *)__alloc_pages_noprof(flags, order, node, NULL);
4276+
folio = (struct folio *)__alloc_frozen_pages_noprof(flags, order, node, NULL);
42774277

42784278
if (folio) {
42794279
ptr = folio_address(folio);
@@ -4770,7 +4770,7 @@ static void free_large_kmalloc(struct folio *folio, void *object)
47704770
lruvec_stat_mod_folio(folio, NR_SLAB_UNRECLAIMABLE_B,
47714771
-(PAGE_SIZE << order));
47724772
__folio_clear_large_kmalloc(folio);
4773-
folio_put(folio);
4773+
free_frozen_pages(&folio->page, order);
47744774
}
47754775

47764776
/*

0 commit comments

Comments
 (0)