Merge branch 'initfs_mmap' into 'main'
Support zero-copy read-only mmaping in the initfs See merge request redox-os/base!58
This commit is contained in:
Generated
+2
-2
@@ -802,7 +802,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "generic-rt"
|
||||
version = "0.1.0"
|
||||
source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#7fcab3a43a6cf023aacd3ac9ced2a479b7f9c455"
|
||||
source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#9db10bb0a9651b86012a0d58a3327df95a20a297"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
@@ -1612,7 +1612,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "redox-rt"
|
||||
version = "0.1.0"
|
||||
source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#7fcab3a43a6cf023aacd3ac9ced2a479b7f9c455"
|
||||
source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#9db10bb0a9651b86012a0d58a3327df95a20a297"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"generic-rt",
|
||||
|
||||
Generated
+2
-2
@@ -40,7 +40,7 @@ checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
|
||||
[[package]]
|
||||
name = "generic-rt"
|
||||
version = "0.1.0"
|
||||
source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#fe5273890a8f39f8ffa1507bfb243d76270e8a27"
|
||||
source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#9db10bb0a9651b86012a0d58a3327df95a20a297"
|
||||
|
||||
[[package]]
|
||||
name = "goblin"
|
||||
@@ -143,7 +143,7 @@ checksum = "436d45c2b6a5b159d43da708e62b25be3a4a3d5550d654b72216ade4c4bfd717"
|
||||
[[package]]
|
||||
name = "redox-rt"
|
||||
version = "0.1.0"
|
||||
source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#fe5273890a8f39f8ffa1507bfb243d76270e8a27"
|
||||
source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#9db10bb0a9651b86012a0d58a3327df95a20a297"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"generic-rt",
|
||||
|
||||
@@ -107,16 +107,11 @@ pub fn main() -> ! {
|
||||
.expect("failed to open init")
|
||||
.to_upper()
|
||||
.unwrap();
|
||||
let memory = FdGuard::open("/scheme/memory", O_CLOEXEC)
|
||||
.expect("failed to open memory")
|
||||
.to_upper()
|
||||
.unwrap();
|
||||
|
||||
fexec_impl(
|
||||
image_file,
|
||||
init_thr_fd,
|
||||
init_proc_fd,
|
||||
&memory,
|
||||
path.as_bytes(),
|
||||
&[path.as_bytes()],
|
||||
&envs,
|
||||
|
||||
+37
-3
@@ -6,10 +6,10 @@ use core::str;
|
||||
use alloc::string::String;
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use redox_initfs::{InitFs, Inode, InodeDir, InodeKind, InodeStruct, types::Timespec};
|
||||
use redox_initfs::{types::Timespec, InitFs, Inode, InodeDir, InodeKind, InodeStruct};
|
||||
|
||||
use redox_path::canonicalize_to_standard;
|
||||
use redox_scheme::{CallerCtx, OpenResult, RequestKind, scheme::SchemeSync};
|
||||
use redox_scheme::{scheme::SchemeSync, CallerCtx, OpenResult, RequestKind};
|
||||
|
||||
use redox_scheme::{SignalBehavior, Socket};
|
||||
use syscall::data::Stat;
|
||||
@@ -19,6 +19,7 @@ use syscall::dirent::DirentKind;
|
||||
use syscall::error::*;
|
||||
use syscall::flag::*;
|
||||
use syscall::schemev2::NewFdFlags;
|
||||
use syscall::PAGE_SIZE;
|
||||
|
||||
struct Handle {
|
||||
inode: Inode,
|
||||
@@ -37,7 +38,8 @@ impl InitFsScheme {
|
||||
Self {
|
||||
handles: HashMap::default(),
|
||||
next_id: 0,
|
||||
fs: InitFs::new(bytes).expect("failed to parse initfs"),
|
||||
fs: InitFs::new(bytes, Some(PAGE_SIZE.try_into().unwrap()))
|
||||
.expect("failed to parse initfs"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,6 +305,38 @@ impl SchemeSync for InitFsScheme {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn mmap_prep(
|
||||
&mut self,
|
||||
id: usize,
|
||||
offset: u64,
|
||||
size: usize,
|
||||
flags: MapFlags,
|
||||
_ctx: &CallerCtx,
|
||||
) -> syscall::Result<usize> {
|
||||
let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?;
|
||||
|
||||
let data = match Self::get_inode(&self.fs, handle.inode)?.kind() {
|
||||
InodeKind::File(file) => file.data().map_err(|_| Error::new(EIO))?,
|
||||
InodeKind::Dir(_) => return Err(Error::new(EISDIR)),
|
||||
InodeKind::Link(link) => return Err(Error::new(ELOOP)),
|
||||
InodeKind::Unknown => return Err(Error::new(EIO)),
|
||||
};
|
||||
|
||||
if flags.contains(MapFlags::PROT_WRITE) {
|
||||
return Err(Error::new(EPERM));
|
||||
}
|
||||
|
||||
let Some(last_addr) = offset.checked_add(size as u64) else {
|
||||
return Err(Error::new(EINVAL));
|
||||
};
|
||||
|
||||
if last_addr > data.len().next_multiple_of(PAGE_SIZE) as u64 {
|
||||
return Err(Error::new(EINVAL));
|
||||
}
|
||||
|
||||
Ok(data.as_ptr() as usize)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run(bytes: &'static [u8], sync_pipe: usize) -> ! {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#![no_std]
|
||||
#![allow(internal_features)]
|
||||
#![feature(core_intrinsics, let_chains, iter_intersperse, str_from_raw_parts)]
|
||||
#![feature(core_intrinsics, iter_intersperse, str_from_raw_parts)]
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
#[path = "aarch64.rs"]
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
name = "redox-initfs"
|
||||
version = "0.2.0"
|
||||
authors = ["4lDO2 <4lDO2@protonmail.com>", "Kamil Koczurek <koczurekk@gmail.com>"]
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
license = "MIT"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
@@ -19,6 +19,9 @@ pub const DEFAULT_MAX_SIZE: u64 = 128 * MEBIBYTE;
|
||||
#[cfg(not(debug_assertions))]
|
||||
pub const DEFAULT_MAX_SIZE: u64 = 64 * MEBIBYTE;
|
||||
|
||||
// FIXME make this configurable to handle systems with 16k and 64k pages.
|
||||
const PAGE_SIZE: u16 = 4096;
|
||||
|
||||
enum EntryKind {
|
||||
File(File),
|
||||
Dir(Dir),
|
||||
@@ -153,9 +156,10 @@ fn read_directory(state: &mut State, path: &Path, root_path: &Path) -> Result<Di
|
||||
}
|
||||
|
||||
fn bump_alloc(state: &mut State, size: u64, why: &str) -> Result<u64> {
|
||||
if state.offset + size <= state.max_size {
|
||||
let end = (state.offset + size).next_multiple_of(PAGE_SIZE.into());
|
||||
if end <= state.max_size {
|
||||
let offset = state.offset;
|
||||
state.offset += size;
|
||||
state.offset = end;
|
||||
log::debug!("Allocating range {}..{} in {}", offset, state.offset, why);
|
||||
Ok(offset)
|
||||
} else {
|
||||
@@ -559,6 +563,7 @@ pub fn archive(
|
||||
.context("failed to get initfs size")?
|
||||
.len()
|
||||
.into(),
|
||||
page_size: PAGE_SIZE.into(),
|
||||
};
|
||||
write_all_at(&state.file, &header_bytes, header_offset, "writing header")
|
||||
.context("failed to write header")?;
|
||||
|
||||
+7
-1
@@ -182,7 +182,7 @@ impl<'initfs> InodeStruct<'initfs> {
|
||||
}
|
||||
|
||||
impl<'initfs> InitFs<'initfs> {
|
||||
pub fn new(base: &'initfs [u8]) -> Result<Self> {
|
||||
pub fn new(base: &'initfs [u8], required_page_size: Option<u16>) -> Result<Self> {
|
||||
let this = Self { base };
|
||||
|
||||
if base.len() < core::mem::size_of::<Header>() {
|
||||
@@ -214,6 +214,12 @@ impl<'initfs> InitFs<'initfs> {
|
||||
return Err(Error);
|
||||
}
|
||||
|
||||
if let Some(required_page_size) = required_page_size
|
||||
&& header.page_size.get() != required_page_size
|
||||
{
|
||||
return Err(Error);
|
||||
}
|
||||
|
||||
// From now on, we can be completely sure that the header and inode tables offsets are
|
||||
// valid, and thus continue based on that assumption.
|
||||
|
||||
|
||||
@@ -73,6 +73,7 @@ pub struct Header {
|
||||
pub inode_count: U16,
|
||||
pub bootstrap_entry: U64,
|
||||
pub initfs_size: U64,
|
||||
pub page_size: U16,
|
||||
}
|
||||
|
||||
const _: () = {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::{collections::HashMap, path::Path};
|
||||
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use anyhow::{Context, Result, anyhow};
|
||||
use redox_initfs::{InitFs, InodeKind, InodeStruct};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
@@ -83,7 +83,8 @@ fn archive_and_read() -> Result<()> {
|
||||
archive_common::archive(&args).context("failed to archive")?;
|
||||
|
||||
let data = std::fs::read(args.destination_path).context("failed to read new archive")?;
|
||||
let filesystem = redox_initfs::InitFs::new(&data).context("failed to parse archive header")?;
|
||||
let filesystem =
|
||||
redox_initfs::InitFs::new(&data, None).context("failed to parse archive header")?;
|
||||
let inode = filesystem
|
||||
.get_inode(redox_initfs::InitFs::ROOT_INODE)
|
||||
.ok_or_else(|| anyhow!("Failed to get root inode"))?;
|
||||
|
||||
@@ -23,7 +23,7 @@ fn main() -> Result<()> {
|
||||
.expect("expected the required arg IMAGE to exist");
|
||||
|
||||
let bytes = std::fs::read(source).context("failed to read image into memory")?;
|
||||
let initfs = InitFs::new(&bytes).context("failed to parse initfs header")?;
|
||||
let initfs = InitFs::new(&bytes, None).context("failed to parse initfs header")?;
|
||||
|
||||
dbg!(initfs.header());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user