Skip to content

Commit eeccf28

Browse files
committed
Merge tag 'mm-stable-2026-02-18-19-48' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
Pull more MM updates from Andrew Morton: - "mm/vmscan: fix demotion targets checks in reclaim/demotion" fixes a couple of issues in the demotion code - pages were failed demotion and were finding themselves demoted into disallowed nodes (Bing Jiao) - "Remove XA_ZERO from error recovery of dup_mmap()" fixes a rare mapledtree race and performs a number of cleanups (Liam Howlett) - "mm: add bitmap VMA flag helpers and convert all mmap_prepare to use them" implements a lot of cleanups following on from the conversion of the VMA flags into a bitmap (Lorenzo Stoakes) - "support batch checking of references and unmapping for large folios" implements batching to greatly improve the performance of reclaiming clean file-backed large folios (Baolin Wang) - "selftests/mm: add memory failure selftests" does as claimed (Miaohe Lin) * tag 'mm-stable-2026-02-18-19-48' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm: (36 commits) mm/page_alloc: clear page->private in free_pages_prepare() selftests/mm: add memory failure dirty pagecache test selftests/mm: add memory failure clean pagecache test selftests/mm: add memory failure anonymous page test mm: rmap: support batched unmapping for file large folios arm64: mm: implement the architecture-specific clear_flush_young_ptes() arm64: mm: support batch clearing of the young flag for large folios arm64: mm: factor out the address and ptep alignment into a new helper mm: rmap: support batched checks of the references for large folios tools/testing/vma: add VMA userland tests for VMA flag functions tools/testing/vma: separate out vma_internal.h into logical headers tools/testing/vma: separate VMA userland tests into separate files mm: make vm_area_desc utilise vma_flags_t only mm: update all remaining mmap_prepare users to use vma_flags_t mm: update shmem_[kernel]_file_*() functions to use vma_flags_t mm: update secretmem to use VMA flags on mmap_prepare mm: update hugetlbfs to use VMA flags on mmap_prepare mm: add basic VMA flag operation helper functions tools: bitmap: add missing bitmap_[subset(), andnot()] mm: add mk_vma_flags() bitmap flag macro helper ...
2 parents 956b9cb + ac1ea21 commit eeccf28

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+3939
-2519
lines changed

MAINTAINERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11845,6 +11845,7 @@ F: include/linux/memory-failure.h
1184511845
F: include/trace/events/memory-failure.h
1184611846
F: mm/hwpoison-inject.c
1184711847
F: mm/memory-failure.c
11848+
F: tools/testing/selftests/mm/memory-failure.c
1184811849

1184911850
HYCON HY46XX TOUCHSCREEN SUPPORT
1185011851
M: Giulio Benetti <giulio.benetti@benettiengineering.com>

