Implement mapped iter that uses the MapIter and can yield data that is backed by EROFS inode. Implement continuous_iter and mapped_iter for filesystem which can returns an iterator that yields raw data. Signed-off-by: Yiyang Wu <toolmanp@xxxxxxx> --- fs/erofs/rust/erofs_sys/data.rs | 2 + .../rust/erofs_sys/data/raw_iters/ref_iter.rs | 63 +++++++++++++++++++ .../rust/erofs_sys/data/raw_iters/traits.rs | 4 ++ fs/erofs/rust/erofs_sys/superblock.rs | 13 ++++ fs/erofs/rust/erofs_sys/superblock/mem.rs | 22 +++++++ 5 files changed, 104 insertions(+) diff --git a/fs/erofs/rust/erofs_sys/data.rs b/fs/erofs/rust/erofs_sys/data.rs index 483f3204ce42..21630673c24e 100644 --- a/fs/erofs/rust/erofs_sys/data.rs +++ b/fs/erofs/rust/erofs_sys/data.rs @@ -2,6 +2,8 @@ // SPDX-License-Identifier: MIT or GPL-2.0-or-later pub(crate) mod backends; pub(crate) mod raw_iters; +use super::inode::*; +use super::map::*; use super::superblock::*; use super::*; diff --git a/fs/erofs/rust/erofs_sys/data/raw_iters/ref_iter.rs b/fs/erofs/rust/erofs_sys/data/raw_iters/ref_iter.rs index 5aa2b7f44f3d..d39c9523b628 100644 --- a/fs/erofs/rust/erofs_sys/data/raw_iters/ref_iter.rs +++ b/fs/erofs/rust/erofs_sys/data/raw_iters/ref_iter.rs @@ -4,6 +4,69 @@ use super::super::*; use super::*; +pub(crate) struct RefMapIter<'a, 'b, FS, B, I> +where + FS: FileSystem<I>, + B: Backend, + I: Inode, +{ + sb: &'a SuperBlock, + backend: &'a B, + map_iter: MapIter<'a, 'b, FS, I>, +} + +impl<'a, 'b, FS, B, I> RefMapIter<'a, 'b, FS, B, I> +where + FS: FileSystem<I>, + B: Backend, + I: Inode, +{ + pub(crate) fn new( + sb: &'a SuperBlock, + backend: &'a B, + map_iter: MapIter<'a, 'b, FS, I>, + ) -> Self { + Self { + sb, + backend, + map_iter, + } + } +} + +impl<'a, 'b, FS, B, I> Iterator for RefMapIter<'a, 'b, FS, B, I> +where + FS: FileSystem<I>, + B: Backend, + I: Inode, +{ + type Item = PosixResult<RefBuffer<'a>>; + fn next(&mut self) -> Option<Self::Item> { + match self.map_iter.next() { + Some(map) => match map { + Ok(m) => { + let accessor = self.sb.blk_access(m.physical.start); + let len = m.physical.len.min(accessor.len); + match self.backend.as_buf(m.physical.start, len) { + Ok(buf) => Some(Ok(buf)), + Err(e) => Some(Err(e)), + } + } + Err(e) => Some(Err(e)), + }, + None => None, + } + } +} + +impl<'a, 'b, FS, B, I> BufferMapIter<'a> for RefMapIter<'a, 'b, FS, B, I> +where + FS: FileSystem<I>, + B: Backend, + I: Inode, +{ +} + /// Continous Ref Buffer Iterator which iterates over a range of disk addresses within the /// the temp block size. Since the temp block is always the same size as page and it will not /// overflow. diff --git a/fs/erofs/rust/erofs_sys/data/raw_iters/traits.rs b/fs/erofs/rust/erofs_sys/data/raw_iters/traits.rs index 90b6a51658a9..531e970cdb49 100644 --- a/fs/erofs/rust/erofs_sys/data/raw_iters/traits.rs +++ b/fs/erofs/rust/erofs_sys/data/raw_iters/traits.rs @@ -3,6 +3,10 @@ use super::super::*; +/// Represents a basic iterator over a range of bytes from data backends. +/// The access order is guided by the block maps from the filesystem. +pub(crate) trait BufferMapIter<'a>: Iterator<Item = PosixResult<RefBuffer<'a>>> {} + /// Represents a basic iterator over a range of bytes from data backends. /// Note that this is skippable and can be used to move the iterator's cursor forward. pub(crate) trait ContinuousBufferIter<'a>: diff --git a/fs/erofs/rust/erofs_sys/superblock.rs b/fs/erofs/rust/erofs_sys/superblock.rs index fc6b3cb00b18..f60657eff3d6 100644 --- a/fs/erofs/rust/erofs_sys/superblock.rs +++ b/fs/erofs/rust/erofs_sys/superblock.rs @@ -5,6 +5,7 @@ use alloc::boxed::Box; use core::mem::size_of; +use super::data::raw_iters::*; use super::data::*; use super::devices::*; use super::inode::*; @@ -274,6 +275,18 @@ fn map(&self, inode: &I, offset: Off) -> MapResult { _ => todo!(), } } + + fn mapped_iter<'b, 'a: 'b>( + &'a self, + inode: &'b I, + offset: Off, + ) -> PosixResult<Box<dyn BufferMapIter<'a> + 'b>>; + + fn continuous_iter<'a>( + &'a self, + offset: Off, + len: Off, + ) -> PosixResult<Box<dyn ContinuousBufferIter<'a> + 'a>>; } pub(crate) struct SuperblockInfo<I, C, T> diff --git a/fs/erofs/rust/erofs_sys/superblock/mem.rs b/fs/erofs/rust/erofs_sys/superblock/mem.rs index 12bf797bd1e3..5756dc08744c 100644 --- a/fs/erofs/rust/erofs_sys/superblock/mem.rs +++ b/fs/erofs/rust/erofs_sys/superblock/mem.rs @@ -1,6 +1,7 @@ // Copyright 2024 Yiyang Wu // SPDX-License-Identifier: MIT or GPL-2.0-or-later +use super::alloc_helper::*; use super::data::raw_iters::ref_iter::*; use super::*; @@ -33,6 +34,27 @@ fn as_filesystem(&self) -> &dyn FileSystem<I> { self } + fn mapped_iter<'b, 'a: 'b>( + &'a self, + inode: &'b I, + offset: Off, + ) -> PosixResult<Box<dyn BufferMapIter<'a> + 'b>> { + heap_alloc(RefMapIter::new( + &self.sb, + &self.backend, + MapIter::new(self, inode, offset), + )) + .map(|v| v as Box<dyn BufferMapIter<'a> + 'b>) + } + fn continuous_iter<'a>( + &'a self, + offset: Off, + len: Off, + ) -> PosixResult<Box<dyn ContinuousBufferIter<'a> + 'a>> { + heap_alloc(ContinuousRefIter::new(&self.sb, &self.backend, offset, len)) + .map(|v| v as Box<dyn ContinuousBufferIter<'a> + 'a>) + } + fn device_info(&self) -> &DeviceInfo { &self.device_info } -- 2.46.0