Add device_infos implementation in rust. It will later be used to be put inside the SuperblockInfo. This mask and spec can later be used to chunk-based image file block mapping. Signed-off-by: Yiyang Wu <toolmanp@xxxxxxx> --- fs/erofs/rust/erofs_sys/devices.rs | 47 ++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/fs/erofs/rust/erofs_sys/devices.rs b/fs/erofs/rust/erofs_sys/devices.rs index 097676ee8720..7495164c7bd0 100644 --- a/fs/erofs/rust/erofs_sys/devices.rs +++ b/fs/erofs/rust/erofs_sys/devices.rs @@ -1,6 +1,10 @@ // Copyright 2024 Yiyang Wu // SPDX-License-Identifier: MIT or GPL-2.0-or-later +use super::alloc_helper::*; +use super::data::raw_iters::*; +use super::data::*; +use super::*; use alloc::vec::Vec; /// Device specification. @@ -21,8 +25,51 @@ pub(crate) struct DeviceSlot { reserved: [u8; 56], } +impl From<[u8; 128]> for DeviceSlot { + fn from(data: [u8; 128]) -> Self { + Self { + tags: data[0..64].try_into().unwrap(), + blocks: u32::from_le_bytes([data[64], data[65], data[66], data[67]]), + mapped_blocks: u32::from_le_bytes([data[68], data[69], data[70], data[71]]), + reserved: data[72..128].try_into().unwrap(), + } + } +} + /// Device information. pub(crate) struct DeviceInfo { pub(crate) mask: u16, pub(crate) specs: Vec<DeviceSpec>, } + +pub(crate) fn get_device_infos<'a>( + iter: &mut (dyn ContinuousBufferIter<'a> + 'a), +) -> PosixResult<DeviceInfo> { + let mut specs = Vec::new(); + for data in iter { + let buffer = data?; + let mut cur: usize = 0; + let len = buffer.content().len(); + while cur + 128 <= len { + let slot_data: [u8; 128] = buffer.content()[cur..cur + 128].try_into().unwrap(); + let slot = DeviceSlot::from(slot_data); + cur += 128; + push_vec( + &mut specs, + DeviceSpec { + tags: slot.tags, + blocks: slot.blocks, + mapped_blocks: slot.mapped_blocks, + }, + )?; + } + } + + let mask = if specs.is_empty() { + 0 + } else { + (1 << (specs.len().ilog2() + 1)) - 1 + }; + + Ok(DeviceInfo { mask, specs }) +} -- 2.46.0