Fix io_uring fsync race condition causing metadata loss #77

Merged
vitalif merged 1 commits from changwei.ye/vitastor:fix-fsync-race into master 2026-08-26 11:12:55 +03:00

1 Commits

Author SHA1 Message Date
81848432e4 Fix io_uring fsync race condition causing metadata loss
In the previous implementation, `unsynced_meta_write_count` was incremented early in `prepare_meta_block_write`
before the I/O request was even submitted. Because Vitastor does not use IOSQE_IO_LINK for io_uring batch
submissions, the kernel does not guarantee execution order within a batch.

Scenario:
1. Client A initiates a metadata write. `unsynced_meta_write_count` is incremented.
2. Client B sends a global SYNC request. The engine sees `unsynced_meta_write_count > 0`, clears it to 0,
   and prepares an `fsync(meta_fd)` SQE.
3. Both the `writev` and `fsync` SQEs are submitted in the same batch.
4. If the kernel's io_wq schedules the `fsync` before the `writev` (Count Stealing), the `fsync` completes
   instantly without flushing the intended metadata.
5. Client A's write completes and ACKs the client.
6. Client A issues a SYNC to guarantee its write. However, since the counter was already consumed by
   Client B's SYNC, Client A's SYNC sees a count of 0 and returns immediately without flushing.
7. A crash at this point results in metadata loss despite Client A receiving a successful SYNC ACK.

This commit moves the `unsynced_meta_write_count` increment into the io_uring completion callback of
the metadata `writev`. This perfectly mirrors the data area's "count-after-completion" strategy,
ensuring that concurrent SYNC operations cannot steal the count before the metadata is safely in
the OS page cache.
2026-08-26 10:11:27 +08:00