29 #include "gc/z/zLargePages.inline.hpp" 30 #include "logging/log.hpp" 31 #include "runtime/os.hpp" 32 #include "utilities/align.hpp" 33 #include "utilities/debug.hpp" 34 35 #include <fcntl.h> 36 #include <sys/mman.h> 37 #include <sys/stat.h> 38 #include <sys/statfs.h> 39 #include <sys/types.h> 40 #include <unistd.h> 41 42 // Filesystem names 43 #define ZFILESYSTEM_TMPFS "tmpfs" 44 #define ZFILESYSTEM_HUGETLBFS "hugetlbfs" 45 46 // Sysfs file for transparent huge page on tmpfs 47 #define ZFILENAME_SHMEM_ENABLED "/sys/kernel/mm/transparent_hugepage/shmem_enabled" 48 49 // Default mount points 50 #define ZMOUNTPOINT_TMPFS "/dev/shm" 51 #define ZMOUNTPOINT_HUGETLBFS "/hugepages" 52 53 // Java heap filename 54 #define ZFILENAME_HEAP "java_heap" 55 56 // Support for building on older Linux systems 57 #ifndef __NR_memfd_create 58 #define __NR_memfd_create 319 59 #endif 60 #ifndef MFD_CLOEXEC 61 #define MFD_CLOEXEC 0x0001U 62 #endif 63 #ifndef MFD_HUGETLB 64 #define MFD_HUGETLB 0x0004U 65 #endif 66 #ifndef O_CLOEXEC 67 #define O_CLOEXEC 02000000 68 #endif 69 #ifndef O_TMPFILE 70 #define O_TMPFILE (020000000 | O_DIRECTORY) 71 #endif 72 73 // Filesystem types, see statfs(2) 74 #ifndef TMPFS_MAGIC 75 #define TMPFS_MAGIC 0x01021994 76 #endif 77 #ifndef HUGETLBFS_MAGIC 78 #define HUGETLBFS_MAGIC 0x958458f6 79 #endif 80 81 static int z_memfd_create(const char *name, unsigned int flags) { 82 return syscall(__NR_memfd_create, name, flags); 83 } 84 85 bool ZBackingFile::_hugetlbfs_mmap_retry = true; 86 87 ZBackingFile::ZBackingFile() : 88 _fd(-1), 89 _filesystem(0), 90 _available(0), 91 _initialized(false) { 92 93 // Create backing file 94 _fd = create_fd(ZFILENAME_HEAP); 95 if (_fd == -1) { 96 return; 97 } 98 99 // Get filesystem statistics 100 struct statfs statfs_buf; 149 char filename[PATH_MAX]; 150 snprintf(filename, sizeof(filename), "%s%s", name, ZLargePages::is_explicit() ? ".hugetlb" : ""); 151 152 // Create file 153 const int extra_flags = ZLargePages::is_explicit() ? MFD_HUGETLB : 0; 154 const int fd = z_memfd_create(filename, MFD_CLOEXEC | extra_flags); 155 if (fd == -1) { 156 ZErrno err; 157 log_debug(gc, init)("Failed to create memfd file (%s)", 158 ((UseLargePages && err == EINVAL) ? "Hugepages not supported" : err.to_string())); 159 return -1; 160 } 161 162 log_info(gc, init)("Heap backed by file: /memfd:%s", filename); 163 164 return fd; 165 } 166 167 int ZBackingFile::create_file_fd(const char* name) const { 168 const char* const filesystem = ZLargePages::is_explicit() ? ZFILESYSTEM_HUGETLBFS : ZFILESYSTEM_TMPFS; 169 const char* const mountpoint = ZLargePages::is_explicit() ? ZMOUNTPOINT_HUGETLBFS : ZMOUNTPOINT_TMPFS; 170 171 // Find mountpoint 172 ZBackingPath path(filesystem, mountpoint); 173 if (path.get() == NULL) { 174 log_error(gc, init)("Use -XX:ZPath to specify the path to a %s filesystem", filesystem); 175 return -1; 176 } 177 178 // Try to create an anonymous file using the O_TMPFILE flag. Note that this 179 // flag requires kernel >= 3.11. If this fails we fall back to open/unlink. 180 const int fd_anon = open(path.get(), O_TMPFILE|O_EXCL|O_RDWR|O_CLOEXEC, S_IRUSR|S_IWUSR); 181 if (fd_anon == -1) { 182 ZErrno err; 183 log_debug(gc, init)("Failed to create anonymous file in %s (%s)", path.get(), 184 (err == EINVAL ? "Not supported" : err.to_string())); 185 } else { 186 // Get inode number for anonymous file 187 struct stat stat_buf; 188 if (fstat(fd_anon, &stat_buf) == -1) { 189 ZErrno err; 190 log_error(gc, init)("Failed to determine inode number for anonymous file (%s)", err.to_string()); 191 return -1; 192 } | 29 #include "gc/z/zLargePages.inline.hpp" 30 #include "logging/log.hpp" 31 #include "runtime/os.hpp" 32 #include "utilities/align.hpp" 33 #include "utilities/debug.hpp" 34 35 #include <fcntl.h> 36 #include <sys/mman.h> 37 #include <sys/stat.h> 38 #include <sys/statfs.h> 39 #include <sys/types.h> 40 #include <unistd.h> 41 42 // Filesystem names 43 #define ZFILESYSTEM_TMPFS "tmpfs" 44 #define ZFILESYSTEM_HUGETLBFS "hugetlbfs" 45 46 // Sysfs file for transparent huge page on tmpfs 47 #define ZFILENAME_SHMEM_ENABLED "/sys/kernel/mm/transparent_hugepage/shmem_enabled" 48 49 // Java heap filename 50 #define ZFILENAME_HEAP "java_heap" 51 52 // Support for building on older Linux systems 53 #ifndef __NR_memfd_create 54 #define __NR_memfd_create 319 55 #endif 56 #ifndef MFD_CLOEXEC 57 #define MFD_CLOEXEC 0x0001U 58 #endif 59 #ifndef MFD_HUGETLB 60 #define MFD_HUGETLB 0x0004U 61 #endif 62 #ifndef O_CLOEXEC 63 #define O_CLOEXEC 02000000 64 #endif 65 #ifndef O_TMPFILE 66 #define O_TMPFILE (020000000 | O_DIRECTORY) 67 #endif 68 69 // Filesystem types, see statfs(2) 70 #ifndef TMPFS_MAGIC 71 #define TMPFS_MAGIC 0x01021994 72 #endif 73 #ifndef HUGETLBFS_MAGIC 74 #define HUGETLBFS_MAGIC 0x958458f6 75 #endif 76 77 // Preferred tmpfs mount points, ordered by priority 78 static const char* z_preferred_tmpfs_mountpoints[] = { 79 "/dev/shm", 80 "/run/shm", 81 NULL 82 }; 83 84 // Preferred tmpfs mount points, ordered by priority 85 static const char* z_preferred_hugetlbfs_mountpoints[] = { 86 "/dev/hugepages", 87 "/hugepages", 88 NULL 89 }; 90 91 static int z_memfd_create(const char *name, unsigned int flags) { 92 return syscall(__NR_memfd_create, name, flags); 93 } 94 95 bool ZBackingFile::_hugetlbfs_mmap_retry = true; 96 97 ZBackingFile::ZBackingFile() : 98 _fd(-1), 99 _filesystem(0), 100 _available(0), 101 _initialized(false) { 102 103 // Create backing file 104 _fd = create_fd(ZFILENAME_HEAP); 105 if (_fd == -1) { 106 return; 107 } 108 109 // Get filesystem statistics 110 struct statfs statfs_buf; 159 char filename[PATH_MAX]; 160 snprintf(filename, sizeof(filename), "%s%s", name, ZLargePages::is_explicit() ? ".hugetlb" : ""); 161 162 // Create file 163 const int extra_flags = ZLargePages::is_explicit() ? MFD_HUGETLB : 0; 164 const int fd = z_memfd_create(filename, MFD_CLOEXEC | extra_flags); 165 if (fd == -1) { 166 ZErrno err; 167 log_debug(gc, init)("Failed to create memfd file (%s)", 168 ((UseLargePages && err == EINVAL) ? "Hugepages not supported" : err.to_string())); 169 return -1; 170 } 171 172 log_info(gc, init)("Heap backed by file: /memfd:%s", filename); 173 174 return fd; 175 } 176 177 int ZBackingFile::create_file_fd(const char* name) const { 178 const char* const filesystem = ZLargePages::is_explicit() ? ZFILESYSTEM_HUGETLBFS : ZFILESYSTEM_TMPFS; 179 const char** const mountpoints = ZLargePages::is_explicit() ? z_preferred_hugetlbfs_mountpoints : z_preferred_tmpfs_mountpoints; 180 181 // Find mountpoint 182 ZBackingPath path(filesystem, mountpoints); 183 if (path.get() == NULL) { 184 log_error(gc, init)("Use -XX:ZPath to specify the path to a %s filesystem", filesystem); 185 return -1; 186 } 187 188 // Try to create an anonymous file using the O_TMPFILE flag. Note that this 189 // flag requires kernel >= 3.11. If this fails we fall back to open/unlink. 190 const int fd_anon = open(path.get(), O_TMPFILE|O_EXCL|O_RDWR|O_CLOEXEC, S_IRUSR|S_IWUSR); 191 if (fd_anon == -1) { 192 ZErrno err; 193 log_debug(gc, init)("Failed to create anonymous file in %s (%s)", path.get(), 194 (err == EINVAL ? "Not supported" : err.to_string())); 195 } else { 196 // Get inode number for anonymous file 197 struct stat stat_buf; 198 if (fstat(fd_anon, &stat_buf) == -1) { 199 ZErrno err; 200 log_error(gc, init)("Failed to determine inode number for anonymous file (%s)", err.to_string()); 201 return -1; 202 } |