aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric B Munson <emunson@mgebm.net>2010-11-23 08:52:14 -0700
committerEric B Munson <emunson@mgebm.net>2010-11-29 13:41:33 -0700
commitfe0b1c2c4223448dddace59e159eed80d0d8f875 (patch)
tree09ffde2852a5672c6078b5bcf54daeccb947017c
parent8007365d1bd2b84f2e3f665460add279900b005e (diff)
downloadlibhugetlbfs-fe0b1c2c4223448dddace59e159eed80d0d8f875.tar.gz
Use MAP_HUGETLB in get_huge_pages
When the kernel supports MAP_HUGETLB use it for requesting a huge page backed area instead of creating a file descriptor. Signed-off-by: Eric B Munson <emunson@mgebm.net> Acked-by: Mel Gorman <mel@csn.ul.ie>
-rw-r--r--alloc.c48
1 files changed, 34 insertions, 14 deletions
diff --git a/alloc.c b/alloc.c
index a7d37e5..675cfda 100644
--- a/alloc.c
+++ b/alloc.c
@@ -77,38 +77,58 @@ static void *fallback_base_pages(size_t len, ghp_t flags)
void *get_huge_pages(size_t len, ghp_t flags)
{
void *buf;
- int buf_fd;
+ int buf_fd = -1;
int saved_error;
int mmap_reserve = __hugetlb_opts.no_reserve ? MAP_NORESERVE : 0;
+ int mmap_hugetlb = 0;
/* Catch an altogether-too easy typo */
if (flags & GHR_MASK)
ERROR("Improper use of GHR_* in get_huge_pages()\n");
- /* Create a file descriptor for the new region */
- buf_fd = hugetlbfs_unlinked_fd();
- if (buf_fd < 0) {
- WARNING("Couldn't open hugetlbfs file for %zd-sized buffer\n",
- len);
- return NULL;
+#ifdef MAP_HUGETLB
+ mmap_hugetlb = MAP_HUGETLB;
+#endif
+
+ if (__hugetlb_opts.map_hugetlb &&
+ gethugepagesize() == kernel_default_hugepage_size()) {
+ /* Because we can use MAP_HUGETLB, we simply mmap the region */
+ buf = mmap(NULL, len, PROT_READ|PROT_WRITE,
+ MAP_PRIVATE|MAP_ANONYMOUS|mmap_hugetlb|mmap_reserve,
+ 0, 0);
+ } else {
+ /* Create a file descriptor for the new region */
+ buf_fd = hugetlbfs_unlinked_fd();
+ if (buf_fd < 0) {
+ WARNING("Couldn't open hugetlbfs file for %zd-sized buffer\n",
+ len);
+ return NULL;
+ }
+
+ /* Map the requested region */
+ buf = mmap(NULL, len, PROT_READ|PROT_WRITE,
+ MAP_PRIVATE|mmap_reserve, buf_fd, 0);
}
- /* Map the requested region */
- buf = mmap(NULL, len, PROT_READ|PROT_WRITE,
- MAP_PRIVATE|mmap_reserve, buf_fd, 0);
if (buf == MAP_FAILED) {
- close(buf_fd);
+ if (buf_fd >= 0)
+ close(buf_fd);
WARNING("get_huge_pages: New region mapping failed (flags: 0x%lX): %s\n",
flags, strerror(errno));
return NULL;
}
- /* Fault the region to ensure accesses succeed */
+ /*
+ * Fault the region to ensure accesses succeed, buf_fd is passed
+ * regarless of how we mmap'd because if MAP_HUGETLB was used the value
+ * in buf_fd is ignored
+ */
if (hugetlbfs_prefault(buf_fd, buf, len) != 0) {
saved_error = errno;
munmap(buf, len);
- close(buf_fd);
+ if (buf_fd >= 0)
+ close(buf_fd);
WARNING("get_huge_pages: Prefaulting failed (flags: 0x%lX): %s\n",
flags, strerror(saved_error));
@@ -116,7 +136,7 @@ void *get_huge_pages(size_t len, ghp_t flags)
}
/* Close the file so we do not have to track the descriptor */
- if (close(buf_fd) != 0) {
+ if (buf_fd >= 0 && close(buf_fd) != 0) {
WARNING("Failed to close new buffer fd: %s\n", strerror(errno));
munmap(buf, len);
return NULL;