Skip to content

Commit b026dd8

Browse files
authored
Remove optionality for BlockRes in DeferredWrite (#1441)
The `Option<BlockRes>` is always `Some(..)`, _except_ in unit testing, so it has too many degrees of freedom during normal operation. This PR turns it into a plain `BlockRes`, and adds a `#[cfg(test)]` helper function to make an empty `BlockRes` during unit tests.
1 parent 9d82a99 commit b026dd8

File tree

3 files changed

+26
-44
lines changed

3 files changed

+26
-44
lines changed

upstairs/src/block_req.rs

+7
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ impl<T, E> BlockRes<T, E> {
2424
// XXX this eats the result!
2525
let _ = self.0.take().expect("sender was populated").send(result);
2626
}
27+
28+
/// Builds an empty `BlockRes`, for use in unit testing
29+
#[cfg(test)]
30+
pub fn dummy() -> Self {
31+
let (tx, _) = oneshot::channel();
32+
Self(Some(tx))
33+
}
2734
}
2835

2936
impl<T, E> Drop for BlockRes<T, E> {

upstairs/src/deferred.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ pub(crate) struct DeferredWrite {
105105
pub ddef: RegionDefinition,
106106
pub impacted_blocks: ImpactedBlocks,
107107
pub data: BytesMut,
108-
pub res: Option<BlockRes>,
108+
pub res: BlockRes,
109109
pub is_write_unwritten: bool,
110110
pub cfg: Arc<UpstairsConfig>,
111111
}
@@ -127,7 +127,7 @@ pub(crate) struct EncryptedWrite {
127127
/// An `RawWrite` containing our encrypted data
128128
pub data: RawWrite,
129129
pub impacted_blocks: ImpactedBlocks,
130-
pub res: Option<BlockRes>,
130+
pub res: BlockRes,
131131
pub is_write_unwritten: bool,
132132
}
133133

upstairs/src/upstairs.rs

+17-42
Original file line numberDiff line numberDiff line change
@@ -1352,26 +1352,6 @@ impl Upstairs {
13521352
cdt::up__to__ds__read__start!(|| (gw_id.0));
13531353
}
13541354

1355-
/// Submits a new write job to the upstairs
1356-
///
1357-
/// This function **defers** the write job submission, because writes
1358-
/// require encrypting data (which is expensive) and we'd like to return as
1359-
/// quickly as possible.
1360-
fn submit_deferred_write(
1361-
&mut self,
1362-
offset: BlockIndex,
1363-
data: BytesMut,
1364-
res: BlockRes,
1365-
is_write_unwritten: bool,
1366-
) {
1367-
self.submit_deferred_write_inner(
1368-
offset,
1369-
data,
1370-
Some(res),
1371-
is_write_unwritten,
1372-
)
1373-
}
1374-
13751355
/// Submits a dummy write (without an associated `BlockOp`)
13761356
///
13771357
/// This **does not** go through the deferred-write pipeline
@@ -1382,22 +1362,26 @@ impl Upstairs {
13821362
data: BytesMut,
13831363
is_write_unwritten: bool,
13841364
) {
1385-
if let Some(w) =
1386-
self.compute_deferred_write(offset, data, None, is_write_unwritten)
1387-
{
1365+
if let Some(w) = self.compute_deferred_write(
1366+
offset,
1367+
data,
1368+
BlockRes::dummy(),
1369+
is_write_unwritten,
1370+
) {
13881371
self.submit_write(DeferredWrite::run(w))
13891372
}
13901373
}
13911374

1392-
/// Submits a new write job to the upstairs, optionally without a `BlockRes`
1375+
/// Submits a new write job to the upstairs
13931376
///
1394-
/// # Panics
1395-
/// If `res` is `None` and this isn't running in the test suite
1396-
fn submit_deferred_write_inner(
1377+
/// This function **defers** the write job submission, because writes
1378+
/// require encrypting data (which is expensive) and we'd like to return as
1379+
/// quickly as possible.
1380+
fn submit_deferred_write(
13971381
&mut self,
13981382
offset: BlockIndex,
13991383
data: BytesMut,
1400-
res: Option<BlockRes>,
1384+
res: BlockRes,
14011385
is_write_unwritten: bool,
14021386
) {
14031387
// It's possible for the write to be invalid out of the gate, in which
@@ -1426,22 +1410,15 @@ impl Upstairs {
14261410
&mut self,
14271411
offset: BlockIndex,
14281412
data: BytesMut,
1429-
res: Option<BlockRes>,
1413+
res: BlockRes,
14301414
is_write_unwritten: bool,
14311415
) -> Option<DeferredWrite> {
1432-
#[cfg(not(test))]
1433-
assert!(res.is_some());
1434-
14351416
if !self.guest_io_ready() {
1436-
if let Some(res) = res {
1437-
res.send_err(CrucibleError::UpstairsInactive);
1438-
}
1417+
res.send_err(CrucibleError::UpstairsInactive);
14391418
return None;
14401419
}
14411420
if self.cfg.read_only {
1442-
if let Some(res) = res {
1443-
res.send_err(CrucibleError::ModifyingReadOnlyRegion);
1444-
}
1421+
res.send_err(CrucibleError::ModifyingReadOnlyRegion);
14451422
return None;
14461423
}
14471424

@@ -1450,9 +1427,7 @@ impl Upstairs {
14501427
*/
14511428
let ddef = self.ddef.get_def().unwrap();
14521429
if let Err(e) = ddef.validate_io(offset, data.len()) {
1453-
if let Some(res) = res {
1454-
res.send_err(e);
1455-
}
1430+
res.send_err(e);
14561431
return None;
14571432
}
14581433

@@ -1500,7 +1475,7 @@ impl Upstairs {
15001475
write.is_write_unwritten,
15011476
)
15021477
},
1503-
write.res.map(GuestBlockRes::Other),
1478+
Some(GuestBlockRes::Other(write.res)),
15041479
);
15051480

15061481
if write.is_write_unwritten {

0 commit comments

Comments
 (0)