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.
{
        char * block_start = block_data + block_header_size;
        char * block_end = block_data + block_size;
        static constexpr size_t key_prefix_size = sizeof(size_t) + sizeof(size_t);
        while (block_start + key_prefix_size < block_end)
        {
            size_t key_size = unalignedLoad<size_t>(block_start);
            block_start += sizeof(key_size);
            StringRef complex_key (block_start, key_size);
            block_start += key_size;
            size_t allocated_size = unalignedLoad<size_t>(block_start);
            block_start += sizeof(size_t);
            
            if (allocated_size == 0)
                break;
            complex_keys.emplace_back(complex_key);
            block_start += allocated_size;
        }
    }
private:
    size_t block_size;
    char * block_data = nullptr;
    size_t current_block_offset = block_header_size;
    size_t keys_size = 0;
};
struct SSDCacheIndex
{
    SSDCacheIndex(size_t block_index_, size_t offset_in_block_)