mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git
synced 2026-05-07 03:51:34 -04:00
Merge tag 'mm-hotfixes-stable-2025-08-21-18-17' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
Pull misc fixes from Andrew Morton: "20 hotfixes. 10 are cc:stable and the remainder address post-6.16 issues or aren't considered necessary for -stable kernels. 17 of these fixes are for MM. As usual, singletons all over the place, apart from a three-patch series of KHO followup work from Pasha which is actually also a bunch of singletons" * tag 'mm-hotfixes-stable-2025-08-21-18-17' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm: mm/mremap: fix WARN with uffd that has remap events disabled mm/damon/sysfs-schemes: put damos dests dir after removing its files mm/migrate: fix NULL movable_ops if CONFIG_ZSMALLOC=m mm/damon/core: fix damos_commit_filter not changing allow mm/memory-failure: fix infinite UCE for VM_PFNMAP pfn MAINTAINERS: mark MGLRU as maintained mm: rust: add page.rs to MEMORY MANAGEMENT - RUST iov_iter: iterate_folioq: fix handling of offset >= folio size selftests/damon: fix selftests by installing drgn related script .mailmap: add entry for Easwar Hariharan selftests/mm: add test for invalid multi VMA operations mm/mremap: catch invalid multi VMA moves earlier mm/mremap: allow multi-VMA move when filesystem uses thp_get_unmapped_area mm/damon/core: fix commit_ops_filters by using correct nth function tools/testing: add linux/args.h header and fix radix, VMA tests mm/debug_vm_pgtable: clear page table entries at destroy_args() squashfs: fix memory leak in squashfs_fill_super kho: warn if KHO is disabled due to an error kho: mm: don't allow deferred struct page with KHO kho: init new_physxa->phys_bits to fix lockdep
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
TEST_GEN_FILES += access_memory access_memory_even
|
||||
|
||||
TEST_FILES = _damon_sysfs.py
|
||||
TEST_FILES += drgn_dump_damon_status.py
|
||||
|
||||
# functionality tests
|
||||
TEST_PROGS += sysfs.sh
|
||||
|
||||
@@ -5,10 +5,14 @@
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/userfaultfd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <syscall.h>
|
||||
#include <time.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
@@ -168,6 +172,7 @@ static bool is_range_mapped(FILE *maps_fp, unsigned long start,
|
||||
|
||||
if (first_val <= start && second_val >= end) {
|
||||
success = true;
|
||||
fflush(maps_fp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -175,6 +180,15 @@ static bool is_range_mapped(FILE *maps_fp, unsigned long start,
|
||||
return success;
|
||||
}
|
||||
|
||||
/* Check if [ptr, ptr + size) mapped in /proc/self/maps. */
|
||||
static bool is_ptr_mapped(FILE *maps_fp, void *ptr, unsigned long size)
|
||||
{
|
||||
unsigned long start = (unsigned long)ptr;
|
||||
unsigned long end = start + size;
|
||||
|
||||
return is_range_mapped(maps_fp, start, end);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the start address of the mapping on success, else returns
|
||||
* NULL on failure.
|
||||
@@ -733,6 +747,249 @@ out:
|
||||
dont_unmap ? " [dontunnmap]" : "");
|
||||
}
|
||||
|
||||
#ifdef __NR_userfaultfd
|
||||
static void mremap_move_multi_invalid_vmas(FILE *maps_fp,
|
||||
unsigned long page_size)
|
||||
{
|
||||
char *test_name = "mremap move multiple invalid vmas";
|
||||
const size_t size = 10 * page_size;
|
||||
bool success = true;
|
||||
char *ptr, *tgt_ptr;
|
||||
int uffd, err, i;
|
||||
void *res;
|
||||
struct uffdio_api api = {
|
||||
.api = UFFD_API,
|
||||
.features = UFFD_EVENT_PAGEFAULT,
|
||||
};
|
||||
|
||||
uffd = syscall(__NR_userfaultfd, O_NONBLOCK);
|
||||
if (uffd == -1) {
|
||||
err = errno;
|
||||
perror("userfaultfd");
|
||||
if (err == EPERM) {
|
||||
ksft_test_result_skip("%s - missing uffd", test_name);
|
||||
return;
|
||||
}
|
||||
success = false;
|
||||
goto out;
|
||||
}
|
||||
if (ioctl(uffd, UFFDIO_API, &api)) {
|
||||
perror("ioctl UFFDIO_API");
|
||||
success = false;
|
||||
goto out_close_uffd;
|
||||
}
|
||||
|
||||
ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
if (ptr == MAP_FAILED) {
|
||||
perror("mmap");
|
||||
success = false;
|
||||
goto out_close_uffd;
|
||||
}
|
||||
|
||||
tgt_ptr = mmap(NULL, size, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
if (tgt_ptr == MAP_FAILED) {
|
||||
perror("mmap");
|
||||
success = false;
|
||||
goto out_close_uffd;
|
||||
}
|
||||
if (munmap(tgt_ptr, size)) {
|
||||
perror("munmap");
|
||||
success = false;
|
||||
goto out_unmap;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unmap so we end up with:
|
||||
*
|
||||
* 0 2 4 6 8 10 offset in buffer
|
||||
* |*| |*| |*| |*| |*|
|
||||
* |*| |*| |*| |*| |*|
|
||||
*
|
||||
* Additionally, register each with UFFD.
|
||||
*/
|
||||
for (i = 0; i < 10; i += 2) {
|
||||
void *unmap_ptr = &ptr[(i + 1) * page_size];
|
||||
unsigned long start = (unsigned long)&ptr[i * page_size];
|
||||
struct uffdio_register reg = {
|
||||
.range = {
|
||||
.start = start,
|
||||
.len = page_size,
|
||||
},
|
||||
.mode = UFFDIO_REGISTER_MODE_MISSING,
|
||||
};
|
||||
|
||||
if (ioctl(uffd, UFFDIO_REGISTER, ®) == -1) {
|
||||
perror("ioctl UFFDIO_REGISTER");
|
||||
success = false;
|
||||
goto out_unmap;
|
||||
}
|
||||
if (munmap(unmap_ptr, page_size)) {
|
||||
perror("munmap");
|
||||
success = false;
|
||||
goto out_unmap;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Now try to move the entire range which is invalid for multi VMA move.
|
||||
*
|
||||
* This will fail, and no VMA should be moved, as we check this ahead of
|
||||
* time.
|
||||
*/
|
||||
res = mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_FIXED, tgt_ptr);
|
||||
err = errno;
|
||||
if (res != MAP_FAILED) {
|
||||
fprintf(stderr, "mremap() succeeded for multi VMA uffd armed\n");
|
||||
success = false;
|
||||
goto out_unmap;
|
||||
}
|
||||
if (err != EFAULT) {
|
||||
errno = err;
|
||||
perror("mrmeap() unexpected error");
|
||||
success = false;
|
||||
goto out_unmap;
|
||||
}
|
||||
if (is_ptr_mapped(maps_fp, tgt_ptr, page_size)) {
|
||||
fprintf(stderr,
|
||||
"Invalid uffd-armed VMA at start of multi range moved\n");
|
||||
success = false;
|
||||
goto out_unmap;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now try to move a single VMA, this should succeed as not multi VMA
|
||||
* move.
|
||||
*/
|
||||
res = mremap(ptr, page_size, page_size,
|
||||
MREMAP_MAYMOVE | MREMAP_FIXED, tgt_ptr);
|
||||
if (res == MAP_FAILED) {
|
||||
perror("mremap single invalid-multi VMA");
|
||||
success = false;
|
||||
goto out_unmap;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unmap the VMA, and remap a non-uffd registered (therefore, multi VMA
|
||||
* move valid) VMA at the start of ptr range.
|
||||
*/
|
||||
if (munmap(tgt_ptr, page_size)) {
|
||||
perror("munmap");
|
||||
success = false;
|
||||
goto out_unmap;
|
||||
}
|
||||
res = mmap(ptr, page_size, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
|
||||
if (res == MAP_FAILED) {
|
||||
perror("mmap");
|
||||
success = false;
|
||||
goto out_unmap;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now try to move the entire range, we should succeed in moving the
|
||||
* first VMA, but no others, and report a failure.
|
||||
*/
|
||||
res = mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_FIXED, tgt_ptr);
|
||||
err = errno;
|
||||
if (res != MAP_FAILED) {
|
||||
fprintf(stderr, "mremap() succeeded for multi VMA uffd armed\n");
|
||||
success = false;
|
||||
goto out_unmap;
|
||||
}
|
||||
if (err != EFAULT) {
|
||||
errno = err;
|
||||
perror("mrmeap() unexpected error");
|
||||
success = false;
|
||||
goto out_unmap;
|
||||
}
|
||||
if (!is_ptr_mapped(maps_fp, tgt_ptr, page_size)) {
|
||||
fprintf(stderr, "Valid VMA not moved\n");
|
||||
success = false;
|
||||
goto out_unmap;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unmap the VMA, and map valid VMA at start of ptr range, and replace
|
||||
* all existing multi-move invalid VMAs, except the last, with valid
|
||||
* multi-move VMAs.
|
||||
*/
|
||||
if (munmap(tgt_ptr, page_size)) {
|
||||
perror("munmap");
|
||||
success = false;
|
||||
goto out_unmap;
|
||||
}
|
||||
if (munmap(ptr, size - 2 * page_size)) {
|
||||
perror("munmap");
|
||||
success = false;
|
||||
goto out_unmap;
|
||||
}
|
||||
for (i = 0; i < 8; i += 2) {
|
||||
res = mmap(&ptr[i * page_size], page_size,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
|
||||
if (res == MAP_FAILED) {
|
||||
perror("mmap");
|
||||
success = false;
|
||||
goto out_unmap;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Now try to move the entire range, we should succeed in moving all but
|
||||
* the last VMA, and report a failure.
|
||||
*/
|
||||
res = mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_FIXED, tgt_ptr);
|
||||
err = errno;
|
||||
if (res != MAP_FAILED) {
|
||||
fprintf(stderr, "mremap() succeeded for multi VMA uffd armed\n");
|
||||
success = false;
|
||||
goto out_unmap;
|
||||
}
|
||||
if (err != EFAULT) {
|
||||
errno = err;
|
||||
perror("mrmeap() unexpected error");
|
||||
success = false;
|
||||
goto out_unmap;
|
||||
}
|
||||
|
||||
for (i = 0; i < 10; i += 2) {
|
||||
bool is_mapped = is_ptr_mapped(maps_fp,
|
||||
&tgt_ptr[i * page_size], page_size);
|
||||
|
||||
if (i < 8 && !is_mapped) {
|
||||
fprintf(stderr, "Valid VMA not moved at %d\n", i);
|
||||
success = false;
|
||||
goto out_unmap;
|
||||
} else if (i == 8 && is_mapped) {
|
||||
fprintf(stderr, "Invalid VMA moved at %d\n", i);
|
||||
success = false;
|
||||
goto out_unmap;
|
||||
}
|
||||
}
|
||||
|
||||
out_unmap:
|
||||
if (munmap(tgt_ptr, size))
|
||||
perror("munmap tgt");
|
||||
if (munmap(ptr, size))
|
||||
perror("munmap src");
|
||||
out_close_uffd:
|
||||
close(uffd);
|
||||
out:
|
||||
if (success)
|
||||
ksft_test_result_pass("%s\n", test_name);
|
||||
else
|
||||
ksft_test_result_fail("%s\n", test_name);
|
||||
}
|
||||
#else
|
||||
static void mremap_move_multi_invalid_vmas(FILE *maps_fp, unsigned long page_size)
|
||||
{
|
||||
char *test_name = "mremap move multiple invalid vmas";
|
||||
|
||||
ksft_test_result_skip("%s - missing uffd", test_name);
|
||||
}
|
||||
#endif /* __NR_userfaultfd */
|
||||
|
||||
/* Returns the time taken for the remap on success else returns -1. */
|
||||
static long long remap_region(struct config c, unsigned int threshold_mb,
|
||||
char *rand_addr)
|
||||
@@ -1074,7 +1331,7 @@ int main(int argc, char **argv)
|
||||
char *rand_addr;
|
||||
size_t rand_size;
|
||||
int num_expand_tests = 2;
|
||||
int num_misc_tests = 8;
|
||||
int num_misc_tests = 9;
|
||||
struct test test_cases[MAX_TEST] = {};
|
||||
struct test perf_test_cases[MAX_PERF_TEST];
|
||||
int page_size;
|
||||
@@ -1197,8 +1454,6 @@ int main(int argc, char **argv)
|
||||
mremap_expand_merge(maps_fp, page_size);
|
||||
mremap_expand_merge_offset(maps_fp, page_size);
|
||||
|
||||
fclose(maps_fp);
|
||||
|
||||
mremap_move_within_range(pattern_seed, rand_addr);
|
||||
mremap_move_1mb_from_start(pattern_seed, rand_addr);
|
||||
mremap_shrink_multiple_vmas(page_size, /* inplace= */true);
|
||||
@@ -1207,6 +1462,9 @@ int main(int argc, char **argv)
|
||||
mremap_move_multiple_vmas(pattern_seed, page_size, /* dontunmap= */ true);
|
||||
mremap_move_multiple_vmas_split(pattern_seed, page_size, /* dontunmap= */ false);
|
||||
mremap_move_multiple_vmas_split(pattern_seed, page_size, /* dontunmap= */ true);
|
||||
mremap_move_multi_invalid_vmas(maps_fp, page_size);
|
||||
|
||||
fclose(maps_fp);
|
||||
|
||||
if (run_perf_tests) {
|
||||
ksft_print_msg("\n%s\n",
|
||||
|
||||
@@ -1 +1,5 @@
|
||||
/* Avoid duplicate definitions due to system headers. */
|
||||
#ifdef __CONCAT
|
||||
#undef __CONCAT
|
||||
#endif
|
||||
#include "../../../../include/linux/idr.h"
|
||||
|
||||
Reference in New Issue
Block a user