diff --git a/drivers/cube/cubelinux_store.rs b/drivers/cube/cubelinux_store.rs index 8b18be6dd..9ed57e753 100644 --- a/drivers/cube/cubelinux_store.rs +++ b/drivers/cube/cubelinux_store.rs @@ -278,6 +278,18 @@ const BOOT_SPACE: [u8; SPACE_ID_LEN] = [0xFC; SPACE_ID_LEN]; /// The class mask the boot record stamps: `EventFlags::BOOT`, bit 7. The kernel cannot link /// `cube-core`, so the bit is spelled out here and on the userspace side, and the agreement is held /// by `verify-boot-record` โ€” the same shape as the `0xFC` space id, for the same reason. +/// The store class for "the kernel wrote this about its own boot" โ€” the first bit of the store's +/// own class vocabulary. +/// +/// The class field is `v4`'s two bytes in the index entry, and it is **its own 16-bit space**. The +/// reason this is named here instead of borrowed from `cube_core::WordFlags` is that `WordFlags` is a +/// different field whose sixteen bits are all spoken for: reading this bit through it gives +/// `TYPE_MASK == 10`, "data type: code", which is a meaning this bit does not have. A vocabulary +/// belongs to one field, and this field's first vocabulary is `events`. +/// +/// `0x0800` is the one bit this field and `WordFlags` share, deliberately and by name: the sealing +/// layer stamps it here (`SEALED_FLAG` in `cube-store-seal`) and it means encrypted in both places, +/// so the two agree instead of colliding. See `DESIGN-flag-vocabularies.md` ยง6. const BOOT_FLAGS: u16 = 1 << 7; /// The coordinate the record lives at. One record, the current boot: each boot overwrites the last, @@ -3089,12 +3101,13 @@ unsafe fn v3_get( len: usize, out_flags: *mut u16, ) -> isize { - // The log is owned for the duration: what it says borrows it, and reading the image needs - // `&mut image`. It is what a checkpoint has not folded, so it is small. - let mut log = KVVec::::new(); - if log.extend_from_slice(image.log(), GFP_KERNEL).is_err() { - return -12; // -ENOMEM - } + // The log is *taken*, not copied. It used to be copied into a second buffer because what it says + // borrows it while reading the image needs `&mut image` โ€” but that borrow is one field, and moving + // the field out settles it for nothing. Measured, a coordinate read costs the same in a store + // forty times larger while the index search does nine probe reads against fifteen: the device + // reads are nearly free and the per-call cost is this kind of setup, so a copy of the log window + // on every read is the thing worth removing, not the reads. + let log = core::mem::replace(&mut image.log, KVVec::new()); match log_effect(log.as_slice(), &sp, &key) { Some(Effect::Delete) => return -2, // -ENOENT Some(Effect::Write(value, flags)) => {