File size is updated correctly according to 

> fdatasync() is similar to fsync(), but does not flush modified metadata unless that metadata is needed in order to allow a subsequent data retrieval to be correctly handled.  For example, changes to  st_atime  or  st_mtime  (respec‐
       tively,  time  of  last  access  and  time  of last modification; see inode(7)) do not require flushing because they are not necessary for a subsequent data read to be handled correctly.  On the other hand, a change to the file size
       (st_size, as made by say ftruncate(2)), would require a metadata flush.

And we don't care about modification times.
Should work alright.
{
        if (block_start + blocks_length > current_blocks_size)
            return false;
        size_t buffer_size_in_bytes = blocks_length * block_size;
        Memory read_buffer_memory(block_size * blocks_length, block_size);
        iocb request{};
        iocb * request_ptr = &request;
        #if defined(__FreeBSD__)
        request.aio.aio_lio_opcode = LIO_READ;
        request.aio.aio_fildes = file.fd;
        request.aio.aio_buf = reinterpret_cast<volatile void *>(reinterpret_cast<UInt64>(read_buffer_memory.data()));
        request.aio.aio_nbytes = buffer_size_in_bytes;
        request.aio.aio_offset = block_start * block_size;
        request.aio_data = 0;
        #else
        request.aio_lio_opcode = IOCB_CMD_PREAD;
        request.aio_fildes = file.fd;
        request.aio_buf = reinterpret_cast<UInt64>(read_buffer_memory.data());
        request.aio_nbytes = buffer_size_in_bytes;
        request.aio_offset = block_start * block_size;
        request.aio_data = 0;
        #endif
        io_event event{};
        AIOContext aio_context(1);
        while (io_submit(aio_context.ctx, 1, &request_ptr) != 1)
        {