-
Notifications
You must be signed in to change notification settings - Fork 661
btree/pager: make it way more difficult to mutate non-dirty pages #4233
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please review @pereman2
This PR is entirely motivated by corruption bugs caused by marking pages as dirty after they had already been modified, causing the subjournal to restore dirty content upon rollback. For examples of this see #4231 and #4232. Changes: 1. Change add_dirty() to return PageWriteGuard<'a> instead of Result<()> 2. Make get_contents_mut() only accessible through PageWriteGuard::contents_mut() 3. Added get_contents_mut_for_test() with #[cfg(test)] so that tests are less annoying 4. Make Page::get() private, and expose things like pin count and flags through separate methods. 5. Poke mutable holes for emptying or replacing page contents entirely for internals to use (i.e. this doesn't require going through add_dirty() because it doesn't make sense in those contexts, e.g. inside page cache)
d5b4040 to
5d64197
Compare
| } | ||
|
|
||
| pub fn overwrite_content(page: &PageRef, dest_offset: usize, new_payload: &[u8]) -> Result<()> { | ||
| turso_assert!(page.is_loaded(), "page should be loaded"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this assertion not required anymore? I'm working on a test that triggers this error (#4168, still a draft).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I brought it back. Didn't notice claude removed it for some reason even though I reviewed this multiple times :]
Beef
This PR is entirely motivated by corruption bugs caused by marking pages as dirty after they had already been modified, causing the subjournal to restore dirty content upon rollback. For examples of this see #4231 and #4232.
Major change 1: Return a
PageWriteGuardfromadd_dirty()and&mut PageContentis only accessible through that wrapperMajor change 2: Make a LOT of the
PageContentmethods require a mutable referencePageContent::as_ptr()that gets a mutable reference to the underlying buffer from an immutable.&PageContent, and replace it with regularas_sliceandas_mut_slicewrite_rightmost_ptr()require&mutget_contents_mut_for_test()from the first commit ->get_contents_mut_unsafe_dont_use()- should be only used in tests or places where subjournaling is never required OR the caller has manually verified that the page is dirty