diff --git a/kernel-rs/src/arena.rs b/kernel-rs/src/arena.rs index 688d70bc0..632cda78f 100644 --- a/kernel-rs/src/arena.rs +++ b/kernel-rs/src/arena.rs @@ -16,9 +16,6 @@ pub trait Arena: Sized { /// The guard type for arena. type Guard<'s>; - /// Creates handle from condition without increasing reference count. - fn unforget bool>(&self, c: C) -> Option; - /// Find or alloc. fn find_or_alloc bool, N: FnOnce(&mut Self::Data)>( &self, @@ -122,21 +119,6 @@ impl Arena for Spinlock; type Guard<'s> = SpinlockGuard<'s, ArrayArena>; - fn unforget bool>(&self, c: C) -> Option { - let mut this = self.lock(); - - for entry in &mut this.entries { - if entry.refcnt != 0 && c(&entry.data) { - return Some(Self::Handle { - ptr: entry, - _marker: PhantomData, - }); - } - } - - None - } - fn find_or_alloc bool, N: FnOnce(&mut Self::Data)>( &self, c: C, @@ -283,29 +265,6 @@ impl Arena for Spinlock; type Guard<'s> = SpinlockGuard<'s, MruArena>; - fn unforget bool>(&self, c: C) -> Option { - let this = self.lock(); - - // Is the block already cached? - let mut list_entry = this.head.next(); - while list_entry as *const _ != &this.head as *const _ { - let entry = unsafe { - &mut *((list_entry as *const _ as usize - Self::LIST_ENTRY_OFFSET) - as *mut MruEntry) - }; - if c(&entry.data) { - debug_assert!(entry.refcnt != 0); - return Some(Self::Handle { - ptr: entry, - _marker: PhantomData, - }); - } - list_entry = list_entry.next(); - } - - None - } - fn find_or_alloc bool, N: FnOnce(&mut Self::Data)>( &self, c: C, @@ -453,12 +412,6 @@ impl> Arena for T { type Handle = Rc; type Guard<'s> = ::Guard<'s>; - fn unforget bool>(&self, c: C) -> Option { - let tag = self.clone(); - let inner = ManuallyDrop::new(tag.deref().unforget(c)?); - Some(Self::Handle { tag, inner }) - } - fn find_or_alloc bool, N: FnOnce(&mut Self::Data)>( &self, c: C, diff --git a/kernel-rs/src/bio.rs b/kernel-rs/src/bio.rs index ae9ce8837..97e8b3638 100644 --- a/kernel-rs/src/bio.rs +++ b/kernel-rs/src/bio.rs @@ -20,7 +20,7 @@ use crate::{ }; use array_macro::array; -use core::mem; +use core::mem::{self, ManuallyDrop}; use core::ops::{Deref, DerefMut}; pub struct BufEntry { @@ -93,48 +93,51 @@ impl BufInner { pub type Bcache = Spinlock>; +/// We can consider it as BufEntry. pub type BufUnlocked<'s> = Rc; +/// # Safety +/// +/// (inner: BufEntry).inner is locked. pub struct Buf<'s> { - inner: BufUnlocked<'s>, -} - -impl<'s> Deref for Buf<'s> { - type Target = BufUnlocked<'s>; - - fn deref(&self) -> &Self::Target { - &self.inner - } -} - -impl DerefMut for Buf<'_> { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.inner - } + inner: ManuallyDrop>, } impl<'s> Buf<'s> { pub fn deref_inner(&self) -> &BufInner { + // It is safe becuase inner.inner is locked. unsafe { self.inner.inner.get_mut_unchecked() } } pub fn deref_inner_mut(&mut self) -> &mut BufInner { + // It is safe becuase inner.inner is locked and &mut self is exclusive. unsafe { self.inner.inner.get_mut_unchecked() } } - pub fn unlock(self) -> BufUnlocked<'s> { - unsafe { - self.inner.inner.unlock(); - mem::transmute(self) - } + pub fn unlock(mut self) -> BufUnlocked<'s> { + // It is safe because this method consumes self and self.inner will not + // be used again. + let inner = unsafe { ManuallyDrop::take(&mut self.inner) }; + // It is safe because this method consumes self. + unsafe { inner.inner.unlock() }; + mem::forget(self); + inner + } +} + +impl Deref for Buf<'_> { + type Target = BufEntry; + + fn deref(&self) -> &Self::Target { + &self.inner } } impl Drop for Buf<'_> { fn drop(&mut self) { - unsafe { - self.inner.inner.unlock(); - } + // It is safe because self will be dropped and self.inner will not be + // used again. + unsafe { ManuallyDrop::take(&mut self.inner).inner.unlock() }; } } @@ -161,26 +164,13 @@ impl Bcache { unsafe { Rc::from_unchecked(self, inner) } } - - /// Retrieves BufUnlocked without increasing reference count. - pub fn buf_unforget(&self, dev: u32, blockno: u32) -> Option> { - let inner = self.unforget(|buf| buf.dev == dev && buf.blockno == blockno)?; - - Some(unsafe { Rc::from_unchecked(self, inner) }) - } } impl<'s> BufUnlocked<'s> { pub fn lock(self) -> Buf<'s> { mem::forget(self.inner.lock()); - Buf { inner: self } - } - - pub fn deref_inner(&self) -> &BufInner { - unsafe { self.inner.get_mut_unchecked() } - } - - pub fn deref_mut_inner(&mut self) -> &mut BufInner { - unsafe { self.inner.get_mut_unchecked() } + Buf { + inner: ManuallyDrop::new(self), + } } } diff --git a/kernel-rs/src/fs/inode.rs b/kernel-rs/src/fs/inode.rs index e6400ef0b..bba5d06d3 100644 --- a/kernel-rs/src/fs/inode.rs +++ b/kernel-rs/src/fs/inode.rs @@ -314,7 +314,7 @@ impl InodeGuard<'_> { // * dip is inside bp.data. // * dip will not be read. let dip = unsafe { - &mut *(bp.deref_mut_inner().data.as_mut_ptr() as *mut Dinode) + &mut *(bp.deref_inner_mut().data.as_mut_ptr() as *mut Dinode) .add(self.inum as usize % IPB) }; @@ -342,11 +342,11 @@ impl InodeGuard<'_> { } } - dip.nlink = inner.nlink; - dip.size = inner.size; - dip.addr_direct.copy_from_slice(&inner.addr_direct); - dip.addr_indirect = inner.addr_indirect; - unsafe { tx.write(bp) }; + (*dip).nlink = inner.nlink; + (*dip).size = inner.size; + (*dip).addr_direct.copy_from_slice(&inner.addr_direct); + (*dip).addr_indirect = inner.addr_indirect; + tx.write(bp); } /// Truncate inode (discard contents). @@ -355,7 +355,7 @@ impl InodeGuard<'_> { let dev = self.dev; for addr in &mut self.deref_inner_mut().addr_direct { if *addr != 0 { - unsafe { tx.bfree(dev, *addr) }; + tx.bfree(dev, *addr); *addr = 0; } } @@ -366,15 +366,15 @@ impl InodeGuard<'_> { .disk .read(dev, self.deref_inner().addr_indirect); // It is safe because u32 does not have internal structure. - let (prefix, data, _) = unsafe { bp.deref_mut_inner().data.align_to_mut::() }; + let (prefix, data, _) = unsafe { bp.deref_inner_mut().data.align_to_mut::() }; debug_assert_eq!(prefix.len(), 0, "itrunc: Buf data unaligned"); for a in data { if *a != 0 { - unsafe { tx.bfree(dev, *a) }; + tx.bfree(dev, *a); } } drop(bp); - unsafe { tx.bfree(dev, self.deref_inner().addr_indirect) }; + tx.bfree(dev, self.deref_inner().addr_indirect); self.deref_inner_mut().addr_indirect = 0 } @@ -449,14 +449,14 @@ impl InodeGuard<'_> { } let mut tot: u32 = 0; while tot < n { - let mut bp = kernel() + let bp = kernel() .file_system .disk .read(self.dev, self.bmap(off as usize / BSIZE)); let m = core::cmp::min(n - tot, BSIZE as u32 - off % BSIZE as u32); let begin = (off % BSIZE as u32) as usize; let end = begin + m as usize; - f(tot, &bp.deref_mut_inner().data[begin..end])?; + f(tot, &bp.deref_inner().data[begin..end])?; tot += m; off += m; } @@ -563,12 +563,10 @@ impl InodeGuard<'_> { let m = core::cmp::min(n - tot, BSIZE as u32 - off % BSIZE as u32); let begin = (off % BSIZE as u32) as usize; let end = begin + m as usize; - if f(tot, &mut bp.deref_mut_inner().data[begin..end]).is_err() { + if f(tot, &mut bp.deref_inner_mut().data[begin..end]).is_err() { break; } - unsafe { - tx.write(bp); - } + tx.write(bp); tot += m; off += m; } @@ -606,7 +604,7 @@ impl InodeGuard<'_> { if bn < NDIRECT { let mut addr = inner.addr_direct[bn]; if addr == 0 { - addr = unsafe { tx_opt.expect("bmap: out of range").balloc(self.dev) }; + addr = tx_opt.expect("bmap: out of range").balloc(self.dev); self.deref_inner_mut().addr_direct[bn] = addr; } addr @@ -616,19 +614,19 @@ impl InodeGuard<'_> { let mut indirect = inner.addr_indirect; if indirect == 0 { - indirect = unsafe { tx_opt.expect("bmap: out of range").balloc(self.dev) }; + indirect = tx_opt.expect("bmap: out of range").balloc(self.dev); self.deref_inner_mut().addr_indirect = indirect; } let mut bp = kernel().file_system.disk.read(self.dev, indirect); - let (prefix, data, _) = unsafe { bp.deref_mut_inner().data.align_to_mut::() }; + let (prefix, data, _) = unsafe { bp.deref_inner_mut().data.align_to_mut::() }; debug_assert_eq!(prefix.len(), 0, "bmap: Buf data unaligned"); let mut addr = data[bn]; if addr == 0 { let tx = tx_opt.expect("bmap: out of range"); - addr = unsafe { tx.balloc(self.dev) }; + addr = tx.balloc(self.dev); data[bn] = addr; - unsafe { tx.write(bp) }; + tx.write(bp); } addr } @@ -706,7 +704,7 @@ impl Inode { // It is safe because dip is inside bp.data. let dip = unsafe { - (bp.deref_mut_inner().data.as_mut_ptr() as *mut Dinode) + (bp.deref_inner_mut().data.as_mut_ptr() as *mut Dinode) .add(self.inum as usize % IPB) }; // It is safe because i16 does not have internal structure. @@ -809,7 +807,7 @@ impl Itable { const_assert!(mem::align_of::() % mem::align_of::() == 0); // It is safe because dip is inside bp.data. let dip = unsafe { - (bp.deref_mut_inner().data.as_mut_ptr() as *mut Dinode).add(inum as usize % IPB) + (bp.deref_inner_mut().data.as_mut_ptr() as *mut Dinode).add(inum as usize % IPB) }; // It is safe because i16 does not have internal structure. let t = unsafe { *(dip as *const i16) }; @@ -833,7 +831,7 @@ impl Itable { } // mark it allocated on the disk - unsafe { tx.write(bp) }; + tx.write(bp); return self.get_inode(dev, inum); } } diff --git a/kernel-rs/src/fs/log.rs b/kernel-rs/src/fs/log.rs index db8b606eb..02b118fea 100644 --- a/kernel-rs/src/fs/log.rs +++ b/kernel-rs/src/fs/log.rs @@ -21,11 +21,12 @@ //! ... //! Log appends are synchronous. use arrayvec::ArrayVec; -use core::{mem, ptr}; +use core::mem; use itertools::*; use static_assertions::const_assert; use crate::{ + bio::BufData, bio::{Buf, BufUnlocked}, kernel::kernel, param::{BSIZE, LOGSIZE, MAXOPBLOCKS}, @@ -44,7 +45,7 @@ pub struct Log { committing: bool, /// Contents of the header block, used to keep track in memory of logged block# before commit. - lh: ArrayVec<[BufUnlocked<'static>; LOGSIZE]>, + bufs: ArrayVec<[BufUnlocked<'static>; LOGSIZE]>, } /// Contents of the header block, used for the on-disk header block. @@ -53,9 +54,6 @@ struct LogHeader { block: [u32; LOGSIZE], } -// `LogHeader` must be fit in a block. -const_assert!(mem::size_of::() < BSIZE); - impl Log { pub fn new(dev: u32, start: i32, size: i32) -> Self { let mut log = Self { @@ -64,18 +62,15 @@ impl Log { size, outstanding: 0, committing: false, - lh: ArrayVec::new(), + bufs: ArrayVec::new(), }; - unsafe { - log.recover_from_log(); - } - + log.recover_from_log(); log } /// Copy committed blocks from log to their home location. - unsafe fn install_trans(&mut self, recovering: bool) { - for (tail, dbuf) in self.lh.drain(..).enumerate() { + fn install_trans(&mut self) { + for (tail, dbuf) in self.bufs.drain(..).enumerate() { // Read log block. let lbuf = kernel() .file_system @@ -86,54 +81,64 @@ impl Log { let mut dbuf = dbuf.lock(); // Copy block to dst. - unsafe { - ptr::copy( - lbuf.deref_inner().data.as_ptr(), - dbuf.deref_mut_inner().data.as_mut_ptr(), - BSIZE, - ) - }; + dbuf.deref_inner_mut() + .data + .copy_from_slice(&lbuf.deref_inner().data[..]); // Write dst to disk. kernel().file_system.disk.write(&mut dbuf); - - if recovering { - mem::forget(dbuf); - } } } /// Read the log header from disk into the in-memory log header. - unsafe fn read_head(&mut self) { + fn read_head(&mut self) { let mut buf = kernel().file_system.disk.read(self.dev, self.start as u32); - let lh = buf.deref_mut_inner().data.as_mut_ptr() as *mut LogHeader; - for b in unsafe { &(*lh).block[0..(*lh).n as usize] } { - self.lh - .push(kernel().bcache.buf_unforget(self.dev, *b).unwrap()); + + const_assert!(mem::size_of::() <= BSIZE); + const_assert!(mem::align_of::() % mem::align_of::() == 0); + // It is safe becuase + // * buf.data is larger than LogHeader + // * buf.data is aligned properly. + // * LogHeader contains only u32's, so does not have any requirements. + // * buf is locked, so we can access it exclusively. + let lh = unsafe { &mut *(buf.deref_inner_mut().data.as_mut_ptr() as *mut LogHeader) }; + + for b in &lh.block[0..lh.n as usize] { + self.bufs + .push(kernel().file_system.disk.read(self.dev, *b).unlock()) } } /// Write in-memory log header to disk. /// This is the true point at which the /// current transaction commits. - unsafe fn write_head(&mut self) { + fn write_head(&mut self) { let mut buf = kernel().file_system.disk.read(self.dev, self.start as u32); - let mut hb = unsafe { &mut *(buf.deref_mut_inner().data.as_mut_ptr() as *mut LogHeader) }; - hb.n = self.lh.len() as u32; - for (db, b) in izip!(&mut hb.block, &self.lh) { - *db = (*b).blockno; + + const_assert!(mem::size_of::() <= BSIZE); + const_assert!(mem::align_of::() % mem::align_of::() == 0); + // It is safe becuase + // * buf.data is larger than LogHeader + // * buf.data is aligned properly. + // * LogHeader contains only u32's, so does not have any requirements. + // * buf is locked, so we can access it exclusively. + let mut lh = unsafe { &mut *(buf.deref_inner_mut().data.as_mut_ptr() as *mut LogHeader) }; + + lh.n = self.bufs.len() as u32; + for (db, b) in izip!(&mut lh.block, &self.bufs) { + *db = b.blockno; } kernel().file_system.disk.write(&mut buf) } - unsafe fn recover_from_log(&mut self) { - unsafe { self.read_head() }; + fn recover_from_log(&mut self) { + self.read_head(); // If committed, copy from log to disk. - unsafe { self.install_trans(true) }; + self.install_trans(); // Clear the log. - unsafe { self.write_head() }; + self.write_head(); } /// Called at the start of each FS system call. @@ -142,7 +147,7 @@ impl Log { loop { if guard.committing || // This op might exhaust log space; wait for commit. - guard.lh.len() as i32 + (guard.outstanding + 1) * MAXOPBLOCKS as i32 > LOGSIZE as i32 + guard.bufs.len() as i32 + (guard.outstanding + 1) * MAXOPBLOCKS as i32 > LOGSIZE as i32 { guard.sleep(); } else { @@ -154,7 +159,7 @@ impl Log { /// Called at the end of each FS system call. /// Commits if this was the last outstanding operation. - pub unsafe fn end_op(this: &Sleepablelock) { + pub fn end_op(this: &Sleepablelock) { let mut guard = this.lock(); guard.outstanding -= 1; assert!(!guard.committing, "guard.committing"); @@ -174,6 +179,8 @@ impl Log { if do_commit { // Call commit w/o holding locks, since not allowed // to sleep with locks. + // It is safe because other threads neither read nor write this log + // when guard.committing is true. unsafe { this.get_mut_unchecked().commit() }; let mut guard = this.lock(); guard.committing = false; @@ -182,8 +189,8 @@ impl Log { } /// Copy modified blocks from cache to self. - unsafe fn write_log(&mut self) { - for (tail, from) in self.lh.iter().enumerate() { + fn write_log(&mut self) { + for (tail, from) in self.bufs.iter().enumerate() { // Log block. let mut to = kernel() .file_system @@ -193,32 +200,28 @@ impl Log { // Cache block. let from = kernel().file_system.disk.read(self.dev, from.blockno); - unsafe { - ptr::copy( - from.deref_inner().data.as_ptr(), - to.deref_mut_inner().data.as_mut_ptr(), - BSIZE, - ) - }; + to.deref_inner_mut() + .data + .copy_from_slice(&from.deref_inner().data[..]); // Write the log. - kernel().file_system.disk.write(&mut to) + kernel().file_system.disk.write(&mut to); } } - unsafe fn commit(&mut self) { - if !self.lh.is_empty() { + fn commit(&mut self) { + if !self.bufs.is_empty() { // Write modified blocks from cache to self. - unsafe { self.write_log() }; + self.write_log(); // Write header to disk -- the real commit. - unsafe { self.write_head() }; + self.write_head(); // Now install writes to home locations. - unsafe { self.install_trans(false) }; + self.install_trans(); // Erase the transaction from the self. - unsafe { self.write_head() }; + self.write_head(); }; } @@ -232,19 +235,19 @@ impl Log { /// write(bp) pub fn write(&mut self, b: Buf<'static>) { assert!( - !(self.lh.len() >= LOGSIZE || self.lh.len() as i32 >= self.size - 1), + !(self.bufs.len() >= LOGSIZE || self.bufs.len() as i32 >= self.size - 1), "too big a transaction" ); assert!(self.outstanding >= 1, "write outside of trans"); - for buf in &self.lh { + for buf in &self.bufs { // Log absorbtion. - if buf.blockno == (*b).blockno { + if buf.blockno == b.blockno { return; } } // Add new block to log? - self.lh.push(b.unlock()); + self.bufs.push(b.unlock()); } } diff --git a/kernel-rs/src/fs/mod.rs b/kernel-rs/src/fs/mod.rs index b2f440104..22c68f883 100644 --- a/kernel-rs/src/fs/mod.rs +++ b/kernel-rs/src/fs/mod.rs @@ -11,7 +11,7 @@ //! //! On-disk file system format used for both kernel and user programs are also included here. -use core::{cmp, mem, ptr}; +use core::{cmp, mem}; use spin::Once; use crate::{ @@ -69,7 +69,7 @@ impl FileSystem { pub fn init(&self, dev: u32) { let _ = self .superblock - .call_once(|| unsafe { Superblock::new(&self.disk.read(dev, 1)) }); + .call_once(|| Superblock::new(&self.disk.read(dev, 1))); let _ = self.log.call_once(|| { Sleepablelock::new( "LOG", @@ -113,9 +113,7 @@ impl Drop for FsTransaction<'_> { fn drop(&mut self) { // Called at the end of each FS system call. // Commits if this was the last outstanding operation. - unsafe { - Log::end_op(self.fs.log()); - } + Log::end_op(self.fs.log()); } } @@ -128,30 +126,30 @@ impl FsTransaction<'_> { /// bp = kernel().file_system.disk.read(...) /// modify bp->data[] /// write(bp) - unsafe fn write(&self, b: Buf<'static>) { + fn write(&self, b: Buf<'static>) { self.fs.log().lock().write(b); } /// Zero a block. - unsafe fn bzero(&self, dev: u32, bno: u32) { + fn bzero(&self, dev: u32, bno: u32) { let mut buf = kernel().bcache.get_buf(dev, bno).lock(); - unsafe { ptr::write_bytes(buf.deref_mut_inner().data.as_mut_ptr(), 0, BSIZE) }; - buf.deref_mut_inner().valid = true; - unsafe { self.write(buf) }; + buf.deref_inner_mut().data.fill(0); + buf.deref_inner_mut().valid = true; + self.write(buf); } /// Blocks. /// Allocate a zeroed disk block. - unsafe fn balloc(&self, dev: u32) -> u32 { - for b in num_iter::range_step(0, self.fs.superblock().size, BPB) { + fn balloc(&self, dev: u32) -> u32 { + for b in num_iter::range_step(0, self.fs.superblock().size, BPB as u32) { let mut bp = self.fs.disk.read(dev, self.fs.superblock().bblock(b)); - for bi in 0..cmp::min(BPB, self.fs.superblock().size - b) { + for bi in 0..cmp::min(BPB as u32, self.fs.superblock().size - b) { let m = 1 << (bi % 8); - if bp.deref_mut_inner().data[(bi / 8) as usize] & m == 0 { + if bp.deref_inner_mut().data[(bi / 8) as usize] & m == 0 { // Is block free? - bp.deref_mut_inner().data[(bi / 8) as usize] |= m; // Mark block in use. - unsafe { self.write(bp) }; - unsafe { self.bzero(dev, b + bi) }; + bp.deref_inner_mut().data[(bi / 8) as usize] |= m; // Mark block in use. + self.write(bp); + self.bzero(dev, b + bi); return b + bi; } } @@ -161,16 +159,16 @@ impl FsTransaction<'_> { } /// Free a disk block. - unsafe fn bfree(&self, dev: u32, b: u32) { + fn bfree(&self, dev: u32, b: u32) { let mut bp = self.fs.disk.read(dev, self.fs.superblock().bblock(b)); - let bi = b.wrapping_rem(BPB) as i32; + let bi = b as usize % BPB; let m = 1u8 << (bi % 8); assert_ne!( - bp.deref_mut_inner().data[(bi / 8) as usize] & m, + bp.deref_inner_mut().data[bi / 8] & m, 0, "freeing free block" ); - bp.deref_mut_inner().data[(bi / 8) as usize] &= !m; - unsafe { self.write(bp) }; + bp.deref_inner_mut().data[bi / 8] &= !m; + self.write(bp); } } diff --git a/kernel-rs/src/fs/superblock.rs b/kernel-rs/src/fs/superblock.rs index 68a94083f..eec63deea 100644 --- a/kernel-rs/src/fs/superblock.rs +++ b/kernel-rs/src/fs/superblock.rs @@ -1,6 +1,10 @@ use core::{mem, ptr}; +use static_assertions::const_assert; -use crate::{bio::Buf, param::BSIZE}; +use crate::{ + bio::{Buf, BufData}, + param::BSIZE, +}; use super::Dinode; @@ -13,6 +17,7 @@ const FSMAGIC: u32 = 0x10203040; /// mkfs computes the super block and builds an initial file system. The /// super block describes the disk layout: #[derive(Copy, Clone)] +#[repr(C)] pub struct Superblock { /// Must be FSMAGIC magic: u32, @@ -40,14 +45,21 @@ pub struct Superblock { } /// Inodes per block. -pub const IPB: usize = BSIZE.wrapping_div(mem::size_of::()); +pub const IPB: usize = BSIZE / mem::size_of::(); /// Bitmap bits per block -pub const BPB: u32 = BSIZE.wrapping_mul(8) as u32; +pub const BPB: usize = BSIZE * 8; impl Superblock { /// Read the super block. - pub unsafe fn new(buf: &Buf<'static>) -> Self { + pub fn new(buf: &Buf<'static>) -> Self { + const_assert!(mem::size_of::() <= BSIZE); + const_assert!(mem::align_of::() % mem::align_of::() == 0); + // It is safe becuase + // * buf.data is larger than Superblock + // * buf.data is aligned properly. + // * Superblock contains only u32's, so does not have any requirements. + // * buf is locked, so we can access it exclusively. let result = unsafe { ptr::read(buf.deref_inner().data.as_ptr() as *const Superblock) }; assert_eq!(result.magic, FSMAGIC, "invalid file system"); result @@ -55,11 +67,11 @@ impl Superblock { /// Block containing inode i pub const fn iblock(self, i: u32) -> u32 { - i.wrapping_div(IPB as u32).wrapping_add(self.inodestart) + i / IPB as u32 + self.inodestart } /// Block of free map containing bit for block b pub const fn bblock(self, b: u32) -> u32 { - b.wrapping_div(BPB).wrapping_add(self.bmapstart) + b / BPB as u32 + self.bmapstart } } diff --git a/kernel-rs/src/virtio_disk.rs b/kernel-rs/src/virtio_disk.rs index 73d3efeb5..3b43684f4 100644 --- a/kernel-rs/src/virtio_disk.rs +++ b/kernel-rs/src/virtio_disk.rs @@ -218,7 +218,7 @@ impl Sleepablelock { let mut buf = kernel().bcache.get_buf(dev, blockno).lock(); if !buf.deref_inner().valid { Disk::rw(&mut self.lock(), &mut buf, false); - buf.deref_mut_inner().valid = true; + buf.deref_inner_mut().valid = true; } buf } @@ -348,7 +348,7 @@ impl Disk { }; // Record struct Buf for virtio_disk_intr(). - b.deref_mut_inner().disk = true; + b.deref_inner_mut().disk = true; // It does not break the invariant because b is &mut Buf, which refers // to a valid Buf. this.info.inflight[desc[0].idx].b = b; @@ -403,7 +403,7 @@ impl Disk { let buf = unsafe { self.info.inflight[id].b.as_mut() }.expect("Disk::intr"); // disk is done with buf - buf.deref_mut_inner().disk = false; + buf.deref_inner_mut().disk = false; buf.vdisk_request_waitchannel.wakeup(); self.info.used_idx += 1;