aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric B Munson <emunson@mgebm.net>2010-11-23 08:52:12 -0700
committerEric B Munson <emunson@mgebm.net>2010-11-29 13:41:03 -0700
commitda9280b07cd1c3bc1249129617dbad0867d6a334 (patch)
tree5d418612f3622d44f1c5c8cc66ddee7962ccd668
parentb046b0bc9a5a170b0f43972e9846f46c1bfd7aaa (diff)
downloadlibhugetlbfs-da9280b07cd1c3bc1249129617dbad0867d6a334.tar.gz
Transition hugetlbfs_prefault to handle MAP_HUGETLB
hugetlbfs_prefault relies on having a file descriptor associated with the huge page backed region to prefault the huge pages. This patch gives an alternative for prefaulting which will be used when the kernel supports MAP_HUGETLB. Signed-off-by: Eric B Munson <emunson@mgebm.net> Acked-by: Mel Gorman <mel@csn.ul.ie>
-rw-r--r--hugeutils.c59
1 files changed, 38 insertions, 21 deletions
diff --git a/hugeutils.c b/hugeutils.c
index 4e26dd5..af648a5 100644
--- a/hugeutils.c
+++ b/hugeutils.c
@@ -956,6 +956,15 @@ int hugetlbfs_unlinked_fd(void)
#define IOV_LEN 64
int hugetlbfs_prefault(int fd, void *addr, size_t length)
{
+ size_t offset;
+ struct iovec iov[IOV_LEN];
+ int ret;
+ int i;
+ int close_fd = -1;
+
+ if (!__hugetlbfs_prefault)
+ return 0;
+
/*
* The NUMA users of libhugetlbfs' malloc feature are
* expected to use the numactl program to specify an
@@ -972,30 +981,38 @@ int hugetlbfs_prefault(int fd, void *addr, size_t length)
* -ENOMEM is returned. The caller is expected to release the entire
* mapping and optionally it may recover by mapping base pages instead.
*/
- if (__hugetlbfs_prefault) {
- int i;
- size_t offset;
- struct iovec iov[IOV_LEN];
- int ret;
-
- for (offset = 0; offset < length; ) {
- for (i = 0; i < IOV_LEN && offset < length; i++) {
- iov[i].iov_base = addr + offset;
- iov[i].iov_len = 1;
- offset += gethugepagesize();
- }
- ret = readv(fd, iov, i);
- if (ret != i) {
- DEBUG("Got %d of %d requested; err=%d\n", ret,
- i, ret < 0 ? errno : 0);
- WARNING("Failed to reserve %ld huge pages "
- "for new region\n",
- length / gethugepagesize());
- return -ENOMEM;
- }
+
+ if (fd < 0 && __hugetlb_opts.map_hugetlb) {
+ fd = open("/dev/zero", O_RDONLY);
+ if (fd < 0) {
+ ERROR("Failed to open /dev/zero for reading\n");
+ return -ENOMEM;
+ }
+ close_fd = fd;
+ }
+
+ for (offset = 0; offset < length; ) {
+ for (i = 0; i < IOV_LEN && offset < length; i++) {
+ iov[i].iov_base = addr + offset;
+ iov[i].iov_len = 1;
+ offset += gethugepagesize();
+ }
+ ret = readv(fd, iov, i);
+ if (ret != i) {
+ DEBUG("Got %d of %d requested; err=%d\n", ret,
+ i, ret < 0 ? errno : 0);
+ WARNING("Failed to reserve %ld huge pages "
+ "for new region\n",
+ length / gethugepagesize());
+ if (close_fd >= 0)
+ close(close_fd);
+ return -ENOMEM;
}
}
+ if (close_fd >= 0)
+ close(close_fd);
+
return 0;
}