// SPDX-License-Identifier: GPL-2.0 /* * This program tests for hugepage leaks after DIO writes to a file using a * hugepage as the user buffer. During DIO, the user buffer is pinned and * should be properly unpinned upon completion. This patch verifies that the * kernel correctly unpins the buffer at DIO completion for both aligned and * unaligned user buffer offsets (w.r.t page boundary), ensuring the hugepage * is freed upon unmapping.
*/
/* Get the default huge page size */
h_pagesize = default_huge_page_size(); if (!h_pagesize)
ksft_exit_fail_msg("Unable to determine huge page size\n");
/* Open the file to DIO */
fd = open("/tmp", O_TMPFILE | O_RDWR | O_DIRECT, 0664); if (fd < 0)
ksft_exit_fail_perror("Error opening file\n");
/* Get the free huge pages before allocation */
free_hpage_b = get_free_hugepages(); if (free_hpage_b == 0) {
close(fd);
ksft_exit_skip("No free hugepage, exiting!\n");
}
/* Write the buffer to the file */ if (write(fd, buffer, writesize) != (writesize)) {
munmap(orig_buffer, h_pagesize);
close(fd);
ksft_exit_fail_perror("Error writing to file\n");
}
/* unmap the huge page */
munmap(orig_buffer, h_pagesize);
close(fd);
/* Get the free huge pages after unmap*/
free_hpage_a = get_free_hugepages();
ksft_print_msg("No. Free pages before allocation : %d\n", free_hpage_b);
ksft_print_msg("No. Free pages after munmap : %d\n", free_hpage_a);
/* * If the no. of free hugepages before allocation and after unmap does * not match - that means there could still be a page which is pinned.
*/
ksft_test_result(free_hpage_a == free_hpage_b, "free huge pages from %u-%u\n", start_off, end_off);
}
int main(void)
{
size_t pagesize = 0; int fd;
ksft_print_header();
/* Open the file to DIO */
fd = open("/tmp", O_TMPFILE | O_RDWR | O_DIRECT, 0664); if (fd < 0)
ksft_exit_skip("Unable to allocate file: %s\n", strerror(errno));
close(fd);
/* Check if huge pages are free */ if (!get_free_hugepages())
ksft_exit_skip("No free hugepage, exiting\n");
ksft_set_plan(4);
/* Get base page size */
pagesize = psize();
/* start and end is aligned to pagesize */
run_dio_using_hugetlb(0, (pagesize * 3));
/* start is aligned but end is not aligned */
run_dio_using_hugetlb(0, (pagesize * 3) - (pagesize / 2));
/* start is unaligned and end is aligned */
run_dio_using_hugetlb(pagesize / 2, (pagesize * 3));
/* both start and end are unaligned */
run_dio_using_hugetlb(pagesize / 2, (pagesize * 3) + (pagesize / 2));
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.