ext2: Use memory offset instead of block id for mmaping info

ext2's mmaping information is used to perform mmap() in crosvm's main
process. Previously, the struct has a block id field so we needed to
calculate the offset by multiplying block size.
Instead, the struct now contains memory offset for convenience.

BUG=b:329359333
TEST=run VM on workstation with pmem-ext2

Change-Id: I845fc021c715a4b490e80142823855832fe3bc41
Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/5771636
Commit-Queue: Keiichi Watanabe <keiichiw@chromium.org>
Reviewed-by: Takaya Saeki <takayas@chromium.org>
This commit is contained in:
Keiichi Watanabe 2024-08-08 20:03:44 +09:00 committed by crosvm LUCI
parent c7a790d1cf
commit 0d2ad4007e
2 changed files with 15 additions and 15 deletions

View file

@ -168,8 +168,8 @@ impl BlockId {
/// Information on how to mmap a host file to ext2 blocks.
pub struct FileMappingInfo {
/// The ext2 disk block id that the memory region maps to.
pub start_block: BlockId,
/// Offset in the memory that a file is mapped to.
pub mem_offset: usize,
/// The file to be mmap'd.
pub file: File,
/// The length of the mapping.
@ -205,18 +205,17 @@ impl<'a> Arena<'a> {
}
/// A helper function to mark a region as reserved.
fn reserve(&self, block: BlockId, block_offset: usize, len: usize) -> Result<()> {
let offset = u32::from(block) as usize * self.block_size + block_offset;
let mem_end = offset.checked_add(len).context("mem_end overflow")?;
fn reserve(&self, mem_offset: usize, len: usize) -> Result<()> {
let mem_end = mem_offset.checked_add(len).context("mem_end overflow")?;
if mem_end > self.mem.size() {
bail!(
"out of memory region: {offset} + {len} > {}",
"out of memory region: {mem_offset} + {len} > {}",
self.mem.size()
);
}
self.regions.borrow_mut().allocate(offset, len)?;
self.regions.borrow_mut().allocate(mem_offset, len)?;
Ok(())
}
@ -226,14 +225,14 @@ impl<'a> Arena<'a> {
/// `into_mapping_info()` to retrieve the mapping information and call mmap later instead.
pub fn reserve_for_mmap(
&self,
start_block: BlockId,
mem_offset: usize,
length: usize,
file: File,
file_offset: usize,
) -> Result<()> {
self.reserve(start_block, 0, length)?;
self.reserve(mem_offset, length)?;
self.mappings.borrow_mut().push(FileMappingInfo {
start_block,
mem_offset,
length,
file: file.try_clone()?,
file_offset,
@ -250,9 +249,9 @@ impl<'a> Arena<'a> {
block_offset: usize,
len: usize,
) -> Result<&'a mut [u8]> {
self.reserve(block, block_offset, len)?;
let offset = u32::from(block) as usize * self.block_size + block_offset;
self.reserve(offset, len)?;
let new_addr = (self.mem.as_ptr() as usize)
.checked_add(offset)
.context("address overflow")?;

View file

@ -482,10 +482,11 @@ impl<'a> Ext2<'a> {
}
let length = std::cmp::min(remaining, BLOCK_SIZE * blocks.len());
let start_block = blocks[0];
let mem_offset = u32::from(start_block) as usize * BLOCK_SIZE;
// Reserve the region in arena to prevent from overwriting metadata.
arena
.reserve_for_mmap(
start_block,
mem_offset,
length,
file.try_clone().context("failed to clone file")?,
file_offset,
@ -814,14 +815,14 @@ pub fn create_ext2_region(cfg: &Config, src_dir: Option<&Path>) -> Result<Memory
mem.msync()?;
let mut mmap_arena = MemoryMappingArena::from(mem);
for FileMappingInfo {
start_block,
mem_offset,
file,
length,
file_offset,
} in file_mappings
{
mmap_arena.add_fd_mapping(
u32::from(start_block) as usize * BLOCK_SIZE,
mem_offset,
length,
&file,
file_offset as u64, /* fd_offset */