APFS failure to preallocate file space

Originator:jamesandrewstone
Number:rdar://38939209 Date Originated:27 March 2018
Status:open Resolved:
Product:MacOS + SDK Product Version:
Classification:Serious Reproducible:Always
 
Summary: Preallocating file space on APFS fails with error "Invalid Arguments"

Steps to Reproduce:
Compile the attached code using "clang++ --std=c++14 radar.cpp -o radar"
Run the binary produced on an APFS file system. I used MacOS 10.13.3, and can also reproduce on a APFS ramdisk. However, the code attached works correctly on a HSF+ file system.
On APFS, the program outputs: "Failed to preallocate space! Invalid argument"
On HSF+, the program outputs: "successfully preallocated file"

Expected Results:
I expect the call to fcntl to succeed on APFS as it does on HSF+.

Actual Results:
Calling fcntl to preallocate file space immediately after the file is created fails.
Note that adding a sufficient delay between file creation and calling fcntl can cause the call to succeed so the issue seems to be timing related. We tried syncing the file before the preallocation, but this doesn't help.

Version/Build:
MacBook Pro (Retina, 13-inch, Early 2015)
Processor: 3.1 GHz Intel Core i7
Memory: 16 GB 1867 MHz DDR3

Clang version:
Apple LLVM version 9.0.0 (clang-900.0.39.2)
Target: x86_64-apple-darwin17.4.0
Thread model: posix


Source Code of "radar.cpp":

#include <fcntl.h>
#include <iostream>
#include <unistd.h>

int main() {
    const char* file_name = "test.txt";

    if (access(file_name, F_OK) == 0) {
        int rm_status = unlink(file_name);
        if (rm_status == -1) {
            std::cout << "could not remove the existing file: " << file_name << std::endl;
        }
    }
    
    int fd = ::open(file_name, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
    if (fd < 0) {
        std::cout << "could not open file" << std::endl;
        return 1;
    }
    
    const size_t bytes_to_write = 5;
    ssize_t written_bytes = ::write(fd, "hello", bytes_to_write);
    if (written_bytes == bytes_to_write) {
        const off_t space_to_allocate = 100;
        fstore_t store = { F_ALLOCATEALL, F_PEOFPOSMODE, 0, space_to_allocate, 0 };
        int ret = ::fcntl(fd, F_PREALLOCATE, &store);
        if (ret == -1) {
            int err = errno;
            const size_t error_buffer_size = 256;
            char error_buffer[error_buffer_size + 1];
            const int result = ::strerror_r(err, error_buffer, error_buffer_size);
            error_buffer[error_buffer_size] = '\0';
            std::cout << "Failed to preallocate space! " << error_buffer << std::endl;
        } else {
            std::cout << "successfully preallocated file" << std::endl;
        }
    } else {
        std::cout << "could not write to file, exiting" << std::endl;
    }

    ::close(fd);
}

Comments


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!