mirror of
https://github.com/aljazceru/turso.git
synced 2026-01-22 01:24:18 +01:00
Merge 'Fix io_uring WAL write corruption by ensuring buffer lifetime' from Daniel Boll
### Problem When using the `io_uring` backend, WAL file writes were corrupted: the submitted buffer data (e.g., WAL header magic `37 7f 06 82`) was correct in logs, but the file on disk showed incorrect data (e.g., `00 18 27 xx`). This occurred because the `Arc<RefCell<Buffer>>` was dropped before the asynchronous `io_uring` write completed, allowing the kernel to write stale or freed memory. ### Root Cause In `UringFile::pwrite`, the `buffer` was passed to `io_uring` via an `iovec`, but the `Arc<RefCell<Buffer>>` wasn’t guaranteed to live until the write finished. Unlike synchronous `UnixIO`, where the buffer persists during the `pwrite` call, `io_uring`’s async nature exposed this lifetime issue. ### Fix Modified `UringFile::pwrite` to hold a reference to the `buffer` in the completion callback by calling `buffer.borrow()`. This ensures the `Buffer` remains alive until `io_uring` completes the write, preventing memory corruption. ### Changes - Updated `core/io/io_uring.rs`: - Added `WriteCompletion` import. - Wrapped the original `Completion` in a new `WriteCompletion` closure that references the `buffer`, extending its lifetime until the write completes. ### Validation - Tested with `limbo -v io_uring`: - `.open limbo.db` - `CREATE TABLE users (id INT PRIMARY KEY, username TEXT);` - `INSERT INTO users VALUES (1, 'alice');` - `INSERT INTO users VALUES (2, 'bob');` - `SELECT * FROM users;` - Verified WAL file with `xxd -l 16 limbo.db-wal`: - Before: `0018 2734 ...` - After: `377f 0682 ...` (correct WAL magic). - `wal-browser limbo.db-wal` confirms the header is written correctly, **though frame checksums still need separate fixing** (tracked in a follow-up issue). ### Follow-Up - Frame checksum mismatches persist in `wal-browser` output (e.g., `00000000-00000000 != 14d64367-7b77a5a0`). This is a separate issue in `begin_write_wal_frame` or WAL frame initialization, to be addressed in a subsequent PR. Closes: #1137 Closes #1143
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
use super::{common, Completion, File, OpenFlags, IO};
|
||||
use super::{common, Completion, File, OpenFlags, WriteCompletion, IO};
|
||||
use crate::{LimboError, Result};
|
||||
use rustix::fs::{self, FlockOperation, OFlags};
|
||||
use rustix::io_uring::iovec;
|
||||
@@ -279,7 +279,14 @@ impl File for UringFile {
|
||||
.build()
|
||||
.user_data(io.ring.get_key())
|
||||
};
|
||||
io.ring.submit_entry(&write, c);
|
||||
io.ring.submit_entry(
|
||||
&write,
|
||||
Completion::Write(WriteCompletion::new(Box::new(move |result| {
|
||||
c.complete(result);
|
||||
// NOTE: Explicitly reference buffer to ensure it lives until here
|
||||
let _ = buffer.borrow();
|
||||
}))),
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user