Skip to content

Writes are not durable: no fsync between write and rename #175

Description

@xxfast

FileCodec.encode and VersionedCodec.encode write to a staging file, close it, then atomicMove it into place. Closing flushes the userspace buffer to the OS, but nothing forces the data to disk. kotlinx-io has no fsync in its API: RawSink exposes flush() only, and FileSystem has atomicMove with no sync counterpart.

A rename is a metadata operation and can land durably while the data blocks have not. On a hard kill or power loss that leaves a file that exists with zero length, which is the classic rename-without-fsync failure.

Worth investigating as the cause of #80, #157 and #162. All three show JSON input: with nothing after it, so empty files rather than truncated or interleaved ones, and in #80 and #162 it is the two-byte .version file that comes back empty. That fits a durability gap better than it fits concurrent writers. It would also explain why it clustered on one reporter's device and nobody could reproduce it on demand.

#172 stopped these from crashing, and #174 removes a separate corruption route, but neither addresses this. A store that silently empties itself is still data loss.

Likely needs an upstream request to kotlinx-io or a platform-specific expect/actual sync, so worth confirming the diagnosis before picking either.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions