< prev index next >

src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.cpp

Print this page

        

*** 20,29 **** --- 20,30 ---- * or visit www.oracle.com if you need additional information or have any * questions. */ #include "precompiled.hpp" + #include "gc/shared/gcLogPrecious.hpp" #include "gc/z/zArray.inline.hpp" #include "gc/z/zErrno.hpp" #include "gc/z/zGlobals.hpp" #include "gc/z/zLargePages.inline.hpp" #include "gc/z/zMountPoint_linux.hpp"
*** 128,189 **** // Get filesystem statistics struct statfs buf; if (fstatfs(_fd, &buf) == -1) { ZErrno err; ! log_error(gc)("Failed to determine filesystem type for backing file (%s)", err.to_string()); return; } _filesystem = buf.f_type; _block_size = buf.f_bsize; _available = buf.f_bavail * _block_size; ! log_info(gc, init)("Heap Backing Filesystem: %s (0x" UINT64_FORMAT_X ")", ! is_tmpfs() ? ZFILESYSTEM_TMPFS : is_hugetlbfs() ? ZFILESYSTEM_HUGETLBFS : "other", _filesystem); // Make sure the filesystem type matches requested large page type if (ZLargePages::is_transparent() && !is_tmpfs()) { ! log_error(gc)("-XX:+UseTransparentHugePages can only be enabled when using a %s filesystem", ! ZFILESYSTEM_TMPFS); return; } if (ZLargePages::is_transparent() && !tmpfs_supports_transparent_huge_pages()) { ! log_error(gc)("-XX:+UseTransparentHugePages on a %s filesystem not supported by kernel", ! ZFILESYSTEM_TMPFS); return; } if (ZLargePages::is_explicit() && !is_hugetlbfs()) { ! log_error(gc)("-XX:+UseLargePages (without -XX:+UseTransparentHugePages) can only be enabled " ! "when using a %s filesystem", ZFILESYSTEM_HUGETLBFS); return; } if (!ZLargePages::is_explicit() && is_hugetlbfs()) { ! log_error(gc)("-XX:+UseLargePages must be enabled when using a %s filesystem", ! ZFILESYSTEM_HUGETLBFS); return; } if (ZLargePages::is_explicit() && os::large_page_size() != ZGranuleSize) { ! log_error(gc)("Incompatible large page size configured " SIZE_FORMAT " (expected " SIZE_FORMAT ")", ! os::large_page_size(), ZGranuleSize); return; } // Make sure the filesystem block size is compatible if (ZGranuleSize % _block_size != 0) { ! log_error(gc)("Filesystem backing the heap has incompatible block size (" SIZE_FORMAT ")", ! _block_size); return; } if (is_hugetlbfs() && _block_size != ZGranuleSize) { ! log_error(gc)("%s filesystem has unexpected block size " SIZE_FORMAT " (expected " SIZE_FORMAT ")", ! ZFILESYSTEM_HUGETLBFS, _block_size, ZGranuleSize); return; } // Successfully initialized _initialized = true; --- 129,190 ---- // Get filesystem statistics struct statfs buf; if (fstatfs(_fd, &buf) == -1) { ZErrno err; ! log_error_p(gc)("Failed to determine filesystem type for backing file (%s)", err.to_string()); return; } _filesystem = buf.f_type; _block_size = buf.f_bsize; _available = buf.f_bavail * _block_size; ! log_info_p(gc, init)("Heap Backing Filesystem: %s (0x" UINT64_FORMAT_X ")", ! is_tmpfs() ? ZFILESYSTEM_TMPFS : is_hugetlbfs() ? ZFILESYSTEM_HUGETLBFS : "other", _filesystem); // Make sure the filesystem type matches requested large page type if (ZLargePages::is_transparent() && !is_tmpfs()) { ! log_error_p(gc)("-XX:+UseTransparentHugePages can only be enabled when using a %s filesystem", ! ZFILESYSTEM_TMPFS); return; } if (ZLargePages::is_transparent() && !tmpfs_supports_transparent_huge_pages()) { ! log_error_p(gc)("-XX:+UseTransparentHugePages on a %s filesystem not supported by kernel", ! ZFILESYSTEM_TMPFS); return; } if (ZLargePages::is_explicit() && !is_hugetlbfs()) { ! log_error_p(gc)("-XX:+UseLargePages (without -XX:+UseTransparentHugePages) can only be enabled " ! "when using a %s filesystem", ZFILESYSTEM_HUGETLBFS); return; } if (!ZLargePages::is_explicit() && is_hugetlbfs()) { ! log_error_p(gc)("-XX:+UseLargePages must be enabled when using a %s filesystem", ! ZFILESYSTEM_HUGETLBFS); return; } if (ZLargePages::is_explicit() && os::large_page_size() != ZGranuleSize) { ! log_error_p(gc)("Incompatible large page size configured " SIZE_FORMAT " (expected " SIZE_FORMAT ")", ! os::large_page_size(), ZGranuleSize); return; } // Make sure the filesystem block size is compatible if (ZGranuleSize % _block_size != 0) { ! log_error_p(gc)("Filesystem backing the heap has incompatible block size (" SIZE_FORMAT ")", ! _block_size); return; } if (is_hugetlbfs() && _block_size != ZGranuleSize) { ! log_error_p(gc)("%s filesystem has unexpected block size " SIZE_FORMAT " (expected " SIZE_FORMAT ")", ! ZFILESYSTEM_HUGETLBFS, _block_size, ZGranuleSize); return; } // Successfully initialized _initialized = true;
*** 197,212 **** // Create file const int extra_flags = ZLargePages::is_explicit() ? MFD_HUGETLB : 0; const int fd = ZSyscall::memfd_create(filename, MFD_CLOEXEC | extra_flags); if (fd == -1) { ZErrno err; ! log_debug(gc, init)("Failed to create memfd file (%s)", ! ((ZLargePages::is_explicit() && err == EINVAL) ? "Hugepages not supported" : err.to_string())); return -1; } ! log_info(gc, init)("Heap Backing File: /memfd:%s", filename); return fd; } int ZPhysicalMemoryBacking::create_file_fd(const char* name) const { --- 198,213 ---- // Create file const int extra_flags = ZLargePages::is_explicit() ? MFD_HUGETLB : 0; const int fd = ZSyscall::memfd_create(filename, MFD_CLOEXEC | extra_flags); if (fd == -1) { ZErrno err; ! log_debug_p(gc, init)("Failed to create memfd file (%s)", ! ((ZLargePages::is_explicit() && err == EINVAL) ? "Hugepages not supported" : err.to_string())); return -1; } ! log_info_p(gc, init)("Heap Backing File: /memfd:%s", filename); return fd; } int ZPhysicalMemoryBacking::create_file_fd(const char* name) const {
*** 218,274 **** : z_preferred_tmpfs_mountpoints; // Find mountpoint ZMountPoint mountpoint(filesystem, preferred_mountpoints); if (mountpoint.get() == NULL) { ! log_error(gc)("Use -XX:AllocateHeapAt to specify the path to a %s filesystem", filesystem); return -1; } // Try to create an anonymous file using the O_TMPFILE flag. Note that this // flag requires kernel >= 3.11. If this fails we fall back to open/unlink. const int fd_anon = os::open(mountpoint.get(), O_TMPFILE|O_EXCL|O_RDWR|O_CLOEXEC, S_IRUSR|S_IWUSR); if (fd_anon == -1) { ZErrno err; ! log_debug(gc, init)("Failed to create anonymous file in %s (%s)", mountpoint.get(), ! (err == EINVAL ? "Not supported" : err.to_string())); } else { // Get inode number for anonymous file struct stat stat_buf; if (fstat(fd_anon, &stat_buf) == -1) { ZErrno err; ! log_error(gc)("Failed to determine inode number for anonymous file (%s)", err.to_string()); return -1; } ! log_info(gc, init)("Heap Backing File: %s/#" UINT64_FORMAT, mountpoint.get(), (uint64_t)stat_buf.st_ino); return fd_anon; } ! log_debug(gc, init)("Falling back to open/unlink"); // Create file name char filename[PATH_MAX]; snprintf(filename, sizeof(filename), "%s/%s.%d", mountpoint.get(), name, os::current_process_id()); // Create file const int fd = os::open(filename, O_CREAT|O_EXCL|O_RDWR|O_CLOEXEC, S_IRUSR|S_IWUSR); if (fd == -1) { ZErrno err; ! log_error(gc)("Failed to create file %s (%s)", filename, err.to_string()); return -1; } // Unlink file if (unlink(filename) == -1) { ZErrno err; ! log_error(gc)("Failed to unlink file %s (%s)", filename, err.to_string()); return -1; } ! log_info(gc, init)("Heap Backing File: %s", filename); return fd; } int ZPhysicalMemoryBacking::create_fd(const char* name) const { --- 219,275 ---- : z_preferred_tmpfs_mountpoints; // Find mountpoint ZMountPoint mountpoint(filesystem, preferred_mountpoints); if (mountpoint.get() == NULL) { ! log_error_p(gc)("Use -XX:AllocateHeapAt to specify the path to a %s filesystem", filesystem); return -1; } // Try to create an anonymous file using the O_TMPFILE flag. Note that this // flag requires kernel >= 3.11. If this fails we fall back to open/unlink. const int fd_anon = os::open(mountpoint.get(), O_TMPFILE|O_EXCL|O_RDWR|O_CLOEXEC, S_IRUSR|S_IWUSR); if (fd_anon == -1) { ZErrno err; ! log_debug_p(gc, init)("Failed to create anonymous file in %s (%s)", mountpoint.get(), ! (err == EINVAL ? "Not supported" : err.to_string())); } else { // Get inode number for anonymous file struct stat stat_buf; if (fstat(fd_anon, &stat_buf) == -1) { ZErrno err; ! log_error_p(gc)("Failed to determine inode number for anonymous file (%s)", err.to_string()); return -1; } ! log_info_p(gc, init)("Heap Backing File: %s/#" UINT64_FORMAT, mountpoint.get(), (uint64_t)stat_buf.st_ino); return fd_anon; } ! log_debug_p(gc, init)("Falling back to open/unlink"); // Create file name char filename[PATH_MAX]; snprintf(filename, sizeof(filename), "%s/%s.%d", mountpoint.get(), name, os::current_process_id()); // Create file const int fd = os::open(filename, O_CREAT|O_EXCL|O_RDWR|O_CLOEXEC, S_IRUSR|S_IWUSR); if (fd == -1) { ZErrno err; ! log_error_p(gc)("Failed to create file %s (%s)", filename, err.to_string()); return -1; } // Unlink file if (unlink(filename) == -1) { ZErrno err; ! log_error_p(gc)("Failed to unlink file %s (%s)", filename, err.to_string()); return -1; } ! log_info_p(gc, init)("Heap Backing File: %s", filename); return fd; } int ZPhysicalMemoryBacking::create_fd(const char* name) const {
*** 281,291 **** const int fd = create_mem_fd(name); if (fd != -1) { return fd; } ! log_debug(gc, init)("Falling back to searching for an accessible mount point"); } return create_file_fd(name); } --- 282,292 ---- const int fd = create_mem_fd(name); if (fd != -1) { return fd; } ! log_debug_p(gc)("Falling back to searching for an accessible mount point"); } return create_file_fd(name); }
*** 296,357 **** void ZPhysicalMemoryBacking::warn_available_space(size_t max) const { // Note that the available space on a tmpfs or a hugetlbfs filesystem // will be zero if no size limit was specified when it was mounted. if (_available == 0) { // No size limit set, skip check ! log_info(gc, init)("Available space on backing filesystem: N/A"); return; } ! log_info(gc, init)("Available space on backing filesystem: " SIZE_FORMAT "M", _available / M); // Warn if the filesystem doesn't currently have enough space available to hold // the max heap size. The max heap size will be capped if we later hit this limit // when trying to expand the heap. if (_available < max) { ! log_warning(gc)("***** WARNING! INCORRECT SYSTEM CONFIGURATION DETECTED! *****"); ! log_warning(gc)("Not enough space available on the backing filesystem to hold the current max Java heap"); ! log_warning(gc)("size (" SIZE_FORMAT "M). Please adjust the size of the backing filesystem accordingly " "(available", max / M); ! log_warning(gc)("space is currently " SIZE_FORMAT "M). Continuing execution with the current filesystem " "size could", _available / M); ! log_warning(gc)("lead to a premature OutOfMemoryError being thrown, due to failure to map memory."); } } void ZPhysicalMemoryBacking::warn_max_map_count(size_t max) const { const char* const filename = ZFILENAME_PROC_MAX_MAP_COUNT; FILE* const file = fopen(filename, "r"); if (file == NULL) { // Failed to open file, skip check ! log_debug(gc, init)("Failed to open %s", filename); return; } size_t actual_max_map_count = 0; const int result = fscanf(file, SIZE_FORMAT, &actual_max_map_count); fclose(file); if (result != 1) { // Failed to read file, skip check ! log_debug(gc, init)("Failed to read %s", filename); return; } // The required max map count is impossible to calculate exactly since subsystems // other than ZGC are also creating memory mappings, and we have no control over that. // However, ZGC tends to create the most mappings and dominate the total count. // In the worst cases, ZGC will map each granule three times, i.e. once per heap view. // We speculate that we need another 20% to allow for non-ZGC subsystems to map memory. const size_t required_max_map_count = (max / ZGranuleSize) * 3 * 1.2; if (actual_max_map_count < required_max_map_count) { ! log_warning(gc)("***** WARNING! INCORRECT SYSTEM CONFIGURATION DETECTED! *****"); ! log_warning(gc)("The system limit on number of memory mappings per process might be too low for the given"); ! log_warning(gc)("max Java heap size (" SIZE_FORMAT "M). Please adjust %s to allow for at", max / M, filename); ! log_warning(gc)("least " SIZE_FORMAT " mappings (current limit is " SIZE_FORMAT "). Continuing execution " "with the current", required_max_map_count, actual_max_map_count); ! log_warning(gc)("limit could lead to a fatal error, due to failure to map memory."); } } void ZPhysicalMemoryBacking::warn_commit_limits(size_t max) const { // Warn if available space is too low --- 297,358 ---- void ZPhysicalMemoryBacking::warn_available_space(size_t max) const { // Note that the available space on a tmpfs or a hugetlbfs filesystem // will be zero if no size limit was specified when it was mounted. if (_available == 0) { // No size limit set, skip check ! log_info_p(gc, init)("Available space on backing filesystem: N/A"); return; } ! log_info_p(gc, init)("Available space on backing filesystem: " SIZE_FORMAT "M", _available / M); // Warn if the filesystem doesn't currently have enough space available to hold // the max heap size. The max heap size will be capped if we later hit this limit // when trying to expand the heap. if (_available < max) { ! log_warning_p(gc)("***** WARNING! INCORRECT SYSTEM CONFIGURATION DETECTED! *****"); ! log_warning_p(gc)("Not enough space available on the backing filesystem to hold the current max Java heap"); ! log_warning_p(gc)("size (" SIZE_FORMAT "M). Please adjust the size of the backing filesystem accordingly " "(available", max / M); ! log_warning_p(gc)("space is currently " SIZE_FORMAT "M). Continuing execution with the current filesystem " "size could", _available / M); ! log_warning_p(gc)("lead to a premature OutOfMemoryError being thrown, due to failure to map memory."); } } void ZPhysicalMemoryBacking::warn_max_map_count(size_t max) const { const char* const filename = ZFILENAME_PROC_MAX_MAP_COUNT; FILE* const file = fopen(filename, "r"); if (file == NULL) { // Failed to open file, skip check ! log_debug_p(gc, init)("Failed to open %s", filename); return; } size_t actual_max_map_count = 0; const int result = fscanf(file, SIZE_FORMAT, &actual_max_map_count); fclose(file); if (result != 1) { // Failed to read file, skip check ! log_debug_p(gc, init)("Failed to read %s", filename); return; } // The required max map count is impossible to calculate exactly since subsystems // other than ZGC are also creating memory mappings, and we have no control over that. // However, ZGC tends to create the most mappings and dominate the total count. // In the worst cases, ZGC will map each granule three times, i.e. once per heap view. // We speculate that we need another 20% to allow for non-ZGC subsystems to map memory. const size_t required_max_map_count = (max / ZGranuleSize) * 3 * 1.2; if (actual_max_map_count < required_max_map_count) { ! log_warning_p(gc)("***** WARNING! INCORRECT SYSTEM CONFIGURATION DETECTED! *****"); ! log_warning_p(gc)("The system limit on number of memory mappings per process might be too low for the given"); ! log_warning_p(gc)("max Java heap size (" SIZE_FORMAT "M). Please adjust %s to allow for at", max / M, filename); ! log_warning_p(gc)("least " SIZE_FORMAT " mappings (current limit is " SIZE_FORMAT "). Continuing execution " "with the current", required_max_map_count, actual_max_map_count); ! log_warning_p(gc)("limit could lead to a fatal error, due to failure to map memory."); } } void ZPhysicalMemoryBacking::warn_commit_limits(size_t max) const { // Warn if available space is too low
*** 562,572 **** // Failed return err; } // Not supported ! log_debug(gc)("Falling back to fallocate() compatibility mode"); z_fallocate_supported = false; } return fallocate_fill_hole_compat(offset, length); } --- 563,573 ---- // Failed return err; } // Not supported ! log_debug_p(gc)("Falling back to fallocate() compatibility mode"); z_fallocate_supported = false; } return fallocate_fill_hole_compat(offset, length); }
*** 643,662 **** // the hugetlbfs filesystem, then we wait and retry a few times before // giving up. Otherwise there is a risk that running JVMs back-to-back // will fail, since there is a delay between process termination and the // huge pages owned by that process being returned to the huge page pool // and made available for new allocations. ! log_debug(gc, init)("Failed to commit memory (%s), retrying", err.to_string()); // Wait and retry in one second, in the hope that huge pages will be // available by then. sleep(1); goto retry; } // Failed ! log_error(gc)("Failed to commit memory (%s)", err.to_string()); return false; } // Success return true; --- 644,663 ---- // the hugetlbfs filesystem, then we wait and retry a few times before // giving up. Otherwise there is a risk that running JVMs back-to-back // will fail, since there is a delay between process termination and the // huge pages owned by that process being returned to the huge page pool // and made available for new allocations. ! log_debug_p(gc, init)("Failed to commit memory (%s), retrying", err.to_string()); // Wait and retry in one second, in the hope that huge pages will be // available by then. sleep(1); goto retry; } // Failed ! log_error_p(gc)("Failed to commit memory (%s)", err.to_string()); return false; } // Success return true;
< prev index next >