| Author | Tokens | Token Proportion | Commits | Commit Proportion |
|---|---|---|---|---|
| Mike Kravetz | 1158 | 93.09% | 2 | 14.29% |
| Mike Rapoport | 65 | 5.23% | 4 | 28.57% |
| Peter Xu | 6 | 0.48% | 1 | 7.14% |
| Kevin Brodsky | 5 | 0.40% | 1 | 7.14% |
| Muhammad Usama Anjum | 3 | 0.24% | 1 | 7.14% |
| Nico Pache | 2 | 0.16% | 1 | 7.14% |
| Ryan Roberts | 2 | 0.16% | 1 | 7.14% |
| Bala-Vignesh-Reddy | 1 | 0.08% | 1 | 7.14% |
| John Hubbard | 1 | 0.08% | 1 | 7.14% |
| wang lian | 1 | 0.08% | 1 | 7.14% |
| Total | 1244 | 14 |
// SPDX-License-Identifier: GPL-2.0 /* * hugetlb-madvise: * * Basic functional testing of madvise MADV_DONTNEED and MADV_REMOVE * on hugetlb mappings. */ #define _GNU_SOURCE #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <sys/mman.h> #include <fcntl.h> #include "vm_util.h" #include "kselftest.h" #include "hugepage_settings.h" #define MIN_FREE_PAGES 20 #define NR_HUGE_PAGES 10 /* common number of pages to map/allocate */ #define validate_free_pages(exp_free) \ do { \ unsigned long fhp = hugetlb_free_default_pages(); \ if (fhp != (exp_free)) \ ksft_exit_fail_msg("Unexpected number of free " \ "huge pages %lu, expected %lu line %d\n", \ fhp, (exp_free), __LINE__); \ } while (0) unsigned long huge_page_size; unsigned long base_page_size; void write_fault_pages(void *addr, unsigned long nr_pages) { unsigned long i; for (i = 0; i < nr_pages; i++) *((unsigned long *)(addr + (i * huge_page_size))) = i; } void read_fault_pages(void *addr, unsigned long nr_pages) { force_read_pages(addr, nr_pages, huge_page_size); } int main(int argc, char **argv) { unsigned long free_hugepages; void *addr, *addr2; int fd; int ret; ksft_print_header(); ksft_set_plan(1); huge_page_size = default_huge_page_size(); if (!huge_page_size) ksft_exit_skip("Unable to determine huge page size\n"); base_page_size = sysconf(_SC_PAGE_SIZE); if (!base_page_size) ksft_exit_fail_msg("Unable to determine base page size\n"); if (!hugetlb_setup_default(MIN_FREE_PAGES)) ksft_exit_skip("Not enough free huge pages (have %lu, need %d)\n", hugetlb_free_default_pages(), MIN_FREE_PAGES); free_hugepages = hugetlb_free_default_pages(); fd = memfd_create(argv[0], MFD_HUGETLB); if (fd < 0) ksft_exit_fail_perror("memfd_create"); /* * Test validity of MADV_DONTNEED addr and length arguments. mmap * size is NR_HUGE_PAGES + 2. One page at the beginning and end of * the mapping will be unmapped so we KNOW there is nothing mapped * there. */ addr = mmap(NULL, (NR_HUGE_PAGES + 2) * huge_page_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, -1, 0); if (addr == MAP_FAILED) ksft_exit_fail_perror("mmap"); if (munmap(addr, huge_page_size) || munmap(addr + (NR_HUGE_PAGES + 1) * huge_page_size, huge_page_size)) ksft_exit_fail_perror("munmap"); addr = addr + huge_page_size; write_fault_pages(addr, NR_HUGE_PAGES); validate_free_pages(free_hugepages - NR_HUGE_PAGES); /* addr before mapping should fail */ ret = madvise(addr - base_page_size, NR_HUGE_PAGES * huge_page_size, MADV_DONTNEED); if (!ret) ksft_exit_fail_msg("madvise with invalid addr unexpectedly succeeded line %d\n", __LINE__); /* addr + length after mapping should fail */ ret = madvise(addr, (NR_HUGE_PAGES * huge_page_size) + base_page_size, MADV_DONTNEED); if (!ret) ksft_exit_fail_msg("madvise with invalid length unexpectedly succeeded line %d\n", __LINE__); (void)munmap(addr, NR_HUGE_PAGES * huge_page_size); /* * Test alignment of MADV_DONTNEED addr and length arguments */ addr = mmap(NULL, NR_HUGE_PAGES * huge_page_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, -1, 0); if (addr == MAP_FAILED) ksft_exit_fail_perror("mmap"); write_fault_pages(addr, NR_HUGE_PAGES); validate_free_pages(free_hugepages - NR_HUGE_PAGES); /* addr is not huge page size aligned and should fail */ ret = madvise(addr + base_page_size, NR_HUGE_PAGES * huge_page_size - base_page_size, MADV_DONTNEED); if (!ret) ksft_exit_fail_msg("madvise with unaligned start unexpectedly succeeded line %d\n", __LINE__); /* addr + length should be aligned down to huge page size */ if (madvise(addr, ((NR_HUGE_PAGES - 1) * huge_page_size) + base_page_size, MADV_DONTNEED)) ksft_exit_fail_perror("madvise"); /* should free all but last page in mapping */ validate_free_pages(free_hugepages - 1); (void)munmap(addr, NR_HUGE_PAGES * huge_page_size); validate_free_pages(free_hugepages); /* * Test MADV_DONTNEED on anonymous private mapping */ addr = mmap(NULL, NR_HUGE_PAGES * huge_page_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, -1, 0); if (addr == MAP_FAILED) ksft_exit_fail_perror("mmap"); write_fault_pages(addr, NR_HUGE_PAGES); validate_free_pages(free_hugepages - NR_HUGE_PAGES); if (madvise(addr, NR_HUGE_PAGES * huge_page_size, MADV_DONTNEED)) ksft_exit_fail_perror("madvise"); /* should free all pages in mapping */ validate_free_pages(free_hugepages); (void)munmap(addr, NR_HUGE_PAGES * huge_page_size); /* * Test MADV_DONTNEED on private mapping of hugetlb file */ if (fallocate(fd, 0, 0, NR_HUGE_PAGES * huge_page_size)) ksft_exit_fail_perror("fallocate"); validate_free_pages(free_hugepages - NR_HUGE_PAGES); addr = mmap(NULL, NR_HUGE_PAGES * huge_page_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); if (addr == MAP_FAILED) ksft_exit_fail_perror("mmap"); /* read should not consume any pages */ read_fault_pages(addr, NR_HUGE_PAGES); validate_free_pages(free_hugepages - NR_HUGE_PAGES); /* madvise should not free any pages */ if (madvise(addr, NR_HUGE_PAGES * huge_page_size, MADV_DONTNEED)) ksft_exit_fail_perror("madvise"); validate_free_pages(free_hugepages - NR_HUGE_PAGES); /* writes should allocate private pages */ write_fault_pages(addr, NR_HUGE_PAGES); validate_free_pages(free_hugepages - (2 * NR_HUGE_PAGES)); /* madvise should free private pages */ if (madvise(addr, NR_HUGE_PAGES * huge_page_size, MADV_DONTNEED)) ksft_exit_fail_perror("madvise"); validate_free_pages(free_hugepages - NR_HUGE_PAGES); /* writes should allocate private pages */ write_fault_pages(addr, NR_HUGE_PAGES); validate_free_pages(free_hugepages - (2 * NR_HUGE_PAGES)); /* * The fallocate below certainly should free the pages associated * with the file. However, pages in the private mapping are also * freed. This is not the 'correct' behavior, but is expected * because this is how it has worked since the initial hugetlb * implementation. */ if (fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 0, NR_HUGE_PAGES * huge_page_size)) ksft_exit_fail_perror("fallocate"); validate_free_pages(free_hugepages); (void)munmap(addr, NR_HUGE_PAGES * huge_page_size); /* * Test MADV_DONTNEED on shared mapping of hugetlb file */ if (fallocate(fd, 0, 0, NR_HUGE_PAGES * huge_page_size)) ksft_exit_fail_perror("fallocate"); validate_free_pages(free_hugepages - NR_HUGE_PAGES); addr = mmap(NULL, NR_HUGE_PAGES * huge_page_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (addr == MAP_FAILED) ksft_exit_fail_perror("mmap"); /* write should not consume any pages */ write_fault_pages(addr, NR_HUGE_PAGES); validate_free_pages(free_hugepages - NR_HUGE_PAGES); /* madvise should not free any pages */ if (madvise(addr, NR_HUGE_PAGES * huge_page_size, MADV_DONTNEED)) ksft_exit_fail_perror("madvise"); validate_free_pages(free_hugepages - NR_HUGE_PAGES); /* * Test MADV_REMOVE on shared mapping of hugetlb file * * madvise is same as hole punch and should free all pages. */ if (madvise(addr, NR_HUGE_PAGES * huge_page_size, MADV_REMOVE)) ksft_exit_fail_perror("madvise"); validate_free_pages(free_hugepages); (void)munmap(addr, NR_HUGE_PAGES * huge_page_size); /* * Test MADV_REMOVE on shared and private mapping of hugetlb file */ if (fallocate(fd, 0, 0, NR_HUGE_PAGES * huge_page_size)) ksft_exit_fail_perror("fallocate"); validate_free_pages(free_hugepages - NR_HUGE_PAGES); addr = mmap(NULL, NR_HUGE_PAGES * huge_page_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (addr == MAP_FAILED) ksft_exit_fail_perror("mmap"); /* shared write should not consume any additional pages */ write_fault_pages(addr, NR_HUGE_PAGES); validate_free_pages(free_hugepages - NR_HUGE_PAGES); addr2 = mmap(NULL, NR_HUGE_PAGES * huge_page_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); if (addr2 == MAP_FAILED) ksft_exit_fail_perror("mmap"); /* private read should not consume any pages */ read_fault_pages(addr2, NR_HUGE_PAGES); validate_free_pages(free_hugepages - NR_HUGE_PAGES); /* private write should consume additional pages */ write_fault_pages(addr2, NR_HUGE_PAGES); validate_free_pages(free_hugepages - (2 * NR_HUGE_PAGES)); /* madvise of shared mapping should not free any pages */ if (madvise(addr, NR_HUGE_PAGES * huge_page_size, MADV_DONTNEED)) ksft_exit_fail_perror("madvise"); validate_free_pages(free_hugepages - (2 * NR_HUGE_PAGES)); /* madvise of private mapping should free private pages */ if (madvise(addr2, NR_HUGE_PAGES * huge_page_size, MADV_DONTNEED)) ksft_exit_fail_perror("madvise"); validate_free_pages(free_hugepages - NR_HUGE_PAGES); /* private write should consume additional pages again */ write_fault_pages(addr2, NR_HUGE_PAGES); validate_free_pages(free_hugepages - (2 * NR_HUGE_PAGES)); /* * madvise should free both file and private pages although this is * not correct. private pages should not be freed, but this is * expected. See comment associated with FALLOC_FL_PUNCH_HOLE call. */ if (madvise(addr, NR_HUGE_PAGES * huge_page_size, MADV_REMOVE)) ksft_exit_fail_perror("madvise"); validate_free_pages(free_hugepages); (void)munmap(addr, NR_HUGE_PAGES * huge_page_size); (void)munmap(addr2, NR_HUGE_PAGES * huge_page_size); close(fd); ksft_test_result_pass("MADV_DONTNEED and MADV_REMOVE on hugetlb\n"); ksft_finished(); }
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with Cregit http://github.com/cregit/cregit
Version 2.0-RC1