Skip to content

Commit b9c0e49

Browse files
Matthew Wilcox (Oracle)akpm00
Matthew Wilcox (Oracle)
authored andcommitted
mm: decline to manipulate the refcount on a slab page
Slab pages now have a refcount of 0, so nobody should be trying to manipulate the refcount on them. Doing so has little effect; the object could be freed and reallocated to a different purpose, although the slab itself would not be until the refcount was put making it behave rather like TYPESAFE_BY_RCU. Unfortunately, __iov_iter_get_pages_alloc() does take a refcount. Fix that to not change the refcount, and make put_page() silently not change the refcount. get_page() warns so that we can fix any other callers that need to be changed. Long-term, networking needs to stop taking a refcount on the pages that it uses and rely on the caller to hold whatever references are necessary to make the memory stable. In the medium term, more page types are going to hav a zero refcount, so we'll want to move get_page() and put_page() out of line. Link: https://lkml.kernel.org/r/[email protected] Fixes: 9aec2fb (slab: allocate frozen pages) Signed-off-by: Matthew Wilcox (Oracle) <[email protected]> Reported-by: Hannes Reinecke <[email protected]> Closes: https://lore.kernel.org/all/[email protected]/ Acked-by: Vlastimil Babka <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 9f01b49 commit b9c0e49

File tree

2 files changed

+13
-3
lines changed

2 files changed

+13
-3
lines changed

include/linux/mm.h

+7-1
Original file line numberDiff line numberDiff line change
@@ -1458,7 +1458,10 @@ static inline void folio_get(struct folio *folio)
14581458

14591459
static inline void get_page(struct page *page)
14601460
{
1461-
folio_get(page_folio(page));
1461+
struct folio *folio = page_folio(page);
1462+
if (WARN_ON_ONCE(folio_test_slab(folio)))
1463+
return;
1464+
folio_get(folio);
14621465
}
14631466

14641467
static inline __must_check bool try_get_page(struct page *page)
@@ -1552,6 +1555,9 @@ static inline void put_page(struct page *page)
15521555
{
15531556
struct folio *folio = page_folio(page);
15541557

1558+
if (folio_test_slab(folio))
1559+
return;
1560+
15551561
/*
15561562
* For some devmap managed pages we need to catch refcount transition
15571563
* from 2 to 1:

lib/iov_iter.c

+6-2
Original file line numberDiff line numberDiff line change
@@ -1190,8 +1190,12 @@ static ssize_t __iov_iter_get_pages_alloc(struct iov_iter *i,
11901190
if (!n)
11911191
return -ENOMEM;
11921192
p = *pages;
1193-
for (int k = 0; k < n; k++)
1194-
get_page(p[k] = page + k);
1193+
for (int k = 0; k < n; k++) {
1194+
struct folio *folio = page_folio(page);
1195+
p[k] = page + k;
1196+
if (!folio_test_slab(folio))
1197+
folio_get(folio);
1198+
}
11951199
maxsize = min_t(size_t, maxsize, n * PAGE_SIZE - *start);
11961200
i->count -= maxsize;
11971201
i->iov_offset += maxsize;

0 commit comments

Comments
 (0)