Skip to content

Commit e59e3fe

Browse files
authored
Make IOop use absolute block indices (#1693)
Following up from #1685, the upstairs only cares about the block → extent mapping when checking live-repair stuff. However, all of our `IOop` variants store `(ExtentId, BlockOffset)` tuples. This PR makes the `IOop` more compact by using an absolute `BlockIndex` instead, then unpacks it into an `(ExtentId, BlockOffset)` only when needed for live-repair checks.
1 parent 534eae4 commit e59e3fe

File tree

3 files changed

+86
-92
lines changed

3 files changed

+86
-92
lines changed

upstairs/src/downstairs.rs

Lines changed: 17 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use crate::{
2626
RawWrite, ReconcileIO, ReconciliationId, RegionDefinition, ReplaceResult,
2727
SnapshotDetails, WorkSummary,
2828
};
29-
use crucible_common::{BlockIndex, BlockOffset, ExtentId, NegotiationError};
29+
use crucible_common::{BlockIndex, ExtentId, NegotiationError};
3030
use crucible_protocol::WriteHeader;
3131

3232
use ringbuffer::RingBuffer;
@@ -1510,8 +1510,7 @@ impl Downstairs {
15101510

15111511
let aread = IOop::Read {
15121512
dependencies,
1513-
start_eid: ExtentId(0),
1514-
start_offset: BlockOffset(7),
1513+
start_block: BlockIndex(7),
15151514
count: 1,
15161515
block_size: 512,
15171516
};
@@ -1565,25 +1564,17 @@ impl Downstairs {
15651564

15661565
// TODO: can anyone actually give us an empty write?
15671566
let start = blocks.start().unwrap_or(BlockIndex(0));
1568-
1569-
// XXX change IOop to take `BlockIndex` instead?
1570-
let extent_size = self.ddef.unwrap().extent_size().value;
1571-
let start_eid = ExtentId((start.0 / extent_size) as u32);
1572-
let start_offset = BlockOffset(start.0 % extent_size);
1573-
15741567
let awrite = if is_write_unwritten {
15751568
IOop::WriteUnwritten {
15761569
dependencies,
1577-
start_eid,
1578-
start_offset,
1570+
start_block: start,
15791571
data: write.data.freeze(),
15801572
blocks: write.blocks,
15811573
}
15821574
} else {
15831575
IOop::Write {
15841576
dependencies,
1585-
start_eid,
1586-
start_offset,
1577+
start_block: start,
15871578
data: write.data.freeze(),
15881579
blocks: write.blocks,
15891580
}
@@ -2164,16 +2155,9 @@ impl Downstairs {
21642155
// TODO: can anyone actually give us an empty write?
21652156
let start = blocks.start().unwrap_or(BlockIndex(0));
21662157
let ddef = self.ddef.unwrap();
2167-
2168-
// XXX change IOop to take `BlockIndex` instead?
2169-
let extent_size = ddef.extent_size().value;
2170-
let start_eid = ExtentId((start.0 / extent_size) as u32);
2171-
let start_offset = BlockOffset(start.0 % extent_size);
2172-
21732158
let aread = IOop::Read {
21742159
dependencies,
2175-
start_eid,
2176-
start_offset,
2160+
start_block: start,
21772161
count: blocks.blocks().len() as u64,
21782162
block_size: ddef.block_size(),
21792163
};
@@ -2267,7 +2251,10 @@ impl Downstairs {
22672251
let r = match client.should_send() {
22682252
Ok(r) => r,
22692253
Err(ShouldSendError::InLiveRepair) => {
2270-
if io.send_io_live_repair(last_repair_extent) {
2254+
if io.send_io_live_repair(
2255+
last_repair_extent,
2256+
self.ddef.as_ref().unwrap(),
2257+
) {
22712258
EnqueueResult::Send
22722259
} else {
22732260
EnqueueResult::Skip
@@ -2320,9 +2307,6 @@ impl Downstairs {
23202307

23212308
/// Sends the given job to the given client
23222309
fn send(&mut self, ds_id: JobId, io: IOop, client_id: ClientId) {
2323-
let def = self.ddef.unwrap();
2324-
let blocks_per_extent = def.extent_size().value;
2325-
23262310
let job = self.clients[client_id].prune_deps(
23272311
ds_id,
23282312
io,
@@ -2331,8 +2315,7 @@ impl Downstairs {
23312315
let message = match job {
23322316
IOop::Write {
23332317
dependencies,
2334-
start_eid,
2335-
start_offset,
2318+
start_block,
23362319
blocks,
23372320
data,
23382321
} => {
@@ -2343,18 +2326,14 @@ impl Downstairs {
23432326
session_id: self.cfg.session_id,
23442327
job_id: ds_id,
23452328
dependencies,
2346-
start: BlockIndex(
2347-
start_eid.0 as u64 * blocks_per_extent
2348-
+ start_offset.0,
2349-
),
2329+
start: start_block,
23502330
contexts: blocks,
23512331
},
23522332
data,
23532333
}
23542334
}
23552335
IOop::WriteUnwritten {
2356-
start_eid,
2357-
start_offset,
2336+
start_block,
23582337
blocks,
23592338
dependencies,
23602339
data,
@@ -2369,10 +2348,7 @@ impl Downstairs {
23692348
session_id: self.cfg.session_id,
23702349
job_id: ds_id,
23712350
dependencies,
2372-
start: BlockIndex(
2373-
start_eid.0 as u64 * blocks_per_extent
2374-
+ start_offset.0,
2375-
),
2351+
start: start_block,
23762352
contexts: blocks,
23772353
},
23782354
data,
@@ -2408,8 +2384,7 @@ impl Downstairs {
24082384
}
24092385
IOop::Read {
24102386
dependencies,
2411-
start_eid,
2412-
start_offset,
2387+
start_block,
24132388
count,
24142389
..
24152390
} => {
@@ -2419,9 +2394,7 @@ impl Downstairs {
24192394
session_id: self.cfg.session_id,
24202395
job_id: ds_id,
24212396
dependencies,
2422-
start: BlockIndex(
2423-
start_eid.0 as u64 * blocks_per_extent + start_offset.0,
2424-
),
2397+
start: start_block,
24252398
count,
24262399
}
24272400
}
@@ -3544,7 +3517,7 @@ impl Downstairs {
35443517
fn submit_test_write_block(
35453518
&mut self,
35463519
eid: ExtentId,
3547-
block: BlockOffset,
3520+
block: crucible_common::BlockOffset,
35483521
is_write_unwritten: bool,
35493522
) -> JobId {
35503523
let extent_size = self.ddef.unwrap().extent_size().value;
@@ -3597,7 +3570,7 @@ impl Downstairs {
35973570
fn submit_read_block(
35983571
&mut self,
35993572
eid: ExtentId,
3600-
block: BlockOffset,
3573+
block: crucible_common::BlockOffset,
36013574
) -> JobId {
36023575
let extent_size = self.ddef.unwrap().extent_size().value;
36033576
let block = BlockIndex(u64::from(eid.0) * extent_size + block.0);

upstairs/src/lib.rs

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,10 +1018,8 @@ enum IOop {
10181018
Write {
10191019
/// Jobs that mush finish before this
10201020
dependencies: Vec<JobId>,
1021-
/// Extent in which the write starts
1022-
start_eid: ExtentId,
1023-
/// Relative offset (within that extent) to start writing
1024-
start_offset: BlockOffset,
1021+
/// Absolute block at which the write starts
1022+
start_block: BlockIndex,
10251023
/// Per-block context
10261024
blocks: Vec<BlockContext>,
10271025
/// Raw data, tightly packed
@@ -1030,10 +1028,8 @@ enum IOop {
10301028
WriteUnwritten {
10311029
/// Jobs that mush finish before this
10321030
dependencies: Vec<JobId>,
1033-
/// Extent in which the write starts
1034-
start_eid: ExtentId,
1035-
/// Relative offset (within that extent) to start writing
1036-
start_offset: BlockOffset,
1031+
/// Absolute block at which the write starts
1032+
start_block: BlockIndex,
10371033
/// Per-block context
10381034
blocks: Vec<BlockContext>,
10391035
/// Raw data, tightly packed
@@ -1042,10 +1038,8 @@ enum IOop {
10421038
Read {
10431039
/// Jobs that must finish before this
10441040
dependencies: Vec<JobId>,
1045-
/// Extent in which the read starts
1046-
start_eid: ExtentId,
1047-
/// Relative offset (within that extent) to start reading
1048-
start_offset: BlockOffset,
1041+
/// Absolute block at which the read starts
1042+
start_block: BlockIndex,
10491043
/// Number of blocks to read
10501044
count: u64,
10511045
/// Block size for this region (stored here for convenience)
@@ -1197,7 +1191,11 @@ impl IOop {
11971191
// repair), and determine if this IO should be sent to the downstairs or not
11981192
// (skipped).
11991193
// Return true if we should send it.
1200-
fn send_io_live_repair(&self, extent_limit: Option<ExtentId>) -> bool {
1194+
fn send_io_live_repair(
1195+
&self,
1196+
extent_limit: Option<ExtentId>,
1197+
ddef: &RegionDefinition,
1198+
) -> bool {
12011199
// Always send live-repair IOs
12021200
if matches!(
12031201
self,
@@ -1216,9 +1214,12 @@ impl IOop {
12161214
// repaired is handled with dependencies, and IOs should arrive
12171215
// here with those dependencies already set.
12181216
match &self {
1219-
IOop::Write { start_eid, .. }
1220-
| IOop::WriteUnwritten { start_eid, .. }
1221-
| IOop::Read { start_eid, .. } => *start_eid <= extent_limit,
1217+
IOop::Write { start_block, .. }
1218+
| IOop::WriteUnwritten { start_block, .. }
1219+
| IOop::Read { start_block, .. } => {
1220+
let start_eid = start_block.0 / ddef.extent_size().value;
1221+
start_eid as u32 <= extent_limit.0
1222+
}
12221223
IOop::Flush { .. } => {
12231224
// If we have set extent limit, then we go ahead and
12241225
// send the flush with the extent_limit in it, and allow

0 commit comments

Comments
 (0)