Skip to content

Commit 87e2107

Browse files
committed
[llvm][cas] Fix error handling of posix_fallocate
The posix_fallocate function returns an error code directly and not via errno, and on older POSIX versions it may return EINVAL in places it should return ENOTSUP (in practice, seen on FreeBSD). (cherry picked from commit c8f75c6)
1 parent 7725fb2 commit 87e2107

File tree

1 file changed

+15
-5
lines changed

1 file changed

+15
-5
lines changed

llvm/lib/CAS/OnDiskCommon.cpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "llvm/Config/config.h"
1212
#include "llvm/Support/Error.h"
1313
#include "llvm/Support/Process.h"
14+
#include <limits>
1415
#include <mutex>
1516
#include <optional>
1617
#include <thread>
@@ -115,16 +116,25 @@ cas::ondisk::tryLockFileThreadSafe(int FD, std::chrono::milliseconds Timeout,
115116
}
116117

117118
Expected<size_t> cas::ondisk::preallocateFileTail(int FD, size_t CurrentSize, size_t NewSize) {
118-
auto CreateErrorFromErrno = [&]() -> Expected<size_t> {
119-
std::error_code EC = errnoAsErrorCode();
119+
auto CreateError = [&](std::error_code EC) -> Expected<size_t> {
120120
if (EC == std::errc::not_supported)
121121
// Ignore ENOTSUP in case the filesystem cannot preallocate.
122122
return NewSize;
123+
#if defined(HAVE_POSIX_FALLOCATE)
124+
if (EC == std::errc::invalid_argument &&
125+
CurrentSize < NewSize && // len > 0
126+
NewSize < std::numeric_limits<off_t>::max()) // 0 <= offset, len < max
127+
// Prior to 2024, POSIX required EINVAL for cases that should be ENOTSUP,
128+
// so handle it the same as above if it is not one of the other ways to
129+
// get EINVAL.
130+
return NewSize;
131+
#endif
123132
return createStringError(EC, "failed to allocate to CAS file: " + EC.message());
124133
};
125134
#if defined(HAVE_POSIX_FALLOCATE)
126-
if (posix_fallocate(FD, CurrentSize, NewSize - CurrentSize))
127-
return CreateErrorFromErrno();
135+
// Note: posix_fallocate returns its error directly, not via errno.
136+
if (int Err = posix_fallocate(FD, CurrentSize, NewSize - CurrentSize))
137+
return CreateError(std::error_code(Err, std::generic_category()));
128138
return NewSize;
129139
#elif defined(__APPLE__)
130140
fstore_t FAlloc;
@@ -134,7 +144,7 @@ Expected<size_t> cas::ondisk::preallocateFileTail(int FD, size_t CurrentSize, si
134144
FAlloc.fst_length = NewSize - CurrentSize;
135145
FAlloc.fst_bytesalloc = 0;
136146
if (fcntl(FD, F_PREALLOCATE, &FAlloc))
137-
return CreateErrorFromErrno();
147+
return CreateError(errnoAsErrorCode());
138148
assert(CurrentSize + FAlloc.fst_bytesalloc >= NewSize);
139149
return CurrentSize + FAlloc.fst_bytesalloc;
140150
#else

0 commit comments

Comments
 (0)