File: fallocate_align.c

package info (click to toggle)
libhugetlbfs 2.24-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,272 kB
  • sloc: ansic: 10,830; python: 810; makefile: 670; sh: 660; asm: 170
file content (143 lines) | stat: -rw-r--r-- 4,729 bytes parent folder | download | duplicates (3)
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();
}