diff --git a/Makefile b/Makefile index 1104e09..4b735bf 100644 --- a/Makefile +++ b/Makefile @@ -28,8 +28,11 @@ check: fmt: cargo fmt --all -- --check +# Libraries on the host; programs (no_std, they link only for RISC-V) for +# their target, as `build` builds them. The adapter is `kernel-clippy`'s. clippy: - cargo clippy --workspace -- -D warnings + cargo clippy --workspace --exclude adapter-riscv --lib -- -D warnings + cargo clippy --target $(RISCV_TARGET) --release $(PROGRAMS) -- -D warnings test: cargo test --workspace @@ -48,14 +51,15 @@ kani-kernel: kani: kani-types kani-domain kani-kernel +PROGRAMS = -p init -p echo -p sleep -p snake \ + -p display-qemu -p input-qemu -p storage-qemu \ + -p log-server -p permission-manager -p session-server -p smptest -p spawntest -p hello \ + -p terminal-server -p shell -p cat -p ls -p counter -p gatekeeper + # Programs first: the kernel image packs init and storage (see the # adapter's build.rs). build: - cargo build --target $(RISCV_TARGET) --release \ - -p init -p echo -p sleep -p snake \ - -p display-qemu -p input-qemu -p storage-qemu \ - -p log-server -p permission-manager -p session-server -p smptest -p spawntest -p hello \ - -p terminal-server -p shell -p cat -p ls -p counter -p gatekeeper + cargo build --target $(RISCV_TARGET) --release $(PROGRAMS) cargo build --target $(RISCV_TARGET) --release -p adapter-riscv # The keystore holds the owner's sealed keys: made once, never rebuilt. diff --git a/crates/apps/snake/src/game.rs b/crates/apps/snake/src/game.rs index 788d3f6..5618696 100644 --- a/crates/apps/snake/src/game.rs +++ b/crates/apps/snake/src/game.rs @@ -44,6 +44,12 @@ pub struct Snake { rng_state: u32, } +impl Default for Snake { + fn default() -> Self { + Self::new() + } +} + impl Snake { pub fn new() -> Self { let start = Position { x: GRID_WIDTH / 2, y: GRID_HEIGHT / 2 }; diff --git a/crates/apps/snake/src/main.rs b/crates/apps/snake/src/main.rs index ea79139..2c4edce 100644 --- a/crates/apps/snake/src/main.rs +++ b/crates/apps/snake/src/main.rs @@ -61,8 +61,7 @@ fn main() { loop { let count = renderer::render(&snake, &mut commands); - for i in 0..count { - let cmd = &commands[i]; + for cmd in &commands[..count] { draw_rect(cmd.x, cmd.y, cmd.w, cmd.h, cmd.color); } flush(); diff --git a/crates/drivers/framebuffer/virtio/src/lib.rs b/crates/drivers/framebuffer/virtio/src/lib.rs index 9113a8e..d5d25a8 100644 --- a/crates/drivers/framebuffer/virtio/src/lib.rs +++ b/crates/drivers/framebuffer/virtio/src/lib.rs @@ -148,7 +148,8 @@ impl Framebuffer for VirtioFramebuffer { fn flush(&mut self) { let w = self.width.raw() as u32; let h = self.height.raw() as u32; - gpu::transfer_to_host(&self.mmio, &self.queue, &self.dma, RESOURCE_ID, 0, 0, w, h); - gpu::resource_flush(&self.mmio, &self.queue, &self.dma, RESOURCE_ID, 0, 0, w, h); + let whole = gpu::Rect { x: 0, y: 0, w, h }; + gpu::transfer_to_host(&self.mmio, &self.queue, &self.dma, RESOURCE_ID, whole); + gpu::resource_flush(&self.mmio, &self.queue, &self.dma, RESOURCE_ID, whole); } } diff --git a/crates/hw-virtio/src/gpu.rs b/crates/hw-virtio/src/gpu.rs index 37e27b8..ae72ed9 100644 --- a/crates/hw-virtio/src/gpu.rs +++ b/crates/hw-virtio/src/gpu.rs @@ -56,18 +56,27 @@ pub fn set_scanout(mmio: &impl MmioAccess, queue: &VirtioQueue, dma: &GpuDmaAddr submit_cmd(mmio, queue, dma, 48) } -pub fn transfer_to_host(mmio: &impl MmioAccess, queue: &VirtioQueue, dma: &GpuDmaAddrs, resource_id: u32, x: u32, y: u32, w: u32, h: u32) -> bool { +/// A rectangle of a resource, in pixels. +#[derive(Clone, Copy, Debug)] +pub struct Rect { + pub x: u32, + pub y: u32, + pub w: u32, + pub h: u32, +} + +pub fn transfer_to_host(mmio: &impl MmioAccess, queue: &VirtioQueue, dma: &GpuDmaAddrs, resource_id: u32, rect: Rect) -> bool { write_cmd_header(&dma.cmd, 0x0105); - put_rect(&dma.cmd, x, y, w, h); + put_rect(&dma.cmd, rect); // Offset into the resource's memory, then the resource id. dma.cmd.write(BODY + 16, 0u64); dma.cmd.write(BODY + 24, resource_id); submit_cmd(mmio, queue, dma, 56) } -pub fn resource_flush(mmio: &impl MmioAccess, queue: &VirtioQueue, dma: &GpuDmaAddrs, resource_id: u32, x: u32, y: u32, w: u32, h: u32) -> bool { +pub fn resource_flush(mmio: &impl MmioAccess, queue: &VirtioQueue, dma: &GpuDmaAddrs, resource_id: u32, rect: Rect) -> bool { write_cmd_header(&dma.cmd, 0x0104); - put_rect(&dma.cmd, x, y, w, h); + put_rect(&dma.cmd, rect); dma.cmd.write(BODY + 16, resource_id); submit_cmd(mmio, queue, dma, 48) } @@ -77,11 +86,11 @@ fn write_cmd_header(cmd: &Window, cmd_type: u32) { cmd.write(TYPE, cmd_type); } -fn put_rect(cmd: &Window, x: u32, y: u32, w: u32, h: u32) { - cmd.write(RECT_X, x); - cmd.write(RECT_Y, y); - cmd.write(RECT_W, w); - cmd.write(RECT_H, h); +fn put_rect(cmd: &Window, r: Rect) { + cmd.write(RECT_X, r.x); + cmd.write(RECT_Y, r.y); + cmd.write(RECT_W, r.w); + cmd.write(RECT_H, r.h); } pub fn get_display_info(mmio: &impl MmioAccess, queue: &VirtioQueue, dma: &GpuDmaAddrs) -> Option<(u32, u32)> { diff --git a/crates/init/src/factory.rs b/crates/init/src/factory.rs index 1285ee9..9fe1c0b 100644 --- a/crates/init/src/factory.rs +++ b/crates/init/src/factory.rs @@ -43,16 +43,30 @@ impl Path { } } -/// Up to `BATCH` entries of `dir`: names and whether each is a folder. -fn entries(fs: &mut Storage, dir: &Path) -> Option<([([u8; NAME], usize, bool); BATCH], usize)> { - let mut out = [([0u8; NAME], 0, false); BATCH]; +/// One thing in a folder. +#[derive(Clone, Copy)] +struct Entry { + name: [u8; NAME], + len: usize, + is_dir: bool, +} + +impl Entry { + fn name(&self) -> &[u8] { + &self.name[..self.len] + } +} + +/// Up to `BATCH` entries of `dir`. +fn entries(fs: &mut Storage, dir: &Path) -> Option<([Entry; BATCH], usize)> { + let mut out = [Entry { name: [0; NAME], len: 0, is_dir: false }; BATCH]; let mut n = 0; fs.list_dir(dir.as_bytes(), |e| { let name = e.name(); if name != b"." && name != b".." && n < BATCH { - out[n].0[..name.len()].copy_from_slice(name); - out[n].1 = name.len(); - out[n].2 = e.is_dir; + out[n].name[..name.len()].copy_from_slice(name); + out[n].len = name.len(); + out[n].is_dir = e.is_dir; n += 1; } }) @@ -83,9 +97,9 @@ fn copy_tree(fs: &mut Storage, from: &Path, to: &Path, buf: &mut [u8]) -> Result // Nothing shipped for this area. None => return Ok(()), }; - for (name, len, is_dir) in &list[..n] { - let (src, dst) = (from.join(&name[..*len]).ok_or("path too long")?, to.join(&name[..*len]).ok_or("path too long")?); - if *is_dir { + for entry in &list[..n] { + let (src, dst) = (from.join(entry.name()).ok_or("path too long")?, to.join(entry.name()).ok_or("path too long")?); + if entry.is_dir { fs.mkdir(dst.as_bytes()).map_err(|_| "cannot make a folder")?; copy_tree(fs, &src, &dst, buf)?; } else { diff --git a/crates/init/src/load.rs b/crates/init/src/load.rs index 0479753..cbae7b0 100644 --- a/crates/init/src/load.rs +++ b/crates/init/src/load.rs @@ -54,7 +54,7 @@ pub(crate) fn load_binary( let page_start = segment.vaddr & !0xFFF; let offset_in_page = segment.vaddr & 0xFFF; let total_size = offset_in_page + segment.mem_size; - let seg_pages = (total_size + PAGE_SIZE - 1) / PAGE_SIZE; + let seg_pages = total_size.div_ceil(PAGE_SIZE); let page_count = PageCount::new(u16::try_from(seg_pages).ok()?)?; let local = libkos::window::request(page_count)?; diff --git a/crates/keystore/src/lib.rs b/crates/keystore/src/lib.rs index 3912fb9..5e10641 100644 --- a/crates/keystore/src/lib.rs +++ b/crates/keystore/src/lib.rs @@ -21,6 +21,7 @@ mod user; mod tests; pub use record::{ + Account, Copies, Entry, KdfParams, Outcome, RECORD_SIZE, Record, Refused, SLOTS, Session, State, }; pub use user::{Name, Role, User, UserId}; diff --git a/crates/keystore/src/record.rs b/crates/keystore/src/record.rs index c03f93e..1504d72 100644 --- a/crates/keystore/src/record.rs +++ b/crates/keystore/src/record.rs @@ -154,6 +154,15 @@ fn parse_user(role: u8, id: &[u8], name: &[u8]) -> Option { }) } +/// A user about to be added: who, and the passcodes that will open their +/// slot (and, if given, their duress slot). +pub struct Account<'a> { + pub name: Name, + pub role: Role, + pub passcode: &'a [u8], + pub duress: Option<&'a [u8]>, +} + impl Record { fn name_tag(&self, name: &Name) -> [u8; NAME_TAG] { let mut m = ::new_from_slice(&self.pepper) @@ -273,7 +282,7 @@ impl Record { admin: Some(admin), }; let (record, user) = first - .add_user(&owner, name, Role::Owner, passcode, duress, memory, rng) + .add_user(&owner, Account { name, role: Role::Owner, passcode, duress }, memory, rng) .ok()?; let session = record.unlock(name.as_bytes(), passcode, memory); let _ = user; @@ -371,16 +380,8 @@ impl Record { } /// An owner adds a user; the new record and the user. - pub fn add_user( - &self, - by: &Session, - name: Name, - role: Role, - passcode: &[u8], - duress: Option<&[u8]>, - memory: &mut [Block], - rng: &mut impl Random, - ) -> Result<(Self, User), Refused> { + pub fn add_user(&self, by: &Session, account: Account, memory: &mut [Block], rng: &mut impl Random) -> Result<(Self, User), Refused> { + let Account { name, role, passcode, duress } = account; let admin = by.admin.clone().ok_or(Refused::NotOwner)?; let mut entries = self.entries(&admin).ok_or(Refused::Failed)?; if entries.iter().flatten().any(|e| e.user.name == name) { @@ -467,10 +468,10 @@ impl Record { return Err(Refused::LastOwner); } let mut r = self.next(|_| {}); - for i in 0..SLOTS { - if entries[i].is_some_and(|e| e.user.id == gone.id) { - r.slots[i] = Slot(noise(rng).ok_or(Refused::Failed)?); - entries[i] = None; + for (entry, slot) in entries.iter_mut().zip(r.slots.iter_mut()) { + if entry.is_some_and(|e| e.user.id == gone.id) { + *slot = Slot(noise(rng).ok_or(Refused::Failed)?); + *entry = None; } } if !r.seal_directory(&admin, &entries, rng) { diff --git a/crates/keystore/src/tests.rs b/crates/keystore/src/tests.rs index dd2f62b..eefe336 100644 --- a/crates/keystore/src/tests.rs +++ b/crates/keystore/src/tests.rs @@ -79,15 +79,7 @@ fn users_have_their_own_keys_and_may_even_share_a_passcode() { let (r, owner) = setup(None, 2); let mut rng = Counter(40); let (r, work) = r - .add_user( - &owner, - name("work"), - Role::Standard, - b"1234", - None, - &mut memory(), - &mut rng, - ) + .add_user(&owner, Account { name: name("work"), role: Role::Standard, passcode: b"1234", duress: None }, &mut memory(), &mut rng) .unwrap(); let w = signed_in(&r, "work", b"1234").unwrap(); let g = signed_in(&r, "gabriel", b"1234").unwrap(); @@ -105,15 +97,7 @@ fn users_have_their_own_keys_and_may_even_share_a_passcode() { "not even hidden in their slot" ); assert_eq!( - r.add_user( - &w, - name("x"), - Role::Standard, - b"9", - None, - &mut memory(), - &mut rng - ) + r.add_user(&w, Account { name: name("x"), role: Role::Standard, passcode: b"9", duress: None }, &mut memory(), &mut rng) .err(), Some(Refused::NotOwner) ); @@ -125,26 +109,10 @@ fn owners_see_and_manage_the_users() { let (r, owner) = setup(Some(b"0000"), 3); let mut rng = Counter(50); let (r, _) = r - .add_user( - &owner, - name("work"), - Role::Standard, - b"5678", - Some(b"8765"), - &mut memory(), - &mut rng, - ) + .add_user(&owner, Account { name: name("work"), role: Role::Standard, passcode: b"5678", duress: Some(b"8765") }, &mut memory(), &mut rng) .unwrap(); let (r, second) = r - .add_user( - &owner, - name("anna"), - Role::Owner, - b"4321", - None, - &mut memory(), - &mut rng, - ) + .add_user(&owner, Account { name: name("anna"), role: Role::Owner, passcode: b"4321", duress: None }, &mut memory(), &mut rng) .unwrap(); let names: Vec<_> = r .users(&owner) @@ -155,15 +123,7 @@ fn owners_see_and_manage_the_users() { .collect(); assert_eq!(names.len(), 3, "duress slots are not listed: {names:?}"); assert_eq!( - r.add_user( - &owner, - name("work"), - Role::Standard, - b"x", - None, - &mut memory(), - &mut rng - ) + r.add_user(&owner, Account { name: name("work"), role: Role::Standard, passcode: b"x", duress: None }, &mut memory(), &mut rng) .err(), Some(Refused::NameTaken) ); @@ -205,15 +165,7 @@ fn slots_run_out() { let mut added = 0; for i in 0..SLOTS { let n = std::format!("u{i}"); - match r.add_user( - &owner, - name(&n), - Role::Standard, - b"pass", - None, - &mut memory(), - &mut rng, - ) { + match r.add_user(&owner, Account { name: name(&n), role: Role::Standard, passcode: b"pass", duress: None }, &mut memory(), &mut rng) { Ok((next, _)) => { r = next; added += 1; diff --git a/crates/libkos/src/alloc_impl.rs b/crates/libkos/src/alloc_impl.rs index ca5c16e..6346c17 100644 --- a/crates/libkos/src/alloc_impl.rs +++ b/crates/libkos/src/alloc_impl.rs @@ -1,6 +1,8 @@ use core::alloc::{GlobalAlloc, Layout}; use core::cell::UnsafeCell; +use core::ops::{Deref, DerefMut}; use core::ptr; +use core::sync::atomic::{AtomicBool, Ordering}; const PAGE_SIZE: usize = 4096; @@ -10,6 +12,8 @@ struct FreeBlock { } pub struct KosAllocator { + /// A program's threads share the heap: one at a time in the free list. + locked: AtomicBool, inner: UnsafeCell, } @@ -24,12 +28,45 @@ unsafe impl Sync for KosAllocator {} impl KosAllocator { pub const fn new() -> Self { Self { + locked: AtomicBool::new(false), inner: UnsafeCell::new(AllocatorInner { free_list: ptr::null_mut() }), } } - fn inner_mut(&self) -> &mut AllocatorInner { - unsafe { &mut *self.inner.get() } + fn lock(&self) -> Locked<'_> { + while self.locked.compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed).is_err() { + core::hint::spin_loop(); + } + Locked(self) + } +} + +impl Default for KosAllocator { + fn default() -> Self { + Self::new() + } +} + +/// The free list, held until dropped. +struct Locked<'a>(&'a KosAllocator); + +impl Deref for Locked<'_> { + type Target = AllocatorInner; + fn deref(&self) -> &AllocatorInner { + // Only one `Locked` exists at a time. + unsafe { &*self.0.inner.get() } + } +} + +impl DerefMut for Locked<'_> { + fn deref_mut(&mut self) -> &mut AllocatorInner { + unsafe { &mut *self.0.inner.get() } + } +} + +impl Drop for Locked<'_> { + fn drop(&mut self) { + self.0.locked.store(false, Ordering::Release); } } @@ -103,7 +140,7 @@ impl AllocatorInner { unsafe impl GlobalAlloc for KosAllocator { unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - let inner = self.inner_mut(); + let mut inner = self.lock(); let size = layout.size().max(core::mem::size_of::()); let align = layout.align(); @@ -113,7 +150,7 @@ unsafe impl GlobalAlloc for KosAllocator { } // Alignment can cost up to `align` bytes of the block. - let pages_needed = (size + align + PAGE_SIZE - 1) / PAGE_SIZE; + let pages_needed = (size + align).div_ceil(PAGE_SIZE); let block = inner.request_pages(pages_needed); if block.is_null() { return ptr::null_mut(); @@ -124,7 +161,7 @@ unsafe impl GlobalAlloc for KosAllocator { } unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { - let inner = self.inner_mut(); + let mut inner = self.lock(); let size = layout.size().max(core::mem::size_of::()); inner.add_to_free_list(ptr, size); } diff --git a/crates/libkos/src/syscall/process.rs b/crates/libkos/src/syscall/process.rs index 1c0344a..431eceb 100644 --- a/crates/libkos/src/syscall/process.rs +++ b/crates/libkos/src/syscall/process.rs @@ -12,12 +12,17 @@ use types::time::Ticks; pub fn exit() -> ! { let _ = call0(SYS_EXIT); - loop {} + // The kernel does not return from an exit. + loop { + core::hint::spin_loop(); + } } pub fn exit_thread() -> ! { let _ = call0(SYS_EXIT_THREAD); - loop {} + loop { + core::hint::spin_loop(); + } } pub fn yield_now() { @@ -28,7 +33,9 @@ pub fn yield_now() { /// call fails and this spins, since there is nothing sensible to return. pub fn halt(control: CapSlot) -> ! { let _ = raw(SYS_HALT, [control.value() as usize, 0, 0, 0, 0, 0]); - loop {} + loop { + yield_now(); + } } pub fn get_time() -> Ticks { diff --git a/crates/servers/gatekeeper/src/flow.rs b/crates/servers/gatekeeper/src/flow.rs index 78af43a..932b79f 100644 --- a/crates/servers/gatekeeper/src/flow.rs +++ b/crates/servers/gatekeeper/src/flow.rs @@ -2,7 +2,7 @@ //! randomness, and the owner (`Prompt`). No kernel, no hardware: tested on //! the host. -use keystore::{Block, Copies, KdfParams, Key, Name, Outcome, RECORD_SIZE, Random, Record, Refused, Role, SLOTS, Session, User, UserId}; +use keystore::{Account, Block, Copies, KdfParams, Key, Name, Outcome, RECORD_SIZE, Random, Record, Refused, Role, SLOTS, Session, User, UserId}; use zeroize::Zeroize; /// The keystore device: the record's two copies. @@ -228,7 +228,7 @@ fn manage(ks: &mut impl Keystore, rng: &mut impl Random, prompt: &mut impl Promp let (mut real, mut duress) = (Secret::new(), Secret::new()); ask_passcodes(prompt, &mut real, &mut duress)?; let duress = (duress.len > 0).then_some(duress.as_bytes()); - record.add_user(session, name, role, real.as_bytes(), duress, memory, rng).map(|(r, _)| r) + record.add_user(session, Account { name, role, passcode: real.as_bytes(), duress }, memory, rng).map(|(r, _)| r) } b"r" => { let name = ask_name(prompt, "Remove whom: ")?; diff --git a/crates/servers/input-server/src/adapters/mock.rs b/crates/servers/input-server/src/adapters/mock.rs index 57dc946..1fdd078 100644 --- a/crates/servers/input-server/src/adapters/mock.rs +++ b/crates/servers/input-server/src/adapters/mock.rs @@ -6,6 +6,12 @@ pub struct MockInputDevice { tail: usize, } +impl Default for MockInputDevice { + fn default() -> Self { + Self::new() + } +} + impl MockInputDevice { pub fn new() -> Self { Self { diff --git a/crates/servers/log-server/src/server.rs b/crates/servers/log-server/src/server.rs index 0c0ead8..978c9e4 100644 --- a/crates/servers/log-server/src/server.rs +++ b/crates/servers/log-server/src/server.rs @@ -18,6 +18,12 @@ pub struct LogServer { out: O, } +impl Default for LogServer { + fn default() -> Self { + Self::new() + } +} + impl LogServer { /// Text goes nowhere. pub fn new() -> Self { diff --git a/crates/servers/storage-server/src/adapters/mock_fs.rs b/crates/servers/storage-server/src/adapters/mock_fs.rs index 5343efc..f3bfe6f 100644 --- a/crates/servers/storage-server/src/adapters/mock_fs.rs +++ b/crates/servers/storage-server/src/adapters/mock_fs.rs @@ -44,16 +44,21 @@ impl MockFileSystem { fn find_by_name(&self, path: &[u8]) -> Option { for i in 0..MAX_FILES { - if let Some(entry) = &self.files[i] { - if entry.name == *path { + if let Some(entry) = &self.files[i] + && entry.name == *path { return Some(i); } - } } None } } +impl Default for MockFileSystem { + fn default() -> Self { + Self::new() + } +} + impl FileSystem for MockFileSystem { fn writable(&self) -> bool { !self.read_only diff --git a/crates/servers/storage-server/src/filesystem.rs b/crates/servers/storage-server/src/filesystem.rs index 57ef72a..5287bb1 100644 --- a/crates/servers/storage-server/src/filesystem.rs +++ b/crates/servers/storage-server/src/filesystem.rs @@ -39,6 +39,10 @@ impl FileName { pub fn len(&self) -> usize { self.len as usize } + + pub fn is_empty(&self) -> bool { + self.len == 0 + } } impl PartialEq<[u8]> for FileName { diff --git a/crates/servers/storage-server/src/fs/ext4/dir.rs b/crates/servers/storage-server/src/fs/ext4/dir.rs index 848ea9f..4ff7ccf 100644 --- a/crates/servers/storage-server/src/fs/ext4/dir.rs +++ b/crates/servers/storage-server/src/fs/ext4/dir.rs @@ -37,11 +37,10 @@ pub fn find_entry( let name_len = block_buf[pos + 6] as usize; if rec_len == 0 { break; } - if entry_inode != 0 && name_len == name.len() { - if &block_buf[pos + 8..pos + 8 + name_len] == name { + if entry_inode != 0 && name_len == name.len() + && &block_buf[pos + 8..pos + 8 + name_len] == name { return Some(entry_inode); } - } pos += rec_len; } } @@ -147,8 +146,8 @@ pub fn remove_entry( let name_len = block_buf[pos + 6] as usize; if rec_len == 0 { break; } - if entry_inode != 0 && name_len == name.len() { - if &block_buf[pos + 8..pos + 8 + name_len] == name { + if entry_inode != 0 && name_len == name.len() + && &block_buf[pos + 8..pos + 8 + name_len] == name { if let Some(pp) = prev_pos { let prev_rec = read_u16(&block_buf, pp + 4) as usize; write_u16(&mut block_buf, pp + 4, (prev_rec + rec_len) as u16); @@ -158,7 +157,6 @@ pub fn remove_entry( write_block(device, phys, spb, &block_buf); return Some(entry_inode); } - } prev_pos = Some(pos); pos += rec_len; } diff --git a/crates/servers/storage-server/src/fs/ext4/mod.rs b/crates/servers/storage-server/src/fs/ext4/mod.rs index 2a7c1bc..b453293 100644 --- a/crates/servers/storage-server/src/fs/ext4/mod.rs +++ b/crates/servers/storage-server/src/fs/ext4/mod.rs @@ -131,7 +131,9 @@ impl FileSystem for Ext4 { done += chunk; } - self.open_files[handle.raw() as usize].as_mut().map(|f| f.offset += done); + if let Some(f) = self.open_files[handle.raw() as usize].as_mut() { + f.offset += done; + } Some(done) } @@ -204,13 +206,12 @@ impl FileSystem for Ext4 { fn close(&mut self, handle: FileHandle) { if handle.raw() as usize >= MAX_OPEN_FILES { return; } - if let Some(file) = self.open_files[handle.raw() as usize].take() { - if let Some(mut inode) = self.read_inode(file.inode_num) { + if let Some(file) = self.open_files[handle.raw() as usize].take() + && let Some(mut inode) = self.read_inode(file.inode_num) { inode.size = file.size as u64; inode.block_data = file.block_data; self.write_inode(file.inode_num, &inode); } - } } fn list_dir(&mut self, path: &[u8], entries: &mut [DirEntry]) -> Option { @@ -222,14 +223,13 @@ impl FileSystem for Ext4 { let inode = self.read_inode(dir_inode_num)?; let count = dir::list_entries(&mut self.device, &self.sb, &inode, entries)?; - for i in 0..count { - if !entries[i].is_dir { - let name = entries[i].name; - if let Some(child_ino) = dir::find_entry(&mut self.device, &self.sb, &inode, name.as_bytes()) { - if let Some(child) = self.read_inode(child_ino) { - entries[i].size = child.size as usize; + for entry in entries.iter_mut().take(count) { + if !entry.is_dir { + let name = entry.name; + if let Some(child_ino) = dir::find_entry(&mut self.device, &self.sb, &inode, name.as_bytes()) + && let Some(child) = self.read_inode(child_ino) { + entry.size = child.size as usize; } - } } } Some(count) @@ -279,11 +279,10 @@ impl FileSystem for Ext4 { None => return false, }; - if let Some(child_inode) = self.read_inode(child_inode_num) { - if child_inode.is_dir() { + if let Some(child_inode) = self.read_inode(child_inode_num) + && child_inode.is_dir() { return false; } - } let parent_inode = match self.read_inode(parent_inode_num) { Some(i) => i, @@ -299,11 +298,10 @@ impl FileSystem for Ext4 { self.clear_inode(child_inode_num); self.free_inode(child_inode_num); for slot in self.open_files.iter_mut() { - if let Some(f) = slot { - if f.inode_num == child_inode_num { + if let Some(f) = slot + && f.inode_num == child_inode_num { *slot = None; } - } } true } diff --git a/crates/servers/storage-server/src/grants.rs b/crates/servers/storage-server/src/grants.rs index d71b540..144d7be 100644 --- a/crates/servers/storage-server/src/grants.rs +++ b/crates/servers/storage-server/src/grants.rs @@ -102,3 +102,9 @@ impl Grants { } } } + +impl Default for Grants { + fn default() -> Self { + Self::new() + } +}