-
Notifications
You must be signed in to change notification settings - Fork 26
Decrypt without holding the downstairs lock #1021
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
Decrypt without holding the downstairs lock #1021
Conversation
Same sort of free real estate as b960fe8! Do not decrypt while holding the downstairs lock. Also, filter out invalid block contexts when validating read responses. This is then later relied upon (in the case when comparing different downstairs' read responses) when comparing `job.read_response_hashes` to what was just returned: `job.read_response_hashes` is `Vec<Option<u64>>` not `Vec<Vec<u64>>`, so zero or one valid block context is turned into an Option. Importantly, the result is not `collect`ed (except when panicking!), saving an allocation.
|
Here's some f3 test numbers (f3write -e 5 tmp && f3read tmp): main (@ 3927d8d): this branch: Using the same fio as #1019 (but with a 32 G disk, 512b, and nexus' extent size): main (@ 3927d8d): this branch: |
upstairs/src/lib.rs
Outdated
| ); | ||
| if job.read_response_hashes != read_response_hashes { | ||
|
|
||
| let mismatch = std::iter::zip( |
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.
This code duplicates stuff in the ack_status == AckStatus::Acked condition above. Perhaps it should be a function on job, e.g. DownstairsIO::check_read_response_hashes(&self, read_data: &[ReadResponse]))?
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 like it, also added in 6eb6d22
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 was thinking about also moving the rest of the stuff (including the logging and panic) into that function, but don't feel strongly about it.
leftwo
left a comment
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.
A high level question, if we are doing the decryption outside the lock, do we have
to worry about two reads coming back at close to the same time and then racing for
who is the first? My question is based on my lazyness on not figuring it out for myself.
upstairs/src/test.rs
Outdated
| } | ||
|
|
||
| #[tokio::test] | ||
| #[should_panic] |
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.
If we should panic here, then we unwrap on encrypt_in_placed won't this give us a false negative?
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.
You're right, see 707f4d9 where I rolled this back
| } | ||
|
|
||
| #[tokio::test] | ||
| #[should_panic] |
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.
Same should_panic here, If there is any unwrap() before the expected panic, I think this
tests will pass for the wrong reasons.
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.
Same, see 707f4d9
I don't think so. The decryption context doesn't hold any state that feeds forward from one decryption to the next (unlike something stateful like TLS). The locking of the Downstairs struct eventually does happen which serializes the modifications. If we had a race problem before this commit then that'd be an existing bug that I believe we'd have seen already. |
| } | ||
|
|
||
| if !successful_hash { | ||
| if let Some(valid_hash) = valid_hash { |
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.
Since you are here already, could we correct the comment up at line 4111, or at least mention that
it is only for the SQL backend? Thanks!
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.
Rgr, done in 5d46ff4
elide return statement
Same sort of free real estate as b960fe8! Do not decrypt while holding the downstairs lock.
Also, filter out invalid block contexts when validating read responses. This is then later relied upon (in the case when comparing different downstairs' read responses) when comparing
job.read_response_hashesto what was just returned:job.read_response_hashesisVec<Option<u64>>not
Vec<Vec<u64>>, so zero or one valid block context is turned intoan Option. Importantly, the result is not
collected (except when panicking!), saving an allocation.