diff --git a/drivers/cube/cubelinux_store.rs b/drivers/cube/cubelinux_store.rs index 3ff1e1f1f..631733d93 100644 --- a/drivers/cube/cubelinux_store.rs +++ b/drivers/cube/cubelinux_store.rs @@ -412,6 +412,10 @@ struct TableCache { log_off: u64, log_used: u64, table: KVVec, + /// The log window's bytes. Held for the same reason as the table and one better: on a cache hit + /// the log *cannot* have changed, because a write raises the generation this cache is keyed on — + /// so a hit needs no read to know what the log says. + log: KVVec, /// The two control-block heads, and a scratch to read them with: both persist so that validating /// a call costs no allocation. A 4096-byte scratch here is what the whole block used to need; /// 96 bytes of head is all the validation ever wanted. @@ -2952,6 +2956,7 @@ impl Addressed { log_off: 0, log_used: 0, table: KVVec::new(), + log: KVVec::new(), heads: KVVec::new(), scratch: KVVec::new(), }); @@ -2988,14 +2993,13 @@ impl Addressed { opened.scratch.resize(4096, 0, GFP_KERNEL)?; if cache.generation == generation { - // The store has not moved: what describes it is what we already hold. The log is still - // read, because it is the one thing that changes without a fold — and a write raises the - // generation, so a log newer than this cache is a log this branch does not see. + // The store has not moved: what describes it is what we already hold, the log included. + // The log is the one thing that changes without a fold, and a write raises the generation + // this cache is keyed on — so an unchanged generation is exactly a log that cannot have + // changed. Served from memory, not re-read: this was the last device read a coordinate + // read made that it did not have to. opened.spaces.extend_from_slice(cache.table.as_slice(), GFP_KERNEL)?; - if cache.log_used > 0 { - let len = core::cmp::min(WAL_HEADER_LEN + cache.log_used as usize, MAX_BYTES); - read_exact_at(file, cache.log_off, len, &mut opened.log, &mut opened.scratch)?; - } + opened.log.extend_from_slice(cache.log.as_slice(), GFP_KERNEL)?; return Ok(Some(opened)); } @@ -3032,8 +3036,11 @@ impl Addressed { if control.log_used > 0 { let len = core::cmp::min(WAL_HEADER_LEN + control.log_used as usize, MAX_BYTES); - read_exact_at(file, control.log_off() as u64, len, &mut opened.log, &mut opened.scratch)?; + read_exact_at(file, control.log_off() as u64, len, &mut cache.log, &mut opened.scratch)?; + } else { + cache.log.clear(); } + opened.log.extend_from_slice(cache.log.as_slice(), GFP_KERNEL)?; cache.generation = generation; cache.image_off = opened.image_off;