arch/arm64/include/asm/pgtable.h

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1648,10 +1648,10 @@ extern void contpte_clear_full_ptes(struct mm_struct *mm, unsigned long addr,
16481648
extern pte_t contpte_get_and_clear_full_ptes(struct mm_struct *mm,
16491649
unsigned long addr, pte_t *ptep,
16501650
unsigned int nr, int full);
1651-
extern int contpte_ptep_test_and_clear_young(struct vm_area_struct *vma,
1652-
unsigned long addr, pte_t *ptep);
1653-
extern int contpte_ptep_clear_flush_young(struct vm_area_struct *vma,
1654-
unsigned long addr, pte_t *ptep);
1651+
int contpte_test_and_clear_young_ptes(struct vm_area_struct *vma,
1652+
unsigned long addr, pte_t *ptep, unsigned int nr);
1653+
int contpte_clear_flush_young_ptes(struct vm_area_struct *vma,
1654+
unsigned long addr, pte_t *ptep, unsigned int nr);
16551655
extern void contpte_wrprotect_ptes(struct mm_struct *mm, unsigned long addr,
16561656
pte_t *ptep, unsigned int nr);
16571657
extern int contpte_ptep_set_access_flags(struct vm_area_struct *vma,
@@ -1823,7 +1823,7 @@ static inline int ptep_test_and_clear_young(struct vm_area_struct *vma,
18231823
if (likely(!pte_valid_cont(orig_pte)))
18241824
return __ptep_test_and_clear_young(vma, addr, ptep);
18251825

1826-
return contpte_ptep_test_and_clear_young(vma, addr, ptep);
1826+
return contpte_test_and_clear_young_ptes(vma, addr, ptep, 1);
18271827
}
18281828

18291829
#define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
@@ -1835,7 +1835,18 @@ static inline int ptep_clear_flush_young(struct vm_area_struct *vma,
18351835
if (likely(!pte_valid_cont(orig_pte)))
18361836
return __ptep_clear_flush_young(vma, addr, ptep);
18371837

1838-
return contpte_ptep_clear_flush_young(vma, addr, ptep);
1838+
return contpte_clear_flush_young_ptes(vma, addr, ptep, 1);
1839+
}
1840+
1841+
#define clear_flush_young_ptes clear_flush_young_ptes
1842+
static inline int clear_flush_young_ptes(struct vm_area_struct *vma,
1843+
unsigned long addr, pte_t *ptep,
1844+
unsigned int nr)
1845+
{
1846+
if (likely(nr == 1 && !pte_cont(__ptep_get(ptep))))
1847+
return __ptep_clear_flush_young(vma, addr, ptep);
1848+
1849+
return contpte_clear_flush_young_ptes(vma, addr, ptep, nr);
18391850
}
18401851

18411852
#define wrprotect_ptes wrprotect_ptes

arch/arm64/mm/contpte.c

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,26 @@ static inline pte_t *contpte_align_down(pte_t *ptep)
2626
return PTR_ALIGN_DOWN(ptep, sizeof(*ptep) * CONT_PTES);
2727
}
2828

29+
static inline pte_t *contpte_align_addr_ptep(unsigned long *start,
30+
unsigned long *end, pte_t *ptep,
31+
unsigned int nr)
32+
{
33+
/*
34+
* Note: caller must ensure these nr PTEs are consecutive (present)
35+
* PTEs that map consecutive pages of the same large folio within a
36+
* single VMA and a single page table.
37+
*/
38+
if (pte_cont(__ptep_get(ptep + nr - 1)))
39+
*end = ALIGN(*end, CONT_PTE_SIZE);
40+
41+
if (pte_cont(__ptep_get(ptep))) {
42+
*start = ALIGN_DOWN(*start, CONT_PTE_SIZE);
43+
ptep = contpte_align_down(ptep);
44+
}
45+
46+
return ptep;
47+
}
48+
2949
static void contpte_try_unfold_partial(struct mm_struct *mm, unsigned long addr,
3050
pte_t *ptep, unsigned int nr)
3151
{
@@ -488,8 +508,9 @@ pte_t contpte_get_and_clear_full_ptes(struct mm_struct *mm,
488508
}
489509
EXPORT_SYMBOL_GPL(contpte_get_and_clear_full_ptes);
490510

491-
int contpte_ptep_test_and_clear_young(struct vm_area_struct *vma,
492-
unsigned long addr, pte_t *ptep)
511+
int contpte_test_and_clear_young_ptes(struct vm_area_struct *vma,
512+
unsigned long addr, pte_t *ptep,
513+
unsigned int nr)
493514
{
494515
/*
495516
* ptep_clear_flush_young() technically requires us to clear the access
@@ -498,41 +519,45 @@ int contpte_ptep_test_and_clear_young(struct vm_area_struct *vma,
498519
* contig range when the range is covered by a single folio, we can get
499520
* away with clearing young for the whole contig range here, so we avoid
500521
* having to unfold.
522+
*
523+
* The 'nr' means consecutive (present) PTEs that map consecutive pages
524+
* of the same large folio in a single VMA and a single page table.
501525
*/
502526

527+
unsigned long end = addr + nr * PAGE_SIZE;
503528
int young = 0;
504-
int i;
505-
506-
ptep = contpte_align_down(ptep);
507-
addr = ALIGN_DOWN(addr, CONT_PTE_SIZE);
508529

509-
for (i = 0; i < CONT_PTES; i++, ptep++, addr += PAGE_SIZE)
530+
ptep = contpte_align_addr_ptep(&addr, &end, ptep, nr);
531+
for (; addr != end; ptep++, addr += PAGE_SIZE)
510532
young |= __ptep_test_and_clear_young(vma, addr, ptep);
511533

512534
return young;
513535
}
514-
EXPORT_SYMBOL_GPL(contpte_ptep_test_and_clear_young);
536+
EXPORT_SYMBOL_GPL(contpte_test_and_clear_young_ptes);
515537

516-
int contpte_ptep_clear_flush_young(struct vm_area_struct *vma,
517-
unsigned long addr, pte_t *ptep)
538+
int contpte_clear_flush_young_ptes(struct vm_area_struct *vma,
539+
unsigned long addr, pte_t *ptep,
540+
unsigned int nr)
518541
{
519542
int young;
520543

521-
young = contpte_ptep_test_and_clear_young(vma, addr, ptep);
544+
young = contpte_test_and_clear_young_ptes(vma, addr, ptep, nr);
522545

523546
if (young) {
547+
unsigned long end = addr + nr * PAGE_SIZE;
548+
549+
contpte_align_addr_ptep(&addr, &end, ptep, nr);
524550
/*
525551
* See comment in __ptep_clear_flush_young(); same rationale for
526552
* eliding the trailing DSB applies here.
527553
*/
528-
addr = ALIGN_DOWN(addr, CONT_PTE_SIZE);
529-
__flush_tlb_range_nosync(vma->vm_mm, addr, addr + CONT_PTE_SIZE,
554+
__flush_tlb_range_nosync(vma->vm_mm, addr, end,
530555
PAGE_SIZE, true, 3);
531556
}
532557

533558
return young;
534559
}
535-
EXPORT_SYMBOL_GPL(contpte_ptep_clear_flush_young);
560+
EXPORT_SYMBOL_GPL(contpte_clear_flush_young_ptes);
536561

537562
void contpte_wrprotect_ptes(struct mm_struct *mm, unsigned long addr,
538563
pte_t *ptep, unsigned int nr)
@@ -569,14 +594,7 @@ void contpte_clear_young_dirty_ptes(struct vm_area_struct *vma,
569594
unsigned long start = addr;
570595
unsigned long end = start + nr * PAGE_SIZE;
571596

572-
if (pte_cont(__ptep_get(ptep + nr - 1)))
573-
end = ALIGN(end, CONT_PTE_SIZE);
574-
575-
if (pte_cont(__ptep_get(ptep))) {
576-
start = ALIGN_DOWN(start, CONT_PTE_SIZE);
577-
ptep = contpte_align_down(ptep);
578-
}
579-
597+
ptep = contpte_align_addr_ptep(&start, &end, ptep, nr);
580598
__clear_young_dirty_ptes(vma, start, ptep, (end - start) / PAGE_SIZE, flags);
581599
}
582600
EXPORT_SYMBOL_GPL(contpte_clear_young_dirty_ptes);

arch/x86/kernel/cpu/sgx/ioctl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ static int sgx_encl_create(struct sgx_encl *encl, struct sgx_secs *secs)
8383
encl_size = secs->size + PAGE_SIZE;
8484

8585
backing = shmem_file_setup("SGX backing", encl_size + (encl_size >> 5),
86-
VM_NORESERVE);
86+
mk_vma_flags(VMA_NORESERVE_BIT));
8787
if (IS_ERR(backing)) {
8888
ret = PTR_ERR(backing);
8989
goto err_out_shrink;

drivers/char/mem.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ static unsigned zero_mmap_capabilities(struct file *file)
306306
/* can't do an in-place private mapping if there's no MMU */
307307
static inline int private_mapping_ok(struct vm_area_desc *desc)
308308
{
309-
return is_nommu_shared_mapping(desc->vm_flags);
309+
return is_nommu_shared_vma_flags(&desc->vma_flags);
310310
}
311311
#else
312312

@@ -360,7 +360,7 @@ static int mmap_mem_prepare(struct vm_area_desc *desc)
360360

361361
desc->vm_ops = &mmap_mem_ops;
362362

363-
/* Remap-pfn-range will mark the range VM_IO. */
363+
/* Remap-pfn-range will mark the range with the I/O flag. */
364364
mmap_action_remap_full(desc, desc->pgoff);
365365
/* We filter remap errors to -EAGAIN. */
366366
desc->action.error_hook = mmap_filter_error;
@@ -520,7 +520,7 @@ static int mmap_zero_prepare(struct vm_area_desc *desc)
520520
#ifndef CONFIG_MMU
521521
return -ENOSYS;
522522
#endif
523-
if (desc->vm_flags & VM_SHARED)
523+
if (vma_desc_test_flags(desc, VMA_SHARED_BIT))
524524
return shmem_zero_setup_desc(desc);
525525

526526
desc->action.success_hook = mmap_zero_private_success;

drivers/dax/device.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
#include "dax-private.h"
1414
#include "bus.h"
1515

16-
static int __check_vma(struct dev_dax *dev_dax, vm_flags_t vm_flags,
16+
static int __check_vma(struct dev_dax *dev_dax, vma_flags_t flags,
1717
unsigned long start, unsigned long end, struct file *file,
1818
const char *func)
1919
{
@@ -24,7 +24,7 @@ static int __check_vma(struct dev_dax *dev_dax, vm_flags_t vm_flags,
2424
return -ENXIO;
2525

2626
/* prevent private mappings from being established */
27-
if ((vm_flags & VM_MAYSHARE) != VM_MAYSHARE) {
27+
if (!vma_flags_test(&flags, VMA_MAYSHARE_BIT)) {
2828
dev_info_ratelimited(dev,
2929
"%s: %s: fail, attempted private mapping\n",
3030
current->comm, func);
@@ -53,7 +53,7 @@ static int __check_vma(struct dev_dax *dev_dax, vm_flags_t vm_flags,
5353
static int check_vma(struct dev_dax *dev_dax, struct vm_area_struct *vma,
5454
const char *func)
5555
{
56-
return __check_vma(dev_dax, vma->vm_flags, vma->vm_start, vma->vm_end,
56+
return __check_vma(dev_dax, vma->flags, vma->vm_start, vma->vm_end,
5757
vma->vm_file, func);
5858
}
5959

@@ -306,14 +306,14 @@ static int dax_mmap_prepare(struct vm_area_desc *desc)
306306
* fault time.
307307
*/
308308
id = dax_read_lock();
309-
rc = __check_vma(dev_dax, desc->vm_flags, desc->start, desc->end, filp,
309+
rc = __check_vma(dev_dax, desc->vma_flags, desc->start, desc->end, filp,
310310
__func__);
311311
dax_read_unlock(id);
312312
if (rc)
313313
return rc;
314314

315315
desc->vm_ops = &dax_vm_ops;
316-
desc->vm_flags |= VM_HUGEPAGE;
316+
vma_desc_set_flags(desc, VMA_HUGEPAGE_BIT);
317317
return 0;
318318
}
319319

drivers/gpu/drm/drm_gem.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,15 +186,16 @@ int drm_gem_object_init(struct drm_device *dev, struct drm_gem_object *obj,
186186
{
187187
struct vfsmount *huge_mnt;
188188
struct file *filp;
189+
const vma_flags_t flags = mk_vma_flags(VMA_NORESERVE_BIT);
189190

190191
drm_gem_private_object_init(dev, obj, size);
191192

192193
huge_mnt = drm_gem_get_huge_mnt(dev);
193194
if (huge_mnt)
194195
filp = shmem_file_setup_with_mnt(huge_mnt, "drm mm object",
195-
size, VM_NORESERVE);
196+
size, flags);
196197
else
197-
filp = shmem_file_setup("drm mm object", size, VM_NORESERVE);
198+
filp = shmem_file_setup("drm mm object", size, flags);
198199

199200
if (IS_ERR(filp))
200201
return PTR_ERR(filp);

drivers/gpu/drm/i915/gem/i915_gem_shmem.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,7 @@ static int __create_shmem(struct drm_i915_private *i915,
499499
resource_size_t size,
500500
unsigned int flags)
501501
{
502-
unsigned long shmem_flags = VM_NORESERVE;
502+
const vma_flags_t shmem_flags = mk_vma_flags(VMA_NORESERVE_BIT);
503503
struct vfsmount *huge_mnt;
504504
struct file *filp;
505505

drivers/gpu/drm/i915/gem/i915_gem_ttm.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,8 @@ static int i915_ttm_tt_shmem_populate(struct ttm_device *bdev,
200200
struct address_space *mapping;
201201
gfp_t mask;
202202

203-
filp = shmem_file_setup("i915-shmem-tt", size, VM_NORESERVE);
203+
filp = shmem_file_setup("i915-shmem-tt", size,
204+
mk_vma_flags(VMA_NORESERVE_BIT));
204205
if (IS_ERR(filp))
205206
return PTR_ERR(filp);
206207

drivers/gpu/drm/i915/gt/shmem_utils.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ struct file *shmem_create_from_data(const char *name, void *data, size_t len)
1919
struct file *file;
2020
int err;
2121

22-
file = shmem_file_setup(name, PAGE_ALIGN(len), VM_NORESERVE);
22+
file = shmem_file_setup(name, PAGE_ALIGN(len),
23+
mk_vma_flags(VMA_NORESERVE_BIT));
2324
if (IS_ERR(file))
2425
return file;
2526

0 commit comments

Comments
 (0)