Skip to content

Commit 349994c

Browse files
apopple-nvidiaakpm00
authored andcommitted
mm/rmap: add support for PUD sized mappings to rmap
The rmap doesn't currently support adding a PUD mapping of a folio. This patch adds support for entire PUD mappings of folios, primarily to allow for more standard refcounting of device DAX folios. Currently DAX is the only user of this and it doesn't require support for partially mapped PUD-sized folios so we don't support for that for now. Link: https://lkml.kernel.org/r/248582c07896e30627d1aeaeebc6949cfd91b851.1740713401.git-series.apopple@nvidia.com Signed-off-by: Alistair Popple <apopple@nvidia.com> Acked-by: David Hildenbrand <david@redhat.com> Reviewed-by: Dan Williams <dan.j.williams@intel.com> Tested-by: Alison Schofield <alison.schofield@intel.com> Cc: Alexander Gordeev <agordeev@linux.ibm.com> Cc: Asahi Lina <lina@asahilina.net> Cc: Balbir Singh <balbirs@nvidia.com> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: Christian Borntraeger <borntraeger@linux.ibm.com> Cc: Christoph Hellwig <hch@lst.de> Cc: Chunyan Zhang <zhang.lyra@gmail.com> Cc: "Darrick J. Wong" <djwong@kernel.org> Cc: Dave Chinner <david@fromorbit.com> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: Dave Jiang <dave.jiang@intel.com> Cc: Gerald Schaefer <gerald.schaefer@linux.ibm.com> Cc: Heiko Carstens <hca@linux.ibm.com> Cc: Huacai Chen <chenhuacai@kernel.org> Cc: Ira Weiny <ira.weiny@intel.com> Cc: Jan Kara <jack@suse.cz> Cc: Jason Gunthorpe <jgg@nvidia.com> Cc: Jason Gunthorpe <jgg@ziepe.ca> Cc: John Hubbard <jhubbard@nvidia.com> Cc: linmiaohe <linmiaohe@huawei.com> Cc: Logan Gunthorpe <logang@deltatee.com> Cc: Matthew Wilcow (Oracle) <willy@infradead.org> Cc: Michael "Camp Drill Sergeant" Ellerman <mpe@ellerman.id.au> Cc: Nicholas Piggin <npiggin@gmail.com> Cc: Peter Xu <peterx@redhat.com> Cc: Sven Schnelle <svens@linux.ibm.com> Cc: Ted Ts'o <tytso@mit.edu> Cc: Vasily Gorbik <gor@linux.ibm.com> Cc: Vishal Verma <vishal.l.verma@intel.com> Cc: Vivek Goyal <vgoyal@redhat.com> Cc: WANG Xuerui <kernel@xen0n.name> Cc: Will Deacon <will@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
1 parent ec2e0cc commit 349994c

File tree

2 files changed

+78
-4
lines changed

2 files changed

+78
-4
lines changed

include/linux/rmap.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ typedef int __bitwise rmap_t;
192192
enum rmap_level {
193193
RMAP_LEVEL_PTE = 0,
194194
RMAP_LEVEL_PMD,
195+
RMAP_LEVEL_PUD,
195196
};
196197

