mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-17 12:47:16 +00:00
map segments with vnode
This commit is contained in:
parent
7bee03f91f
commit
9ae2ca4c02
@ -1,6 +1,6 @@
|
|||||||
use super::Inode;
|
use super::Inode;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::rights::Rights;
|
use crate::rights::Full;
|
||||||
use crate::vm::vmo::{Pager, Vmo, VmoFlags, VmoOptions};
|
use crate::vm::vmo::{Pager, Vmo, VmoFlags, VmoOptions};
|
||||||
|
|
||||||
use core::ops::Range;
|
use core::ops::Range;
|
||||||
@ -8,21 +8,21 @@ use jinux_frame::vm::{VmAllocOptions, VmFrame, VmFrameVec};
|
|||||||
use lru::LruCache;
|
use lru::LruCache;
|
||||||
|
|
||||||
pub struct PageCache {
|
pub struct PageCache {
|
||||||
pages: Vmo,
|
pages: Vmo<Full>,
|
||||||
manager: Arc<PageCacheManager>,
|
manager: Arc<PageCacheManager>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PageCache {
|
impl PageCache {
|
||||||
pub fn new(inode: &Arc<dyn Inode>) -> Result<Self> {
|
pub fn new(inode: &Arc<dyn Inode>) -> Result<Self> {
|
||||||
let manager = Arc::new(PageCacheManager::new(Arc::downgrade(inode)));
|
let manager = Arc::new(PageCacheManager::new(Arc::downgrade(inode)));
|
||||||
let pages = VmoOptions::<Rights>::new(inode.len())
|
let pages = VmoOptions::<Full>::new(inode.len())
|
||||||
.flags(VmoFlags::RESIZABLE)
|
.flags(VmoFlags::RESIZABLE)
|
||||||
.pager(manager.clone())
|
.pager(manager.clone())
|
||||||
.alloc()?;
|
.alloc()?;
|
||||||
Ok(Self { pages, manager })
|
Ok(Self { pages, manager })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pages(&self) -> &Vmo {
|
pub fn pages(&self) -> &Vmo<Full> {
|
||||||
&self.pages
|
&self.pages
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,7 @@
|
|||||||
use super::{DirentVisitor, FsFlags, Inode, InodeMode, InodeType, Metadata, PageCache};
|
use super::{DirentVisitor, FsFlags, Inode, InodeMode, InodeType, Metadata, PageCache};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
<<<<<<< HEAD
|
|
||||||
|
|
||||||
=======
|
|
||||||
use crate::rights::Full;
|
use crate::rights::Full;
|
||||||
use crate::vm::vmo::{Vmo, VmoFlags, VmoOptions};
|
use crate::vm::vmo::Vmo;
|
||||||
>>>>>>> support file-backed mmap
|
|
||||||
use alloc::string::String;
|
use alloc::string::String;
|
||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
use jinux_frame::vm::VmIo;
|
use jinux_frame::vm::VmIo;
|
||||||
@ -23,8 +19,12 @@ struct Inner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Vnode {
|
impl Vnode {
|
||||||
pub fn page_cache(&self) -> Vmo<Full> {
|
pub fn page_cache(&self) -> Option<Vmo<Full>> {
|
||||||
self.inner.read().page_cache.dup().unwrap()
|
self.inner
|
||||||
|
.read()
|
||||||
|
.page_cache
|
||||||
|
.as_ref()
|
||||||
|
.map(|page_chche| page_chche.pages().dup().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(inode: Arc<dyn Inode>) -> Result<Self> {
|
pub fn new(inode: Arc<dyn Inode>) -> Result<Self> {
|
||||||
|
@ -1,85 +0,0 @@
|
|||||||
use crate::fs::file_handle::FileHandle;
|
|
||||||
use crate::fs::utils::SeekFrom;
|
|
||||||
use crate::prelude::*;
|
|
||||||
use crate::vm::vmar::{get_intersected_range, is_intersected};
|
|
||||||
use align_ext::AlignExt;
|
|
||||||
use jinux_frame::vm::{VmAllocOptions, VmFrameVec, VmIo};
|
|
||||||
use xmas_elf::program::ProgramHeader64;
|
|
||||||
|
|
||||||
use crate::vm::vmo::Pager;
|
|
||||||
|
|
||||||
// use super::load_elf::ElfSegment;
|
|
||||||
|
|
||||||
/// The pager behind a elf segment
|
|
||||||
pub struct ElfSegmentPager {
|
|
||||||
/// The pager size
|
|
||||||
pager_size: usize,
|
|
||||||
/// the back up file
|
|
||||||
file: Arc<FileHandle>,
|
|
||||||
/// The segment offset in backup file
|
|
||||||
file_offset: usize,
|
|
||||||
/// The segment size in backup file
|
|
||||||
file_size: usize,
|
|
||||||
/// The offset for the segment data.
|
|
||||||
/// The pager always starts at page-align address, while the segment data may start at any address.
|
|
||||||
/// So the offset will be the segment data start address % PAGE_SIZE
|
|
||||||
page_offset: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ElfSegmentPager {
|
|
||||||
pub fn new(file: Arc<FileHandle>, program_header: &ProgramHeader64) -> Self {
|
|
||||||
let ph_start = program_header.virtual_addr as Vaddr;
|
|
||||||
let ph_end = ph_start + program_header.mem_size as Vaddr;
|
|
||||||
let start = ph_start.align_down(PAGE_SIZE);
|
|
||||||
let end = ph_end.align_up(PAGE_SIZE);
|
|
||||||
let pager_size = end - start;
|
|
||||||
let offset = ph_start % PAGE_SIZE;
|
|
||||||
Self {
|
|
||||||
pager_size,
|
|
||||||
file,
|
|
||||||
file_offset: program_header.offset as usize,
|
|
||||||
file_size: program_header.file_size as usize,
|
|
||||||
page_offset: offset,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Pager for ElfSegmentPager {
|
|
||||||
fn commit_page(&self, offset: usize) -> Result<jinux_frame::vm::VmFrame> {
|
|
||||||
if offset >= self.pager_size {
|
|
||||||
return_errno_with_message!(Errno::EINVAL, "offset exceeds pager size");
|
|
||||||
}
|
|
||||||
|
|
||||||
let vm_alloc_option = VmAllocOptions::new(1);
|
|
||||||
let mut vm_frames = VmFrameVec::allocate(&vm_alloc_option)?;
|
|
||||||
vm_frames.zero();
|
|
||||||
|
|
||||||
let page_start = offset.align_down(PAGE_SIZE);
|
|
||||||
let page_end = page_start + PAGE_SIZE;
|
|
||||||
let page_range = page_start..page_end;
|
|
||||||
let segment_range = self.page_offset..self.page_offset + self.file_size;
|
|
||||||
if is_intersected(&page_range, &segment_range) {
|
|
||||||
let intersected_range = get_intersected_range(&page_range, &segment_range);
|
|
||||||
let segment_from_file_range = (intersected_range.start - self.page_offset)
|
|
||||||
..(intersected_range.end - self.page_offset);
|
|
||||||
let mut segment_data = vec![0u8; segment_from_file_range.len()];
|
|
||||||
self.file.seek(SeekFrom::Start(
|
|
||||||
self.file_offset + segment_from_file_range.start,
|
|
||||||
))?;
|
|
||||||
self.file.read(&mut segment_data)?;
|
|
||||||
let write_offset = intersected_range.start % PAGE_SIZE;
|
|
||||||
vm_frames.write_bytes(write_offset, &segment_data)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
let vm_frame = vm_frames.pop().unwrap();
|
|
||||||
Ok(vm_frame)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update_page(&self, offset: usize) -> Result<()> {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn decommit_page(&self, offset: usize) -> Result<()> {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,26 +1,21 @@
|
|||||||
//! This module is used to parse elf file content to get elf_load_info.
|
//! This module is used to parse elf file content to get elf_load_info.
|
||||||
//! When create a process from elf file, we will use the elf_load_info to construct the VmSpace
|
//! When create a process from elf file, we will use the elf_load_info to construct the VmSpace
|
||||||
|
|
||||||
use crate::fs::file_handle::FileHandle;
|
|
||||||
use crate::fs::fs_resolver::{FsPath, FsResolver, AT_FDCWD};
|
use crate::fs::fs_resolver::{FsPath, FsResolver, AT_FDCWD};
|
||||||
use crate::fs::utils::AccessMode;
|
use crate::fs::utils::Dentry;
|
||||||
use crate::process::program_loader::elf::init_stack::{init_aux_vec, InitStack};
|
use crate::process::program_loader::elf::init_stack::{init_aux_vec, InitStack};
|
||||||
use crate::vm::perms::VmPerms;
|
use crate::vm::perms::VmPerms;
|
||||||
use crate::vm::vmo::VmoRightsOp;
|
use crate::vm::vmo::VmoRightsOp;
|
||||||
use crate::{
|
use crate::{
|
||||||
prelude::*,
|
prelude::*,
|
||||||
rights::Full,
|
rights::Full,
|
||||||
vm::{
|
vm::{vmar::Vmar, vmo::Vmo},
|
||||||
vmar::Vmar,
|
|
||||||
vmo::{Pager, Vmo, VmoOptions},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
use align_ext::AlignExt;
|
use align_ext::AlignExt;
|
||||||
use jinux_frame::vm::VmPerm;
|
use jinux_frame::vm::VmPerm;
|
||||||
use xmas_elf::program::{self, ProgramHeader64};
|
use xmas_elf::program::{self, ProgramHeader64};
|
||||||
|
|
||||||
use super::elf_file::Elf;
|
use super::elf_file::Elf;
|
||||||
use super::elf_segment_pager::ElfSegmentPager;
|
|
||||||
|
|
||||||
/// load elf to the root vmar. this function will
|
/// load elf to the root vmar. this function will
|
||||||
/// 1. read the vaddr of each segment to get all elf pages.
|
/// 1. read the vaddr of each segment to get all elf pages.
|
||||||
@ -29,7 +24,7 @@ use super::elf_segment_pager::ElfSegmentPager;
|
|||||||
pub fn load_elf_to_root_vmar(
|
pub fn load_elf_to_root_vmar(
|
||||||
root_vmar: &Vmar<Full>,
|
root_vmar: &Vmar<Full>,
|
||||||
file_header: &[u8],
|
file_header: &[u8],
|
||||||
elf_file: Arc<FileHandle>,
|
elf_file: Arc<Dentry>,
|
||||||
fs_resolver: &FsResolver,
|
fs_resolver: &FsResolver,
|
||||||
argv: Vec<CString>,
|
argv: Vec<CString>,
|
||||||
envp: Vec<CString>,
|
envp: Vec<CString>,
|
||||||
@ -42,7 +37,7 @@ pub fn load_elf_to_root_vmar(
|
|||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
let map_addr = map_segment_vmos(&elf, root_vmar, elf_file)?;
|
let map_addr = map_segment_vmos(&elf, root_vmar, &elf_file)?;
|
||||||
let mut aux_vec = init_aux_vec(&elf, map_addr)?;
|
let mut aux_vec = init_aux_vec(&elf, map_addr)?;
|
||||||
let mut init_stack = InitStack::new_default_config(argv, envp);
|
let mut init_stack = InitStack::new_default_config(argv, envp);
|
||||||
init_stack.init(root_vmar, &elf, &ldso_load_info, &mut aux_vec)?;
|
init_stack.init(root_vmar, &elf, &ldso_load_info, &mut aux_vec)?;
|
||||||
@ -73,12 +68,13 @@ fn load_ldso_for_shared_object(
|
|||||||
if let Ok(ldso_path) = elf.ldso_path(file_header) && elf.is_shared_object(){
|
if let Ok(ldso_path) = elf.ldso_path(file_header) && elf.is_shared_object(){
|
||||||
trace!("ldso_path = {:?}", ldso_path);
|
trace!("ldso_path = {:?}", ldso_path);
|
||||||
let fs_path = FsPath::new(AT_FDCWD, &ldso_path)?;
|
let fs_path = FsPath::new(AT_FDCWD, &ldso_path)?;
|
||||||
let ldso_file = fs_resolver.open(&fs_path, AccessMode::O_RDONLY as u32, 0)?;
|
let ldso_file = fs_resolver.lookup(&fs_path)?;
|
||||||
|
let vnode = ldso_file.vnode();
|
||||||
let mut buf = Box::new([0u8; PAGE_SIZE]);
|
let mut buf = Box::new([0u8; PAGE_SIZE]);
|
||||||
let ldso_header = ldso_file.read(&mut *buf)?;
|
let ldso_header = vnode.read_at(0, &mut *buf)?;
|
||||||
let ldso_elf = Elf::parse_elf(&*buf)?;
|
let ldso_elf = Elf::parse_elf(&*buf)?;
|
||||||
let ldso_file = Arc::new(FileHandle::new_inode_handle(ldso_file));
|
// let ldso_file = Arc::new(FileHandle::new_inode_handle(ldso_file));
|
||||||
let map_addr = map_segment_vmos(&ldso_elf, root_vmar, ldso_file)?.unwrap();
|
let map_addr = map_segment_vmos(&ldso_elf, root_vmar, &ldso_file)?.unwrap();
|
||||||
return Ok(LdsoLoadInfo::new(ldso_elf.entry_point() + map_addr, map_addr));
|
return Ok(LdsoLoadInfo::new(ldso_elf.entry_point() + map_addr, map_addr));
|
||||||
}
|
}
|
||||||
// There are three reasons that an executable may lack ldso_path,
|
// There are three reasons that an executable may lack ldso_path,
|
||||||
@ -137,7 +133,7 @@ impl ElfLoadInfo {
|
|||||||
pub fn map_segment_vmos(
|
pub fn map_segment_vmos(
|
||||||
elf: &Elf,
|
elf: &Elf,
|
||||||
root_vmar: &Vmar<Full>,
|
root_vmar: &Vmar<Full>,
|
||||||
elf_file: Arc<FileHandle>,
|
elf_file: &Dentry,
|
||||||
) -> Result<Option<Vaddr>> {
|
) -> Result<Option<Vaddr>> {
|
||||||
// all segments of the shared object must be mapped to a continuous vm range
|
// all segments of the shared object must be mapped to a continuous vm range
|
||||||
// to ensure the relative offset of each segment not changed.
|
// to ensure the relative offset of each segment not changed.
|
||||||
@ -151,12 +147,12 @@ pub fn map_segment_vmos(
|
|||||||
.get_type()
|
.get_type()
|
||||||
.map_err(|_| Error::with_message(Errno::ENOEXEC, "parse program header type fails"))?;
|
.map_err(|_| Error::with_message(Errno::ENOEXEC, "parse program header type fails"))?;
|
||||||
if type_ == program::Type::Load {
|
if type_ == program::Type::Load {
|
||||||
let vmo = init_segment_vmo(program_header, elf_file.clone())?;
|
let vmo = init_segment_vmo(program_header, elf_file)?;
|
||||||
map_segment_vmo(
|
map_segment_vmo(
|
||||||
program_header,
|
program_header,
|
||||||
vmo,
|
vmo,
|
||||||
root_vmar,
|
root_vmar,
|
||||||
elf_file.clone(),
|
// elf_file.clone(),
|
||||||
&file_map_addr,
|
&file_map_addr,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
@ -180,7 +176,7 @@ fn map_segment_vmo(
|
|||||||
program_header: &ProgramHeader64,
|
program_header: &ProgramHeader64,
|
||||||
vmo: Vmo,
|
vmo: Vmo,
|
||||||
root_vmar: &Vmar<Full>,
|
root_vmar: &Vmar<Full>,
|
||||||
elf_file: Arc<FileHandle>,
|
// elf_file: Arc<FileHandle>,
|
||||||
file_map_addr: &Option<Vaddr>,
|
file_map_addr: &Option<Vaddr>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let perms = VmPerms::from(parse_segment_perm(program_header.flags)?);
|
let perms = VmPerms::from(parse_segment_perm(program_header.flags)?);
|
||||||
@ -188,8 +184,8 @@ fn map_segment_vmo(
|
|||||||
let offset = (program_header.virtual_addr as Vaddr).align_down(PAGE_SIZE);
|
let offset = (program_header.virtual_addr as Vaddr).align_down(PAGE_SIZE);
|
||||||
trace!(
|
trace!(
|
||||||
"map segment vmo: virtual addr = 0x{:x}, size = 0x{:x}, perms = {:?}",
|
"map segment vmo: virtual addr = 0x{:x}, size = 0x{:x}, perms = {:?}",
|
||||||
program_header.virtual_addr,
|
offset,
|
||||||
program_header.file_size,
|
program_header.mem_size,
|
||||||
perms
|
perms
|
||||||
);
|
);
|
||||||
let mut vm_map_options = root_vmar.new_map(vmo, perms)?;
|
let mut vm_map_options = root_vmar.new_map(vmo, perms)?;
|
||||||
@ -204,14 +200,58 @@ fn map_segment_vmo(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// create vmo for each segment
|
/// create vmo for each segment
|
||||||
fn init_segment_vmo(program_header: &ProgramHeader64, elf_file: Arc<FileHandle>) -> Result<Vmo> {
|
fn init_segment_vmo(program_header: &ProgramHeader64, elf_file: &Dentry) -> Result<Vmo> {
|
||||||
let vmo_start = (program_header.virtual_addr as Vaddr).align_down(PAGE_SIZE);
|
trace!(
|
||||||
let vmo_end = (program_header.virtual_addr as Vaddr + program_header.mem_size as Vaddr)
|
"mem range = 0x{:x} - 0x{:x}, mem_size = 0x{:x}",
|
||||||
|
program_header.virtual_addr,
|
||||||
|
program_header.virtual_addr + program_header.mem_size,
|
||||||
|
program_header.mem_size
|
||||||
|
);
|
||||||
|
trace!(
|
||||||
|
"file range = 0x{:x} - 0x{:x}, file_size = 0x{:x}",
|
||||||
|
program_header.offset,
|
||||||
|
program_header.offset + program_header.file_size,
|
||||||
|
program_header.file_size
|
||||||
|
);
|
||||||
|
let file_offset = program_header.offset as usize;
|
||||||
|
let virtual_addr = program_header.virtual_addr as usize;
|
||||||
|
debug_assert!(file_offset % PAGE_SIZE == virtual_addr % PAGE_SIZE);
|
||||||
|
|
||||||
|
let child_vmo_offset = file_offset.align_down(PAGE_SIZE);
|
||||||
|
let map_start = (program_header.virtual_addr as usize).align_down(PAGE_SIZE);
|
||||||
|
let map_end = (program_header.virtual_addr as usize + program_header.mem_size as usize)
|
||||||
.align_up(PAGE_SIZE);
|
.align_up(PAGE_SIZE);
|
||||||
let segment_len = vmo_end - vmo_start;
|
let vmo_size = map_end - map_start;
|
||||||
let pager = Arc::new(ElfSegmentPager::new(elf_file, &program_header)) as Arc<dyn Pager>;
|
debug_assert!(vmo_size >= (program_header.file_size as usize).align_up(PAGE_SIZE));
|
||||||
let vmo_alloc_options: VmoOptions<Full> = VmoOptions::new(segment_len).pager(pager);
|
let vnode = elf_file.vnode();
|
||||||
Ok(vmo_alloc_options.alloc()?.to_dyn())
|
let page_cache_vmo = vnode.page_cache().ok_or(Error::with_message(
|
||||||
|
Errno::ENOENT,
|
||||||
|
"executable has no page cache",
|
||||||
|
))?;
|
||||||
|
let segment_vmo = page_cache_vmo
|
||||||
|
.new_cow_child(child_vmo_offset..child_vmo_offset + vmo_size)?
|
||||||
|
.alloc()?;
|
||||||
|
|
||||||
|
// Write zero as paddings. There are head padding and tail padding.
|
||||||
|
// Head padding: if the segment's virtual address is not page-aligned,
|
||||||
|
// then the bytes in first page from start to virtual address should be padded zeros.
|
||||||
|
// Tail padding: If the segment's mem_size is larger than file size,
|
||||||
|
// then the bytes that are not backed up by file content should be zeros.(usually .data/.bss sections).
|
||||||
|
// FIXME: Head padding may be removed.
|
||||||
|
|
||||||
|
// Head padding.
|
||||||
|
let page_offset = file_offset % PAGE_SIZE;
|
||||||
|
if page_offset != 0 {
|
||||||
|
let buffer = vec![0u8; page_offset];
|
||||||
|
segment_vmo.write_bytes(0, &buffer)?;
|
||||||
|
}
|
||||||
|
// Tail padding.
|
||||||
|
let tail_padding_offset = program_header.file_size as usize + page_offset;
|
||||||
|
if vmo_size > tail_padding_offset {
|
||||||
|
let buffer = vec![0u8; vmo_size - tail_padding_offset];
|
||||||
|
segment_vmo.write_bytes(tail_padding_offset, &buffer)?;
|
||||||
|
}
|
||||||
|
Ok(segment_vmo.to_dyn())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_segment_perm(flags: xmas_elf::program::Flags) -> Result<VmPerm> {
|
fn parse_segment_perm(flags: xmas_elf::program::Flags) -> Result<VmPerm> {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
mod aux_vec;
|
mod aux_vec;
|
||||||
mod elf_file;
|
mod elf_file;
|
||||||
mod elf_segment_pager;
|
|
||||||
mod init_stack;
|
mod init_stack;
|
||||||
mod load_elf;
|
mod load_elf;
|
||||||
|
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
pub mod elf;
|
pub mod elf;
|
||||||
mod shebang;
|
mod shebang;
|
||||||
|
|
||||||
use crate::fs::file_handle::FileHandle;
|
|
||||||
use crate::fs::fs_resolver::{FsPath, FsResolver, AT_FDCWD};
|
use crate::fs::fs_resolver::{FsPath, FsResolver, AT_FDCWD};
|
||||||
use crate::fs::utils::AccessMode;
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::rights::Full;
|
use crate::rights::Full;
|
||||||
use crate::vm::vmar::Vmar;
|
use crate::vm::vmar::Vmar;
|
||||||
@ -34,12 +32,13 @@ pub fn load_program_to_root_vmar(
|
|||||||
executable_path
|
executable_path
|
||||||
};
|
};
|
||||||
let fs_path = FsPath::new(AT_FDCWD, &executable_path)?;
|
let fs_path = FsPath::new(AT_FDCWD, &executable_path)?;
|
||||||
let abs_path = fs_resolver.lookup(&fs_path)?.abs_path();
|
let elf_file = fs_resolver.lookup(&fs_path)?;
|
||||||
let file = fs_resolver.open(&fs_path, AccessMode::O_RDONLY as u32, 0)?;
|
let abs_path = elf_file.abs_path();
|
||||||
|
let vnode = elf_file.vnode();
|
||||||
let file_header = {
|
let file_header = {
|
||||||
// read the first page of file header
|
// read the first page of file header
|
||||||
let mut file_header_buffer = Box::new([0u8; PAGE_SIZE]);
|
let mut file_header_buffer = Box::new([0u8; PAGE_SIZE]);
|
||||||
file.read(&mut *file_header_buffer)?;
|
vnode.read_at(0, &mut *file_header_buffer)?;
|
||||||
file_header_buffer
|
file_header_buffer
|
||||||
};
|
};
|
||||||
if let Some(mut new_argv) = parse_shebang_line(&*file_header)? {
|
if let Some(mut new_argv) = parse_shebang_line(&*file_header)? {
|
||||||
@ -58,7 +57,8 @@ pub fn load_program_to_root_vmar(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let elf_file = Arc::new(FileHandle::new_inode_handle(file));
|
|
||||||
debug!("load executable, path = {}", executable_path);
|
debug!("load executable, path = {}", executable_path);
|
||||||
load_elf_to_root_vmar(root_vmar, &*file_header, elf_file, fs_resolver, argv, envp)
|
let elf_load_info =
|
||||||
|
load_elf_to_root_vmar(root_vmar, &*file_header, elf_file, fs_resolver, argv, envp)?;
|
||||||
|
Ok((abs_path, elf_load_info))
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ pub fn sys_execve(
|
|||||||
// destroy root vmars
|
// destroy root vmars
|
||||||
let root_vmar = current.root_vmar();
|
let root_vmar = current.root_vmar();
|
||||||
root_vmar.clear()?;
|
root_vmar.clear()?;
|
||||||
current.user_vm().set_default();
|
current.user_vm().set_default()?;
|
||||||
// load elf content to new vm space
|
// load elf content to new vm space
|
||||||
let fs_resolver = &*current.fs().read();
|
let fs_resolver = &*current.fs().read();
|
||||||
debug!("load program to root vmar");
|
debug!("load program to root vmar");
|
||||||
|
@ -107,7 +107,10 @@ fn mmap_filebacked_vmo(
|
|||||||
let fs_resolver = current.fs().read();
|
let fs_resolver = current.fs().read();
|
||||||
let dentry = fs_resolver.lookup_from_fd(fd)?;
|
let dentry = fs_resolver.lookup_from_fd(fd)?;
|
||||||
let vnode = dentry.vnode();
|
let vnode = dentry.vnode();
|
||||||
let page_cache_vmo = vnode.page_cache();
|
let page_cache_vmo = vnode.page_cache().ok_or(Error::with_message(
|
||||||
|
Errno::EBADF,
|
||||||
|
"File does not have page cache",
|
||||||
|
))?;
|
||||||
|
|
||||||
let vmo = if flags.contains(MMapFlags::MAP_PRIVATE) {
|
let vmo = if flags.contains(MMapFlags::MAP_PRIVATE) {
|
||||||
// map private
|
// map private
|
||||||
|
@ -334,10 +334,10 @@ impl Vmo_ {
|
|||||||
let frames = inner.committed_pages.get(&page_idx).unwrap().clone();
|
let frames = inner.committed_pages.get(&page_idx).unwrap().clone();
|
||||||
if let Some(parent_page_idx) = inner.inherited_pages.parent_page_idx(page_idx) {
|
if let Some(parent_page_idx) = inner.inherited_pages.parent_page_idx(page_idx) {
|
||||||
// copy contents of parent to the frame
|
// copy contents of parent to the frame
|
||||||
let mut tmp_buffer = [0u8; PAGE_SIZE];
|
let mut tmp_buffer = Box::new([0u8; PAGE_SIZE]);
|
||||||
let parent = self.parent.upgrade().unwrap();
|
let parent = self.parent.upgrade().unwrap();
|
||||||
parent.read_bytes(parent_page_idx * PAGE_SIZE, &mut tmp_buffer)?;
|
parent.read_bytes(parent_page_idx * PAGE_SIZE, &mut *tmp_buffer)?;
|
||||||
frames.write_bytes(0, &tmp_buffer)?;
|
frames.write_bytes(0, &*tmp_buffer)?;
|
||||||
} else {
|
} else {
|
||||||
frames.zero();
|
frames.zero();
|
||||||
}
|
}
|
||||||
|
@ -487,7 +487,12 @@ fn alloc_child_vmo_(
|
|||||||
}
|
}
|
||||||
let parent_page_idx_offset = range.start / PAGE_SIZE;
|
let parent_page_idx_offset = range.start / PAGE_SIZE;
|
||||||
let inherited_end = range.end.min(parent_vmo_size);
|
let inherited_end = range.end.min(parent_vmo_size);
|
||||||
let inherited_end_page_idx = inherited_end / PAGE_SIZE + 1;
|
let cow_size = if inherited_end >= range.start {
|
||||||
|
inherited_end - range.start
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
let inherited_end_page_idx = cow_size / PAGE_SIZE;
|
||||||
let inherited_pages = InheritedPages::new(0..inherited_end_page_idx, parent_page_idx_offset);
|
let inherited_pages = InheritedPages::new(0..inherited_end_page_idx, parent_page_idx_offset);
|
||||||
let vmo_inner = VmoInner {
|
let vmo_inner = VmoInner {
|
||||||
pager: None,
|
pager: None,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user