Use a single mmap + read for each segment
This commit is contained in:
+7
-60
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user