Use a single mmap + read for each segment

This commit is contained in:
bjorn3
2025-04-12 20:10:28 +02:00
parent f79a2fb657
commit 095646517d
+7 -60
View File
@@ -168,74 +168,21 @@ where
total_page_count * PAGE_SIZE,
flags,
)?;
syscall::lseek(*image_file, segment.p_offset as isize, SEEK_SET)
.map_err(|_| Error::new(EIO))?;
// If unaligned, read the head page separately.
let (first_aligned_page, remaining_filesz) = if voff > 0 {
let bytes_to_next_page = PAGE_SIZE - voff;
// TODO: Attempt to mmap with MAP_PRIVATE directly from the image file instead.
let (_guard, dst_page) =
unsafe { MmapGuard::map_mut_anywhere(*grants_fd, vaddr, PAGE_SIZE)? };
if filesz > 0 {
syscall::lseek(*image_file, segment.p_offset as isize, SEEK_SET)
.map_err(|_| Error::new(EIO))?;
let length = core::cmp::min(bytes_to_next_page, filesz);
read_all(*image_file, None, &mut dst_page[voff..][..length])?;
(vaddr + PAGE_SIZE, filesz - length)
} else {
(vaddr, filesz)
};
let remaining_page_count = remaining_filesz.div_floor(PAGE_SIZE);
let tail_bytes = remaining_filesz % PAGE_SIZE;
// TODO: Unless the calling process if *very* memory-constrained, the max amount of
// pages per iteration has no limit other than the time it takes to setup page
// tables.
//
// TODO: Reserve PAGES_PER_ITER "scratch pages" of virtual memory for that type of
// situation?
const PAGES_PER_ITER: usize = 64;
// TODO: Before this loop, attempt to mmap with MAP_PRIVATE directly from the image
// file.
for page_idx in (0..remaining_page_count).step_by(PAGES_PER_ITER) {
// Use commented out lines to trigger kernel bug (FIXME).
//let pages_in_this_group = core::cmp::min(PAGES_PER_ITER, file_page_count - page_idx * PAGES_PER_ITER);
let pages_in_this_group =
core::cmp::min(PAGES_PER_ITER, remaining_page_count - page_idx);
if pages_in_this_group == 0 {
break;
}
// TODO: MAP_FIXED to optimize away funmap?
let (_guard, dst_memory) = unsafe {
MmapGuard::map_mut_anywhere(
*grants_fd,
first_aligned_page + page_idx * PAGE_SIZE, // offset
pages_in_this_group * PAGE_SIZE, // size
vaddr, // offset
(voff + filesz).next_multiple_of(PAGE_SIZE), // size
)?
};
// TODO: Are &mut [u8] and &mut [[u8; PAGE_SIZE]] interchangeable (if the
// lengths are aligned, obviously)?
read_all(*image_file, None, dst_memory)?;
}
if tail_bytes > 0 {
let (_guard, dst_page) = unsafe {
MmapGuard::map_mut_anywhere(
*grants_fd,
first_aligned_page + remaining_page_count * PAGE_SIZE,
PAGE_SIZE,
)?
};
read_all(*image_file, None, &mut dst_page[..tail_bytes])?;
read_all(*image_file, None, &mut dst_memory[voff..voff + filesz])?;
}
// file_page_count..file_page_count + zero_page_count are already zero-initialized