Merge #17887: bug-fix macos: give free bytes to F_PREALLOCATE

75163f4729c10c40d2843da28a8c79ab89193f6a bug-fix macos: give free bytes to F_PREALLOCATE (Karl-Johan Alm)

Pull request description:

  The macos manpage for `fcntl` (for `F_PEOFPOSMODE`) states:

  > Allocate from the physical end of file.  In this case, fst_length indicates the number of newly allocated bytes desired.

  This would result in the rev files being essentially pre-allocating 2x their necessary size (this is the case for block files as well, but these are flushed down to their right sizes every time) as they would pre-allocate `pos + length` **free** bytes, rather than allocating `length` bytes after `pos`, as expected.

  Fixes #17827.

ACKs for top commit:
  eriknylund:
    ACK 75163f4729c10c40d2843da28a8c79ab89193f6a built locally. All tests passing. Manual test as per my previous comment above on an older commit, using an APFS unencrypted disk image with 3 GB.
  laanwj:
    code review ACK 75163f4729c10c40d2843da28a8c79ab89193f6a

Tree-SHA512: 105c8d56c20acad8febdf0583f1e5721b63376ace325a7a62c2e4b15a442c7131404ed604c32c0cda716791d7ca5aa9f5b6a774ff86e39838bc7e87ca3c42760
This commit is contained in:
Wladimir J. van der Laan 2020-01-22 16:26:53 +01:00 committed by pasta
parent 81f118f3d3
commit 1b5ea905a3

View File

@ -1159,17 +1159,19 @@ void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length) {
SetEndOfFile(hFile); SetEndOfFile(hFile);
#elif defined(MAC_OSX) #elif defined(MAC_OSX)
// OSX specific version // OSX specific version
// NOTE: Contrary to other OS versions, the OSX version assumes that
// NOTE: offset is the size of the file.
fstore_t fst; fstore_t fst;
fst.fst_flags = F_ALLOCATECONTIG; fst.fst_flags = F_ALLOCATECONTIG;
fst.fst_posmode = F_PEOFPOSMODE; fst.fst_posmode = F_PEOFPOSMODE;
fst.fst_offset = 0; fst.fst_offset = 0;
fst.fst_length = (off_t)offset + length; fst.fst_length = length; // mac os fst_length takes the # of free bytes to allocate, not desired file size
fst.fst_bytesalloc = 0; fst.fst_bytesalloc = 0;
if (fcntl(fileno(file), F_PREALLOCATE, &fst) == -1) { if (fcntl(fileno(file), F_PREALLOCATE, &fst) == -1) {
fst.fst_flags = F_ALLOCATEALL; fst.fst_flags = F_ALLOCATEALL;
fcntl(fileno(file), F_PREALLOCATE, &fst); fcntl(fileno(file), F_PREALLOCATE, &fst);
} }
ftruncate(fileno(file), fst.fst_length); ftruncate(fileno(file), static_cast<off_t>(offset) + length);
#else #else
#if defined(__linux__) #if defined(__linux__)
// Version using posix_fallocate // Version using posix_fallocate