Add support for converting from VmFrame to VmSegment

This commit is contained in:
LI Qing
2024-02-22 14:51:06 +09:00
committed by Tate, Hongliang Tian
parent 437ab804f3
commit e0d92b5203
4 changed files with 59 additions and 33 deletions

1
Cargo.lock generated
View File

@ -70,6 +70,7 @@ checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16"
name = "aster-block" name = "aster-block"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"align_ext",
"aster-frame", "aster-frame",
"aster-util", "aster-util",
"bitflags 1.3.2", "bitflags 1.3.2",

View File

@ -314,17 +314,17 @@ impl Drop for VmFrame {
/// ``` /// ```
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct VmSegment { pub struct VmSegment {
inner: Arc<Inner>, inner: VmSegmentInner,
range: Range<usize>, range: Range<usize>,
} }
#[derive(Debug)] #[derive(Debug, Clone)]
struct Inner { struct VmSegmentInner {
start_frame_index: Paddr, start_frame_index: Arc<Paddr>,
nframes: usize, nframes: usize,
} }
impl Inner { impl VmSegmentInner {
/// Creates the inner part of 'VmSegment'. /// Creates the inner part of 'VmSegment'.
/// ///
/// # Safety /// # Safety
@ -333,14 +333,13 @@ impl Inner {
unsafe fn new(paddr: Paddr, nframes: usize, flags: VmFrameFlags) -> Self { unsafe fn new(paddr: Paddr, nframes: usize, flags: VmFrameFlags) -> Self {
assert_eq!(paddr % PAGE_SIZE, 0); assert_eq!(paddr % PAGE_SIZE, 0);
Self { Self {
start_frame_index: (paddr / PAGE_SIZE).bitor(flags.bits), start_frame_index: Arc::new((paddr / PAGE_SIZE).bitor(flags.bits)),
nframes, nframes,
} }
} }
fn start_frame_index(&self) -> usize { fn start_frame_index(&self) -> usize {
self.start_frame_index (*self.start_frame_index).bitand(VmFrameFlags::all().bits().not())
.bitand(VmFrameFlags::all().bits().not())
} }
fn start_paddr(&self) -> Paddr { fn start_paddr(&self) -> Paddr {
@ -364,7 +363,7 @@ impl VmSegment {
/// as part of either a `VmFrame` or `VmSegment`. /// as part of either a `VmFrame` or `VmSegment`.
pub(crate) unsafe fn new(paddr: Paddr, nframes: usize, flags: VmFrameFlags) -> Self { pub(crate) unsafe fn new(paddr: Paddr, nframes: usize, flags: VmFrameFlags) -> Self {
Self { Self {
inner: Arc::new(Inner::new(paddr, nframes, flags)), inner: VmSegmentInner::new(paddr, nframes, flags),
range: 0..nframes, range: 0..nframes,
} }
} }
@ -407,7 +406,7 @@ impl VmSegment {
} }
fn need_dealloc(&self) -> bool { fn need_dealloc(&self) -> bool {
(self.inner.start_frame_index & VmFrameFlags::NEED_DEALLOC.bits()) != 0 (*self.inner.start_frame_index & VmFrameFlags::NEED_DEALLOC.bits()) != 0
} }
fn start_frame_index(&self) -> usize { fn start_frame_index(&self) -> usize {
@ -459,7 +458,7 @@ impl VmIo for VmSegment {
impl Drop for VmSegment { impl Drop for VmSegment {
fn drop(&mut self) { fn drop(&mut self) {
if self.need_dealloc() && Arc::strong_count(&self.inner) == 1 { if self.need_dealloc() && Arc::strong_count(&self.inner.start_frame_index) == 1 {
// Safety: the range of contiguous page frames is valid. // Safety: the range of contiguous page frames is valid.
unsafe { unsafe {
frame_allocator::dealloc_contiguous( frame_allocator::dealloc_contiguous(
@ -471,6 +470,18 @@ impl Drop for VmSegment {
} }
} }
impl From<VmFrame> for VmSegment {
fn from(frame: VmFrame) -> Self {
Self {
inner: VmSegmentInner {
start_frame_index: frame.frame_index.clone(),
nframes: 1,
},
range: 0..1,
}
}
}
/// VmReader is a reader for reading data from a contiguous range of memory. /// VmReader is a reader for reading data from a contiguous range of memory.
/// ///
/// # Example /// # Example

View File

@ -10,6 +10,7 @@ bitflags = "1.3"
spin = "0.9.4" spin = "0.9.4"
pod = { git = "https://github.com/asterinas/pod", rev = "d7dba56" } pod = { git = "https://github.com/asterinas/pod", rev = "d7dba56" }
aster-frame = { path = "../../../framework/aster-frame" } aster-frame = { path = "../../../framework/aster-frame" }
align_ext = { path = "../../../framework/libs/align_ext" }
aster-util = { path = "../../libs/aster-util" } aster-util = { path = "../../libs/aster-util" }
int-to-c-enum = { path = "../../libs/int-to-c-enum" } int-to-c-enum = { path = "../../libs/int-to-c-enum" }
component = { path = "../../libs/comp-sys/component" } component = { path = "../../libs/comp-sys/component" }

View File

@ -1,5 +1,6 @@
// SPDX-License-Identifier: MPL-2.0 // SPDX-License-Identifier: MPL-2.0
use align_ext::AlignExt;
use aster_frame::{ use aster_frame::{
sync::WaitQueue, sync::WaitQueue,
vm::{VmFrame, VmReader, VmSegment, VmWriter}, vm::{VmFrame, VmReader, VmSegment, VmWriter},
@ -358,29 +359,27 @@ pub enum BioStatus {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct BioSegment { pub struct BioSegment {
/// The contiguous pages on which this segment resides. /// The contiguous pages on which this segment resides.
pages: Pages, pages: VmSegment,
/// The offset (in bytes) relative to the first page. /// The starting offset (in bytes) within the first page.
/// The offset should always be aligned to the sector size and
/// must not exceed the size of a single page.
offset: AlignedUsize<SECTOR_SIZE>, offset: AlignedUsize<SECTOR_SIZE>,
// The length (in bytes), may cross pages. /// The total length (in bytes).
/// The length can span multiple pages and should be aligned to
/// the sector size.
len: AlignedUsize<SECTOR_SIZE>, len: AlignedUsize<SECTOR_SIZE>,
} }
const SECTOR_SIZE: u16 = super::SECTOR_SIZE as u16; const SECTOR_SIZE: u16 = super::SECTOR_SIZE as u16;
#[derive(Debug, Clone)]
enum Pages {
Frame(VmFrame),
Segment(VmSegment),
}
impl<'a> BioSegment { impl<'a> BioSegment {
/// Constructs a new `BioSegment` from `VmSegment`. /// Constructs a new `BioSegment` from `VmSegment`.
pub fn from_segment(segment: VmSegment, offset: usize, len: usize) -> Self { pub fn from_segment(segment: VmSegment, offset: usize, len: usize) -> Self {
assert!(offset + len <= segment.nbytes()); assert!(offset + len <= segment.nbytes());
Self { Self {
pages: Pages::Segment(segment), pages: segment.range(frame_range(&(offset..offset + len))),
offset: AlignedUsize::<SECTOR_SIZE>::new(offset).unwrap(), offset: AlignedUsize::<SECTOR_SIZE>::new(offset % super::BLOCK_SIZE).unwrap(),
len: AlignedUsize::<SECTOR_SIZE>::new(len).unwrap(), len: AlignedUsize::<SECTOR_SIZE>::new(len).unwrap(),
} }
} }
@ -390,7 +389,7 @@ impl<'a> BioSegment {
assert!(offset + len <= super::BLOCK_SIZE); assert!(offset + len <= super::BLOCK_SIZE);
Self { Self {
pages: Pages::Frame(frame), pages: VmSegment::from(frame),
offset: AlignedUsize::<SECTOR_SIZE>::new(offset).unwrap(), offset: AlignedUsize::<SECTOR_SIZE>::new(offset).unwrap(),
len: AlignedUsize::<SECTOR_SIZE>::new(len).unwrap(), len: AlignedUsize::<SECTOR_SIZE>::new(len).unwrap(),
} }
@ -406,25 +405,39 @@ impl<'a> BioSegment {
self.len.value() self.len.value()
} }
/// Returns the offset (in bytes) within the first page.
pub fn offset(&self) -> usize {
self.offset.value()
}
/// Returns the contiguous pages on which this segment resides.
pub fn pages(&self) -> &VmSegment {
&self.pages
}
/// Returns a reader to read data from it. /// Returns a reader to read data from it.
pub fn reader(&'a self) -> VmReader<'a> { pub fn reader(&'a self) -> VmReader<'a> {
let reader = match &self.pages { self.pages
Pages::Segment(segment) => segment.reader(), .reader()
Pages::Frame(frame) => frame.reader(), .skip(self.offset.value())
}; .limit(self.len.value())
reader.skip(self.offset.value()).limit(self.len.value())
} }
/// Returns a writer to write data into it. /// Returns a writer to write data into it.
pub fn writer(&'a self) -> VmWriter<'a> { pub fn writer(&'a self) -> VmWriter<'a> {
let writer = match &self.pages { self.pages
Pages::Segment(segment) => segment.writer(), .writer()
Pages::Frame(frame) => frame.writer(), .skip(self.offset.value())
}; .limit(self.len.value())
writer.skip(self.offset.value()).limit(self.len.value())
} }
} }
fn frame_range(byte_range: &Range<usize>) -> Range<usize> {
let start = byte_range.start.align_down(super::BLOCK_SIZE);
let end = byte_range.end.align_up(super::BLOCK_SIZE);
(start / super::BLOCK_SIZE)..(end / super::BLOCK_SIZE)
}
/// An aligned unsigned integer number. /// An aligned unsigned integer number.
/// ///
/// An instance of `AlignedUsize<const N: u16>` is guaranteed to have a value that is a multiple /// An instance of `AlignedUsize<const N: u16>` is guaranteed to have a value that is a multiple