Index: llvm/cmake/config-ix.cmake =================================================================== --- llvm/cmake/config-ix.cmake +++ llvm/cmake/config-ix.cmake @@ -197,6 +197,11 @@ check_symbol_exists(futimens sys/stat.h HAVE_FUTIMENS) check_symbol_exists(futimes sys/time.h HAVE_FUTIMES) check_symbol_exists(posix_fallocate fcntl.h HAVE_POSIX_FALLOCATE) + +set(CMAKE_REQUIRED_DEFINITIONS "-D_GNU_SOURCE") +check_symbol_exists(fallocate fcntl.h HAVE_FALLOCATE) +set(CMAKE_REQUIRED_DEFINITIONS "") + # AddressSanitizer conflicts with lib/Support/Unix/Signals.inc # Avoid sigaltstack on Apple platforms, where backtrace() cannot handle it # (rdar://7089625) and _Unwind_Backtrace is unusable because it cannot unwind Index: llvm/include/llvm/Config/config.h.cmake =================================================================== --- llvm/include/llvm/Config/config.h.cmake +++ llvm/include/llvm/Config/config.h.cmake @@ -59,6 +59,9 @@ /* Define to 1 if you have the header file. */ #cmakedefine HAVE_ERRNO_H ${HAVE_ERRNO_H} +/* Define to 1 if you have the `fallocate' function. */ +#cmakedefine HAVE_FALLOCATE ${HAVE_FALLOCATE} + /* Define to 1 if you have the header file. */ #cmakedefine HAVE_FCNTL_H ${HAVE_FCNTL_H} Index: llvm/lib/Support/Unix/Path.inc =================================================================== --- llvm/lib/Support/Unix/Path.inc +++ llvm/lib/Support/Unix/Path.inc @@ -422,19 +422,23 @@ } std::error_code resize_file(int FD, uint64_t Size) { -#if defined(HAVE_POSIX_FALLOCATE) - // If we have posix_fallocate use it. Unlike ftruncate it always allocates - // space, so we get an error if the disk is full. - if (int Err = ::posix_fallocate(FD, 0, Size)) { - if (Err != EOPNOTSUPP) - return std::error_code(Err, std::generic_category()); - } +#ifdef HAVE_FALLOCATE + // We prefer fallocate over ftruncate because only the former system + // call can detect a "disk full" error. ftruncate creates a sparse + // file, so it succeeds even if sufficient disk space is not available. + // + // fallocate() is a Linux-only system call. POSIX defines posix_fallocate, + // but the function is very slow in some implementations (including glibc's) + // because it attempts to actually write zero bytes to each disk block. + // Thus, we do not want to use posix_fallocate. + if (fallocate(FD, 0, 0, Size) == 0) + return std::error_code(); + if (errno == ENOSPC) + return std::error_code(errno, std::generic_category()); #endif - // Use ftruncate as a fallback. It may or may not allocate space. At least on - // OS X with HFS+ it does. + if (::ftruncate(FD, Size) == -1) return std::error_code(errno, std::generic_category()); - return std::error_code(); }