1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
/*
* libhugetlbfs - Easy use of Linux hugepages
* Copyright (C) 20015 Mike Kravetz, Oracle Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#define _GNU_SOURCE
#include <linux/falloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <linux/falloc.h>
#include <hugetlbfs.h>
#include "hugetests.h"
#define P "fallocate-align"
#define DESC \
"* Test alignment of fallocate arguments. fallocate will take *\n"\
"* non-huge page aligned offsets and addresses. However, *\n"\
"* operations are only performed on huge pages. This is different *\n"\
"* that than fallocate behavior in "normal" filesystems. *"
int main(int argc, char *argv[])
{
long hpage_size;
int fd;
int err;
unsigned long free_before, free_after;
test_init(argc, argv);
hpage_size = check_hugepagesize();
fd = hugetlbfs_unlinked_fd();
if (fd < 0)
FAIL("hugetlbfs_unlinked_fd()");
free_before = get_huge_page_counter(hpage_size, HUGEPAGES_FREE);
/*
* First preallocate file with with just 1 byte. Allocation sizes
* are rounded up, so we should get an entire huge page.
*/
err = fallocate(fd, 0, 0, 1);
if (err) {
if (errno == EOPNOTSUPP)
IRRELEVANT();
if (err)
FAIL("fallocate(): %s", strerror(errno));
}
free_after = get_huge_page_counter(hpage_size, HUGEPAGES_FREE);
if (free_before - free_after != 1)
FAIL("fallocate 1 byte did not preallocate entire huge page\n");
/*
* Now punch a hole with just 1 byte. On hole punch, sizes are
* rounded down. So, this operation should not create a hole.
*/
err = fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
0, 1);
if (err)
FAIL("fallocate(FALLOC_FL_PUNCH_HOLE): %s", strerror(errno));
free_after = get_huge_page_counter(hpage_size, HUGEPAGES_FREE);
if (free_after == free_before)
FAIL("fallocate hole punch 1 byte free'ed a huge page\n");
/*
* Now punch a hole with of 2 * hpage_size - 1 byte. This size
* should be rounded down to a single huge page and the hole created.
*/
err = fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
0, (2 * hpage_size) - 1);
if (err)
FAIL("fallocate(FALLOC_FL_PUNCH_HOLE): %s", strerror(errno));
free_after = get_huge_page_counter(hpage_size, HUGEPAGES_FREE);
if (free_after != free_before)
FAIL("fallocate hole punch 2 * hpage_size - 1 byte did not free huge page\n");
/*
* Perform a preallocate operation with offset 1 and size of
* hpage_size. The offset should be rounded down and the
* size rounded up to preallocate two huge pages.
*/
err = fallocate(fd, 0, 1, hpage_size);
if (err)
FAIL("fallocate(): %s", strerror(errno));
free_after = get_huge_page_counter(hpage_size, HUGEPAGES_FREE);
if (free_before - free_after != 2)
FAIL("fallocate 1 byte offset, huge page size did not preallocate two huge pages\n");
/*
* The hole punch code will only delete 'whole' huge pags that are
* in the specified range. The offset is rounded up, and (offset
* + size) is rounded down to determine the huge pages to be deleted.
* In this case, after rounding the range is (hpage_size, hpage_size).
* So, no pages should be deleted.
*/
err = fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
1, hpage_size);
if (err)
FAIL("fallocate(FALLOC_FL_PUNCH_HOLE): %s", strerror(errno));
free_after = get_huge_page_counter(hpage_size, HUGEPAGES_FREE);
if (free_before - free_after != 2)
FAIL("fallocate hole punch 1 byte offset, huge page size incorrectly deleted a huge page\n");
/*
* To delete both huge pages, the range passed to hole punch must
* overlap the allocated pages
*/
err = fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
0, 2 * hpage_size);
if (err)
FAIL("fallocate(FALLOC_FL_PUNCH_HOLE): %s", strerror(errno));
free_after = get_huge_page_counter(hpage_size, HUGEPAGES_FREE);
if (free_after != free_before)
FAIL("fallocate hole punch did not delete two huge pages\n");
PASS();
}
|