Skip to content

Commit 178d581

Browse files
committed
Assert ds_new cache validity
Assert that the cached job ids in ds_new match the New jobs in ds_active, and that io_state_count is correct. Fixes oxidecomputer#765
1 parent 54942ba commit 178d581

File tree

1 file changed

+45
-1
lines changed

1 file changed

+45
-1
lines changed

upstairs/src/lib.rs

+45-1
Original file line numberDiff line numberDiff line change
@@ -3342,15 +3342,59 @@ impl Downstairs {
33423342
* requests for this client.
33433343
*/
33443344
fn new_work(&mut self, client_id: u8) -> Vec<u64> {
3345-
self.ds_new[client_id as usize].drain(..).collect()
3345+
// Compute what should be in the ds_new cache, and assert that the cache
3346+
// is valid. This should only run during debug builds (read: CI) and
3347+
// should not affect release builds as this will degrade performance.
3348+
let computed: Vec<u64> = self
3349+
.ds_active
3350+
.values()
3351+
.filter_map(|job| {
3352+
if let Some(IOState::New) = job.state.get(&client_id) {
3353+
Some(job.ds_id)
3354+
} else {
3355+
None
3356+
}
3357+
})
3358+
.collect();
3359+
3360+
let cached: Vec<u64> =
3361+
self.ds_new[client_id as usize].drain(..).collect();
3362+
3363+
debug_assert_eq!(computed.len(), cached.len());
3364+
debug_assert_eq!(
3365+
HashSet::<&u64>::from_iter(computed.iter()),
3366+
HashSet::<&u64>::from_iter(cached.iter())
3367+
);
3368+
3369+
// Assert that the io_state_count accounting is accurate.
3370+
debug_assert_eq!(
3371+
self.io_state_count.new[client_id as usize] as usize,
3372+
cached.len(),
3373+
);
3374+
3375+
cached
33463376
}
33473377

33483378
/**
33493379
* Called to requeue work that was previously found by calling
33503380
* [`new_work`], presumably due to flow control.
33513381
*/
33523382
fn requeue_work(&mut self, client_id: u8, work: &[u64]) {
3383+
// Assert that the work we're requeuing is still new. This should only
3384+
// run during debug builds (read: CI) and should not affect release
3385+
// builds as this will degrade performance.
3386+
for job_id in work {
3387+
let job = self.ds_active.get_mut(job_id).unwrap();
3388+
debug_assert_eq!(*job.state.get(&client_id).unwrap(), IOState::New);
3389+
}
3390+
33533391
self.ds_new[client_id as usize].extend_from_slice(work);
3392+
3393+
// Assert that the io_state_count accounting is accurate.
3394+
debug_assert_eq!(
3395+
self.io_state_count.new[client_id as usize] as usize,
3396+
self.ds_new[client_id as usize].len(),
3397+
);
33543398
}
33553399

33563400
/**

0 commit comments

Comments
 (0)