197198
static inline void __folio_rmap_sanity_checks(const struct folio *folio,
@@ -228,6 +229,14 @@ static inline void __folio_rmap_sanity_checks(const struct folio *folio,
228229
VM_WARN_ON_FOLIO(folio_nr_pages(folio) != HPAGE_PMD_NR, folio);
229230
VM_WARN_ON_FOLIO(nr_pages != HPAGE_PMD_NR, folio);
230231
break;
232+
case RMAP_LEVEL_PUD:
233+
/*
234+
* Assume that we are creating a single "entire" mapping of the
235+
* folio.
236+
*/
237+
VM_WARN_ON_FOLIO(folio_nr_pages(folio) != HPAGE_PUD_NR, folio);
238+
VM_WARN_ON_FOLIO(nr_pages != HPAGE_PUD_NR, folio);
239+
break;
231240
default:
232241
VM_WARN_ON_ONCE(true);
233242
}
@@ -251,12 +260,16 @@ void folio_add_file_rmap_ptes(struct folio *, struct page *, int nr_pages,
251260
folio_add_file_rmap_ptes(folio, page, 1, vma)
252261
void folio_add_file_rmap_pmd(struct folio *, struct page *,
253262
struct vm_area_struct *);
263+
void folio_add_file_rmap_pud(struct folio *, struct page *,
264+
struct vm_area_struct *);
254265
void folio_remove_rmap_ptes(struct folio *, struct page *, int nr_pages,
255266
struct vm_area_struct *);
256267
#define folio_remove_rmap_pte(folio, page, vma) \
257268
folio_remove_rmap_ptes(folio, page, 1, vma)
258269
void folio_remove_rmap_pmd(struct folio *, struct page *,
259270
struct vm_area_struct *);
271+
void folio_remove_rmap_pud(struct folio *, struct page *,
272+
struct vm_area_struct *);
260273

261274
void hugetlb_add_anon_rmap(struct folio *, struct vm_area_struct *,
262275
unsigned long address, rmap_t flags);
@@ -341,6 +354,7 @@ static __always_inline void __folio_dup_file_rmap(struct folio *folio,
341354
atomic_add(orig_nr_pages, &folio->_large_mapcount);
342355
break;
343356
case RMAP_LEVEL_PMD:
357+
case RMAP_LEVEL_PUD:
344358
atomic_inc(&folio->_entire_mapcount);
345359
atomic_inc(&folio->_large_mapcount);
346360
break;
@@ -437,6 +451,7 @@ static __always_inline int __folio_try_dup_anon_rmap(struct folio *folio,
437451
atomic_add(orig_nr_pages, &folio->_large_mapcount);
438452
break;
439453
case RMAP_LEVEL_PMD:
454+
case RMAP_LEVEL_PUD:
440455
if (PageAnonExclusive(page)) {
441456
if (unlikely(maybe_pinned))
442457
return -EBUSY;

mm/rmap.c

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1269,12 +1269,19 @@ static __always_inline unsigned int __folio_add_rmap(struct folio *folio,
12691269
atomic_add(orig_nr_pages, &folio->_large_mapcount);
12701270
break;
12711271
case RMAP_LEVEL_PMD:
1272+
case RMAP_LEVEL_PUD:
12721273
first = atomic_inc_and_test(&folio->_entire_mapcount);
12731274
if (first) {
12741275
nr = atomic_add_return_relaxed(ENTIRELY_MAPPED, mapped);
12751276
if (likely(nr < ENTIRELY_MAPPED + ENTIRELY_MAPPED)) {
1276-
*nr_pmdmapped = folio_nr_pages(folio);
1277-
nr = *nr_pmdmapped - (nr & FOLIO_PAGES_MAPPED);
1277+
nr_pages = folio_nr_pages(folio);
1278+
/*
1279+
* We only track PMD mappings of PMD-sized
1280+
* folios separately.
1281+
*/
1282+
if (level == RMAP_LEVEL_PMD)
1283+
*nr_pmdmapped = nr_pages;
1284+
nr = nr_pages - (nr & FOLIO_PAGES_MAPPED);
12781285
/* Raced ahead of a remove and another add? */
12791286
if (unlikely(nr < 0))
12801287
nr = 0;
@@ -1420,6 +1427,13 @@ static __always_inline void __folio_add_anon_rmap(struct folio *folio,
14201427
case RMAP_LEVEL_PMD:
14211428
SetPageAnonExclusive(page);
14221429
break;
1430+
case RMAP_LEVEL_PUD:
1431+
/*
1432+
* Keep the compiler happy, we don't support anonymous
1433+
* PUD mappings.
1434+
*/
1435+
WARN_ON_ONCE(1);
1436+
break;
14231437
}
14241438
}
14251439
for (i = 0; i < nr_pages; i++) {
@@ -1613,6 +1627,27 @@ void folio_add_file_rmap_pmd(struct folio *folio, struct page *page,
16131627
#endif
16141628
}
16151629

1630+
/**
1631+
* folio_add_file_rmap_pud - add a PUD mapping to a page range of a folio
1632+
* @folio: The folio to add the mapping to
1633+
* @page: The first page to add
1634+
* @vma: The vm area in which the mapping is added
1635+
*
1636+
* The page range of the folio is defined by [page, page + HPAGE_PUD_NR)
1637+
*
1638+
* The caller needs to hold the page table lock.
1639+
*/
1640+
void folio_add_file_rmap_pud(struct folio *folio, struct page *page,
1641+
struct vm_area_struct *vma)
1642+
{
1643+
#if defined(CONFIG_TRANSPARENT_HUGEPAGE) && \
1644+
defined(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD)
1645+
__folio_add_file_rmap(folio, page, HPAGE_PUD_NR, vma, RMAP_LEVEL_PUD);
1646+
#else
1647+
WARN_ON_ONCE(true);
1648+
#endif
1649+
}
1650+
16161651
static __always_inline void __folio_remove_rmap(struct folio *folio,
16171652
struct page *page, int nr_pages, struct vm_area_struct *vma,
16181653
enum rmap_level level)
@@ -1642,13 +1677,16 @@ static __always_inline void __folio_remove_rmap(struct folio *folio,
16421677
partially_mapped = nr && atomic_read(mapped);
16431678
break;
16441679
case RMAP_LEVEL_PMD:
1680+
case RMAP_LEVEL_PUD:
16451681
atomic_dec(&folio->_large_mapcount);
16461682
last = atomic_add_negative(-1, &folio->_entire_mapcount);
16471683
if (last) {
16481684
nr = atomic_sub_return_relaxed(ENTIRELY_MAPPED, mapped);
16491685
if (likely(nr < ENTIRELY_MAPPED)) {
1650-
nr_pmdmapped = folio_nr_pages(folio);
1651-
nr = nr_pmdmapped - (nr & FOLIO_PAGES_MAPPED);
1686+
nr_pages = folio_nr_pages(folio);
1687+
if (level == RMAP_LEVEL_PMD)
1688+
nr_pmdmapped = nr_pages;
1689+
nr = nr_pages - (nr & FOLIO_PAGES_MAPPED);
16521690
/* Raced ahead of another remove and an add? */
16531691
if (unlikely(nr < 0))
16541692
nr = 0;
@@ -1722,6 +1760,27 @@ void folio_remove_rmap_pmd(struct folio *folio, struct page *page,
17221760
#endif
17231761
}
17241762

1763+
/**
1764+
* folio_remove_rmap_pud - remove a PUD mapping from a page range of a folio
1765+
* @folio: The folio to remove the mapping from
1766+
* @page: The first page to remove
1767+
* @vma: The vm area from which the mapping is removed
1768+
*
1769+
* The page range of the folio is defined by [page, page + HPAGE_PUD_NR)
1770+
*
1771+
* The caller needs to hold the page table lock.
1772+
*/
1773+
void folio_remove_rmap_pud(struct folio *folio, struct page *page,
1774+
struct vm_area_struct *vma)
1775+
{
1776+
#if defined(CONFIG_TRANSPARENT_HUGEPAGE) && \
1777+
defined(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD)
1778+
__folio_remove_rmap(folio, page, HPAGE_PUD_NR, vma, RMAP_LEVEL_PUD);
1779+
#else
1780+
WARN_ON_ONCE(true);
1781+
#endif
1782+
}
1783+
17251784
/* We support batch unmapping of PTEs for lazyfree large folios */
17261785
static inline bool can_batch_unmap_folio_ptes(unsigned long addr,
17271786
struct folio *folio, pte_t *ptep)

0 commit comments

Comments
 (0)