Merge branch 'better_fmap' into 'master'
Offset-based mmap See merge request redox-os/redoxfs!61
This commit is contained in:
Generated
+48
-28
@@ -4,9 +4,9 @@ version = 3
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.19.0"
|
||||
version = "0.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97"
|
||||
checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3"
|
||||
dependencies = [
|
||||
"gimli",
|
||||
]
|
||||
@@ -61,9 +61,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.67"
|
||||
version = "0.3.68"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca"
|
||||
checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"cc",
|
||||
@@ -112,9 +112,12 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.79"
|
||||
version = "1.0.80"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
|
||||
checksum = "51f1226cd9da55587234753d1245dd5b132343ea240f26b6a9003d68706141ba"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
@@ -133,9 +136,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.8"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c"
|
||||
checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
@@ -262,9 +265,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.146"
|
||||
version = "0.2.147"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b"
|
||||
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
@@ -280,9 +283,9 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.6.2"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
|
||||
checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
|
||||
dependencies = [
|
||||
"adler",
|
||||
]
|
||||
@@ -295,9 +298,9 @@ checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.30.4"
|
||||
version = "0.31.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03b4680b86d9cfafba8fc491dc9b6df26b68cf40e9e6cd73909194759a63c385"
|
||||
checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
@@ -326,18 +329,18 @@ checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.60"
|
||||
version = "1.0.66"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406"
|
||||
checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.28"
|
||||
version = "1.0.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488"
|
||||
checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
@@ -380,6 +383,11 @@ version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
|
||||
|
||||
[[package]]
|
||||
name = "range-tree"
|
||||
version = "0.1.0"
|
||||
source = "git+https://gitlab.redox-os.org/redox-os/range-tree.git#a1b3720c65cd3388def5f4c7fb32281380c78c0d"
|
||||
|
||||
[[package]]
|
||||
name = "rdrand"
|
||||
version = "0.4.0"
|
||||
@@ -407,8 +415,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
|
||||
source = "git+https://gitlab.redox-os.org/redox-os/syscall.git#a525620c818a801bb7038e111b71033eff56a3ee"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
@@ -435,6 +442,7 @@ dependencies = [
|
||||
"getrandom",
|
||||
"libc",
|
||||
"log",
|
||||
"range-tree",
|
||||
"redox_simple_endian",
|
||||
"redox_syscall 0.3.5",
|
||||
"seahash",
|
||||
@@ -445,9 +453,21 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.8.4"
|
||||
version = "1.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f"
|
||||
checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7b6d6190b7594385f61bd3911cd1be99dfddcfc365a4160cc2ab5bff4aed294"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
@@ -456,9 +476,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.7.2"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78"
|
||||
checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
@@ -474,9 +494,9 @@ checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.10.0"
|
||||
version = "1.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
|
||||
checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9"
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
@@ -547,9 +567,9 @@ checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.9"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0"
|
||||
checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
|
||||
+3
-2
@@ -39,7 +39,8 @@ failure = "0.1.8"
|
||||
getrandom = { version = "0.2.5", optional = true }
|
||||
libc = "0.2"
|
||||
log = { version = "0.4.14", default-features = false, optional = true}
|
||||
redox_syscall = "0.3"
|
||||
redox_syscall = { git = "https://gitlab.redox-os.org/redox-os/syscall.git" }
|
||||
range-tree = { git = "https://gitlab.redox-os.org/redox-os/range-tree.git" }
|
||||
seahash = { version = "4.1.0", default-features = false }
|
||||
termion = { version = "1.5.6", optional = true }
|
||||
uuid = { version = "0.5", default-features = false }
|
||||
@@ -54,7 +55,7 @@ features = [
|
||||
]
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
default = ["std", "log"]
|
||||
force-soft = [
|
||||
"aes/force-soft"
|
||||
]
|
||||
|
||||
+6
-2
@@ -1,3 +1,5 @@
|
||||
#![feature(int_roundings)]
|
||||
|
||||
extern crate libc;
|
||||
|
||||
#[cfg(target_os = "redox")]
|
||||
@@ -90,14 +92,16 @@ fn bootloader_password() -> Option<Vec<u8>> {
|
||||
|
||||
let mut password = Vec::with_capacity(size);
|
||||
unsafe {
|
||||
let password_map = syscall::physmap(addr, size, syscall::PhysmapFlags::empty())
|
||||
let aligned_size = size.next_multiple_of(syscall::PAGE_SIZE);
|
||||
|
||||
let password_map = syscall::physmap(addr, aligned_size, syscall::PhysmapFlags::empty())
|
||||
.expect("failed to map REDOXFS_PASSWORD");
|
||||
|
||||
for i in 0..size {
|
||||
password.push(*((password_map + i) as *const u8));
|
||||
}
|
||||
|
||||
let _ = syscall::physunmap(password_map);
|
||||
let _ = syscall::funmap(password_map, aligned_size);
|
||||
}
|
||||
Some(password)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
// Used often in generating redox_syscall errors
|
||||
#![allow(clippy::or_fun_call)]
|
||||
|
||||
#![feature(int_roundings)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
use core::sync::atomic::AtomicUsize;
|
||||
|
||||
+172
-67
@@ -1,8 +1,11 @@
|
||||
use std::cmp::{max, min};
|
||||
use std::collections::BTreeMap;
|
||||
use std::slice;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
use alloc::collections::BTreeMap;
|
||||
use range_tree::RangeTree;
|
||||
|
||||
use syscall::{MAP_PRIVATE, PAGE_SIZE, EBADFD};
|
||||
use syscall::data::{Map, Stat, TimeSpec};
|
||||
use syscall::error::{Error, Result, EBADF, EINVAL, EISDIR, ENOMEM, EPERM};
|
||||
use syscall::flag::{
|
||||
@@ -12,6 +15,8 @@ use syscall::flag::{
|
||||
|
||||
use crate::{Disk, Node, Transaction, TreePtr};
|
||||
|
||||
pub type Fmaps = BTreeMap<u32, FileMmapInfo>;
|
||||
|
||||
pub trait Resource<D: Disk> {
|
||||
fn parent_ptr_opt(&self) -> Option<TreePtr<Node>>;
|
||||
|
||||
@@ -29,9 +34,9 @@ pub trait Resource<D: Disk> {
|
||||
|
||||
fn seek(&mut self, offset: isize, whence: usize, tx: &mut Transaction<D>) -> Result<isize>;
|
||||
|
||||
fn fmap(&mut self, map: &Map, tx: &mut Transaction<D>) -> Result<usize>;
|
||||
fn fmap(&mut self, fmaps: &mut Fmaps, flags: MapFlags, size: usize, offset: u64, tx: &mut Transaction<D>) -> Result<usize>;
|
||||
|
||||
fn funmap(&mut self, address: usize, tx: &mut Transaction<D>) -> Result<usize>;
|
||||
fn funmap(&mut self, fmaps: &mut Fmaps, offset: u64, size: usize, tx: &mut Transaction<D>) -> Result<usize>;
|
||||
|
||||
fn fchmod(&mut self, mode: u16, tx: &mut Transaction<D>) -> Result<usize> {
|
||||
let mut node = tx.read_tree(self.node_ptr())?;
|
||||
@@ -112,7 +117,7 @@ pub trait Resource<D: Disk> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn sync(&mut self, tx: &mut Transaction<D>) -> Result<usize>;
|
||||
fn sync(&mut self, fmaps: &mut Fmaps, tx: &mut Transaction<D>) -> Result<usize>;
|
||||
|
||||
fn truncate(&mut self, len: usize, tx: &mut Transaction<D>) -> Result<usize>;
|
||||
|
||||
@@ -203,10 +208,10 @@ impl<D: Disk> Resource<D> for DirResource {
|
||||
Ok(self.seek)
|
||||
}
|
||||
|
||||
fn fmap(&mut self, _map: &Map, _tx: &mut Transaction<D>) -> Result<usize> {
|
||||
fn fmap(&mut self, _fmaps: &mut Fmaps, _flags: MapFlags, _size: usize, _offset: u64, _tx: &mut Transaction<D>) -> Result<usize> {
|
||||
Err(Error::new(EBADF))
|
||||
}
|
||||
fn funmap(&mut self, _address: usize, _tx: &mut Transaction<D>) -> Result<usize> {
|
||||
fn funmap(&mut self, _fmaps: &mut Fmaps, _offset: u64, _size: usize, _tx: &mut Transaction<D>) -> Result<usize> {
|
||||
Err(Error::new(EBADF))
|
||||
}
|
||||
|
||||
@@ -218,7 +223,7 @@ impl<D: Disk> Resource<D> for DirResource {
|
||||
&self.path
|
||||
}
|
||||
|
||||
fn sync(&mut self, _tx: &mut Transaction<D>) -> Result<usize> {
|
||||
fn sync(&mut self, _fmaps: &mut Fmaps, _tx: &mut Transaction<D>) -> Result<usize> {
|
||||
Err(Error::new(EBADF))
|
||||
}
|
||||
|
||||
@@ -231,68 +236,64 @@ impl<D: Disk> Resource<D> for DirResource {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Fmap {
|
||||
node_ptr: TreePtr<Node>,
|
||||
offset: usize,
|
||||
rc: usize,
|
||||
flags: MapFlags,
|
||||
data: &'static mut [u8],
|
||||
last_page_tail: u16,
|
||||
}
|
||||
|
||||
impl Fmap {
|
||||
pub unsafe fn new<D: Disk>(
|
||||
node_ptr: TreePtr<Node>,
|
||||
map: &Map,
|
||||
flags: MapFlags,
|
||||
unaligned_size: usize,
|
||||
offset: u64,
|
||||
base: *mut u8,
|
||||
tx: &mut Transaction<D>,
|
||||
) -> Result<Self> {
|
||||
extern "C" {
|
||||
fn memalign(align: usize, size: usize) -> *mut u8;
|
||||
fn free(ptr: *mut u8);
|
||||
}
|
||||
|
||||
// Memory provided to fmap must be page aligned and sized
|
||||
let align = 4096;
|
||||
let address = memalign(align, ((map.size + align - 1) / align) * align);
|
||||
if address.is_null() {
|
||||
return Err(Error::new(ENOMEM));
|
||||
}
|
||||
let aligned_size = unaligned_size.next_multiple_of(syscall::PAGE_SIZE);
|
||||
|
||||
let address = base.add(offset as usize);
|
||||
//println!("ADDR {:p} {:p}", base, address);
|
||||
|
||||
// Read buffer from disk
|
||||
let atime = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
|
||||
let buf = slice::from_raw_parts_mut(address, map.size);
|
||||
|
||||
let buf = slice::from_raw_parts_mut(address, unaligned_size);
|
||||
|
||||
let count = match tx.read_node(
|
||||
node_ptr,
|
||||
map.offset as u64,
|
||||
offset,
|
||||
buf,
|
||||
atime.as_secs(),
|
||||
atime.subsec_nanos(),
|
||||
) {
|
||||
Ok(ok) => ok,
|
||||
Err(err) => {
|
||||
free(address);
|
||||
let _ = syscall::funmap(address as usize, aligned_size);
|
||||
return Err(err);
|
||||
}
|
||||
};
|
||||
|
||||
// Make sure remaining data is zeroed
|
||||
for i in count..buf.len() {
|
||||
buf[i] = 0;
|
||||
}
|
||||
buf[count..].fill(0_u8);
|
||||
|
||||
Ok(Self {
|
||||
node_ptr,
|
||||
offset: map.offset,
|
||||
flags: map.flags,
|
||||
data: buf,
|
||||
rc: 1,
|
||||
flags,
|
||||
last_page_tail: (unaligned_size % PAGE_SIZE) as u16,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn sync<D: Disk>(&mut self, tx: &mut Transaction<D>) -> Result<()> {
|
||||
pub unsafe fn sync<D: Disk>(&mut self, node_ptr: TreePtr<Node>, base: *mut u8, offset: u64, size: usize, tx: &mut Transaction<D>) -> Result<()> {
|
||||
if self.flags & PROT_WRITE == PROT_WRITE {
|
||||
let mtime = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
|
||||
tx.write_node(
|
||||
self.node_ptr,
|
||||
self.offset as u64,
|
||||
&self.data,
|
||||
node_ptr,
|
||||
offset,
|
||||
unsafe { core::slice::from_raw_parts(base.add(offset as usize), size) },
|
||||
mtime.as_secs(),
|
||||
mtime.subsec_nanos(),
|
||||
)?;
|
||||
@@ -301,18 +302,6 @@ impl Fmap {
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Fmap {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
extern "C" {
|
||||
fn free(ptr: *mut u8);
|
||||
}
|
||||
|
||||
free(self.data.as_mut_ptr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FileResource {
|
||||
path: String,
|
||||
parent_ptr_opt: Option<TreePtr<Node>>,
|
||||
@@ -320,7 +309,20 @@ pub struct FileResource {
|
||||
flags: usize,
|
||||
seek: isize,
|
||||
uid: u32,
|
||||
fmaps: BTreeMap<usize, Fmap>,
|
||||
}
|
||||
pub struct FileMmapInfo {
|
||||
base: *mut u8,
|
||||
ranges: RangeTree<Fmap>,
|
||||
pub open_fds: usize,
|
||||
}
|
||||
impl Default for FileMmapInfo {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
base: core::ptr::null_mut(),
|
||||
ranges: RangeTree::new(),
|
||||
open_fds: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FileResource {
|
||||
@@ -338,7 +340,6 @@ impl FileResource {
|
||||
flags,
|
||||
seek: 0,
|
||||
uid,
|
||||
fmaps: BTreeMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -364,7 +365,6 @@ impl<D: Disk> Resource<D> for FileResource {
|
||||
flags: self.flags,
|
||||
seek: self.seek,
|
||||
uid: self.uid,
|
||||
fmaps: BTreeMap::new(),
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -423,30 +423,91 @@ impl<D: Disk> Resource<D> for FileResource {
|
||||
Ok(self.seek)
|
||||
}
|
||||
|
||||
fn fmap(&mut self, map: &Map, tx: &mut Transaction<D>) -> Result<usize> {
|
||||
fn fmap(&mut self, fmaps: &mut Fmaps, flags: MapFlags, unaligned_size: usize, offset: u64, tx: &mut Transaction<D>) -> Result<usize> {
|
||||
//dbg!(&self.fmaps);
|
||||
let accmode = self.flags & O_ACCMODE;
|
||||
if map.flags.contains(PROT_READ) && !(accmode == O_RDWR || accmode == O_RDONLY) {
|
||||
if flags.contains(PROT_READ) && !(accmode == O_RDWR || accmode == O_RDONLY) {
|
||||
return Err(Error::new(EBADF));
|
||||
}
|
||||
if map.flags.contains(PROT_WRITE) && !(accmode == O_RDWR || accmode == O_WRONLY) {
|
||||
if flags.contains(PROT_WRITE) && !(accmode == O_RDWR || accmode == O_WRONLY) {
|
||||
return Err(Error::new(EBADF));
|
||||
}
|
||||
//TODO: PROT_EXEC?
|
||||
|
||||
let map = unsafe { Fmap::new(self.node_ptr, map, tx)? };
|
||||
let address = map.data.as_ptr() as usize;
|
||||
self.fmaps.insert(address, map);
|
||||
Ok(address)
|
||||
let aligned_size = unaligned_size.next_multiple_of(PAGE_SIZE);
|
||||
|
||||
// TODO: PROT_EXEC? It is however unenforcable without restricting anonymous mmap, since a
|
||||
// program can always map anonymous RW-, read from a file, then remap as R-E. But it might
|
||||
// be usable as a hint, prohibiting direct executable mmaps at least.
|
||||
|
||||
// TODO: Pass entry directory to Resource trait functions, since the node_ptr can be
|
||||
// obtained by the caller.
|
||||
let fmap_info = fmaps.get_mut(&self.node_ptr.id()).ok_or(Error::new(EBADFD))?;
|
||||
|
||||
let max_offset = fmap_info.ranges.end();
|
||||
if offset + aligned_size as u64 > max_offset {
|
||||
if fmap_info.base.is_null() {
|
||||
fmap_info.base = unsafe {
|
||||
syscall::fmap(!0, &Map {
|
||||
size: offset as usize + aligned_size,
|
||||
// PRIVATE/SHARED doesn't matter once the pages are passed in the fmap
|
||||
// handler.
|
||||
flags: MapFlags::PROT_READ | MapFlags::PROT_WRITE | MapFlags::MAP_PRIVATE,
|
||||
|
||||
offset: 0,
|
||||
address: 0,
|
||||
})? as *mut u8
|
||||
};
|
||||
} else {
|
||||
let new_size = (offset as usize + aligned_size).next_multiple_of(PAGE_SIZE);
|
||||
let old_size = max_offset as usize;
|
||||
|
||||
fmap_info.base = unsafe {
|
||||
syscall::syscall5(syscall::SYS_MREMAP, fmap_info.base as usize, old_size, 0, new_size, syscall::MremapFlags::empty().bits() | (PROT_READ | PROT_WRITE).bits())? as *mut u8
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
let affected_fmaps = fmap_info.ranges.remove_and_unused(offset..offset + aligned_size as u64);
|
||||
|
||||
for (range, v_opt) in affected_fmaps {
|
||||
//dbg!(&range);
|
||||
if let Some(mut fmap) = v_opt {
|
||||
fmap.rc += 1;
|
||||
fmap.flags |= flags;
|
||||
|
||||
fmap_info.ranges.insert(range.start, range.end - range.start, fmap);
|
||||
} else {
|
||||
let map = unsafe { Fmap::new(self.node_ptr, flags, unaligned_size, offset, fmap_info.base, tx)? };
|
||||
fmap_info.ranges.insert(offset, aligned_size as u64, map);
|
||||
}
|
||||
}
|
||||
//dbg!(&self.fmaps);
|
||||
|
||||
Ok(fmap_info.base as usize + offset as usize)
|
||||
}
|
||||
|
||||
fn funmap(&mut self, address: usize, tx: &mut Transaction<D>) -> Result<usize> {
|
||||
if let Some(mut fmap) = self.fmaps.remove(&address) {
|
||||
fmap.sync(tx)?;
|
||||
fn funmap(&mut self, fmaps: &mut Fmaps, offset: u64, size: usize, tx: &mut Transaction<D>) -> Result<usize> {
|
||||
let fmap_info = fmaps.get_mut(&self.node_ptr.id()).ok_or(Error::new(EBADFD))?;
|
||||
|
||||
Ok(0)
|
||||
} else {
|
||||
Err(Error::new(EINVAL))
|
||||
//dbg!(&self.fmaps);
|
||||
//dbg!(self.fmaps.conflicts(offset..offset + size as u64).collect::<Vec<_>>());
|
||||
let mut affected_fmaps = fmap_info.ranges.remove(offset..offset + size as u64);
|
||||
|
||||
for (range, mut fmap) in affected_fmaps {
|
||||
fmap.rc = fmap.rc.checked_sub(1).unwrap();
|
||||
|
||||
//log::info!("SYNCING {}..{}", range.start, range.end);
|
||||
unsafe {
|
||||
fmap.sync(self.node_ptr, fmap_info.base, range.start, (range.end - range.start) as usize, tx)?;
|
||||
}
|
||||
|
||||
if fmap.rc > 0 {
|
||||
fmap_info.ranges.insert(range.start, range.end - range.start, fmap);
|
||||
}
|
||||
}
|
||||
//dbg!(&self.fmaps);
|
||||
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn fcntl(&mut self, cmd: usize, arg: usize) -> Result<usize> {
|
||||
@@ -464,9 +525,13 @@ impl<D: Disk> Resource<D> for FileResource {
|
||||
&self.path
|
||||
}
|
||||
|
||||
fn sync(&mut self, tx: &mut Transaction<D>) -> Result<usize> {
|
||||
for fmap in self.fmaps.values_mut() {
|
||||
fmap.sync(tx)?;
|
||||
fn sync(&mut self, fmaps: &mut Fmaps, tx: &mut Transaction<D>) -> Result<usize> {
|
||||
if let Some(fmap_info) = fmaps.get_mut(&self.node_ptr.id()) {
|
||||
for (range, fmap) in fmap_info.ranges.iter_mut() {
|
||||
unsafe {
|
||||
fmap.sync(self.node_ptr, fmap_info.base, range.start, (range.end - range.start) as usize, tx)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(0)
|
||||
@@ -521,6 +586,7 @@ impl<D: Disk> Resource<D> for FileResource {
|
||||
|
||||
impl Drop for FileResource {
|
||||
fn drop(&mut self) {
|
||||
/*
|
||||
if !self.fmaps.is_empty() {
|
||||
eprintln!(
|
||||
"redoxfs: file {} still has {} fmaps!",
|
||||
@@ -528,5 +594,44 @@ impl Drop for FileResource {
|
||||
self.fmaps.len()
|
||||
);
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
impl range_tree::Value for Fmap {
|
||||
type K = u64;
|
||||
|
||||
fn try_merge_forward(self, other: &Self) -> core::result::Result<Self, Self> {
|
||||
if self.rc == other.rc && self.flags == other.flags && self.last_page_tail == 0 {
|
||||
Ok(self)
|
||||
} else {
|
||||
Err(self)
|
||||
}
|
||||
}
|
||||
fn try_merge_backwards(self, other: &Self) -> core::result::Result<Self, Self> {
|
||||
if self.rc == other.rc && self.flags == other.flags && other.last_page_tail == 0 {
|
||||
Ok(self)
|
||||
} else {
|
||||
Err(self)
|
||||
}
|
||||
}
|
||||
fn split(self, prev_range: Option<core::ops::Range<Self::K>>, range: core::ops::Range<Self::K>, next_range: Option<core::ops::Range<Self::K>>) -> (Option<Self>, Self, Option<Self>) {
|
||||
(
|
||||
prev_range.map(|range| Fmap {
|
||||
rc: self.rc,
|
||||
flags: self.flags,
|
||||
last_page_tail: 0,
|
||||
}),
|
||||
Fmap {
|
||||
rc: self.rc,
|
||||
flags: self.flags,
|
||||
last_page_tail: if next_range.is_none() { self.last_page_tail } else { 0 },
|
||||
},
|
||||
next_range.map(|range| Fmap {
|
||||
rc: self.rc,
|
||||
flags: self.flags,
|
||||
last_page_tail: self.last_page_tail,
|
||||
}),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+32
-47
@@ -3,14 +3,15 @@ use std::str;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
use syscall::{EBADFD, MunmapFlags};
|
||||
use syscall::data::{Map, Stat, StatVfs, TimeSpec};
|
||||
use syscall::error::{
|
||||
Error, Result, EACCES, EBADF, EBUSY, EEXIST, EINVAL, EISDIR, ELOOP, ENOENT, ENOTDIR, ENOTEMPTY,
|
||||
EPERM, EXDEV,
|
||||
};
|
||||
use syscall::flag::{
|
||||
EventFlags, MODE_PERM, O_ACCMODE, O_CREAT, O_DIRECTORY, O_EXCL, O_NOFOLLOW, O_RDONLY, O_RDWR,
|
||||
O_STAT, O_SYMLINK, O_TRUNC, O_WRONLY,
|
||||
EventFlags, MapFlags, MODE_PERM, O_ACCMODE, O_CREAT, O_DIRECTORY, O_EXCL, O_NOFOLLOW, O_RDONLY,
|
||||
O_RDWR, O_STAT, O_SYMLINK, O_TRUNC, O_WRONLY,
|
||||
};
|
||||
use syscall::scheme::SchemeMut;
|
||||
|
||||
@@ -23,14 +24,14 @@ pub struct FileScheme<D: Disk> {
|
||||
fs: FileSystem<D>,
|
||||
next_id: AtomicUsize,
|
||||
files: BTreeMap<usize, Box<dyn Resource<D>>>,
|
||||
fmap: BTreeMap<usize, usize>,
|
||||
fmap: super::resource::Fmaps,
|
||||
}
|
||||
|
||||
impl<D: Disk> FileScheme<D> {
|
||||
pub fn new(name: String, fs: FileSystem<D>) -> FileScheme<D> {
|
||||
FileScheme {
|
||||
name: name,
|
||||
fs: fs,
|
||||
name,
|
||||
fs,
|
||||
next_id: AtomicUsize::new(1),
|
||||
files: BTreeMap::new(),
|
||||
fmap: BTreeMap::new(),
|
||||
@@ -400,6 +401,8 @@ impl<D: Disk> SchemeMut for FileScheme<D> {
|
||||
}
|
||||
}
|
||||
};
|
||||
self.fmap.entry(resource.node_ptr().id()).or_insert_with(Default::default).open_fds += 1;
|
||||
|
||||
|
||||
let id = self.next_id.fetch_add(1, Ordering::SeqCst);
|
||||
self.files.insert(id, resource);
|
||||
@@ -533,6 +536,7 @@ impl<D: Disk> SchemeMut for FileScheme<D> {
|
||||
return Err(Error::new(EBADF));
|
||||
};
|
||||
|
||||
self.fmap.get_mut(&resource.node_ptr().id()).ok_or(Error::new(EBADFD))?.open_fds += 1;
|
||||
let id = self.next_id.fetch_add(1, Ordering::SeqCst);
|
||||
self.files.insert(id, resource);
|
||||
|
||||
@@ -755,11 +759,10 @@ impl<D: Disk> SchemeMut for FileScheme<D> {
|
||||
|
||||
fn fsync(&mut self, id: usize) -> Result<usize> {
|
||||
// println!("Fsync {}", id);
|
||||
if let Some(file) = self.files.get_mut(&id) {
|
||||
self.fs.tx(|tx| file.sync(tx))
|
||||
} else {
|
||||
Err(Error::new(EBADF))
|
||||
}
|
||||
let file = self.files.get_mut(&id).ok_or(Error::new(EBADF))?;
|
||||
let fmaps = &mut self.fmap;
|
||||
|
||||
self.fs.tx(|tx| file.sync(fmaps, tx))
|
||||
}
|
||||
|
||||
fn ftruncate(&mut self, id: usize, len: usize) -> Result<usize> {
|
||||
@@ -780,49 +783,31 @@ impl<D: Disk> SchemeMut for FileScheme<D> {
|
||||
}
|
||||
}
|
||||
|
||||
fn fmap(&mut self, id: usize, map: &Map) -> Result<usize> {
|
||||
// println!("Fmap {}, {:?}", id, map);
|
||||
if let Some(file) = self.files.get_mut(&id) {
|
||||
let address = self.fs.tx(|tx| file.fmap(map, tx))?;
|
||||
self.fmap.insert(address, id);
|
||||
Ok(address)
|
||||
} else {
|
||||
Err(Error::new(EBADF))
|
||||
}
|
||||
}
|
||||
fn mmap_prep(&mut self, id: usize, offset: u64, size: usize, flags: MapFlags) -> Result<usize> {
|
||||
println!("Mmap {}, {:?} {} {}", id, flags, size, offset);
|
||||
let file = self.files.get_mut(&id).ok_or(Error::new(EBADF))?;
|
||||
let fmaps = &mut self.fmap;
|
||||
|
||||
fn funmap_old(&mut self, address: usize) -> Result<usize> {
|
||||
if let Some(id) = self.fmap.remove(&address) {
|
||||
if let Some(file) = self.files.get_mut(&id) {
|
||||
self.fs.tx(|tx| file.funmap(address, tx))
|
||||
} else {
|
||||
Err(Error::new(EINVAL))
|
||||
}
|
||||
} else {
|
||||
Err(Error::new(EINVAL))
|
||||
}
|
||||
self.fs.tx(|tx| file.fmap(fmaps, flags, size, offset, tx))
|
||||
}
|
||||
fn munmap(&mut self, id: usize, offset: u64, size: usize, flags: MunmapFlags) -> Result<usize> {
|
||||
println!("Munmap {}, {} {}", id, size, offset);
|
||||
let file = self.files.get_mut(&id).ok_or(Error::new(EBADF))?;
|
||||
let fmaps = &mut self.fmap;
|
||||
|
||||
//TODO: implement (length is ignored!)
|
||||
fn funmap(&mut self, address: usize, length: usize) -> Result<usize> {
|
||||
println!("redoxfs: funmap 0x{:X}, {}", address, length);
|
||||
if let Some(id) = self.fmap.remove(&address) {
|
||||
if let Some(file) = self.files.get_mut(&id) {
|
||||
self.fs.tx(|tx| file.funmap(address, tx))
|
||||
} else {
|
||||
Err(Error::new(EINVAL))
|
||||
}
|
||||
} else {
|
||||
Err(Error::new(EINVAL))
|
||||
}
|
||||
self.fs.tx(|tx| file.funmap(fmaps, offset, size, tx))
|
||||
}
|
||||
|
||||
fn close(&mut self, id: usize) -> Result<usize> {
|
||||
// println!("Close {}", id);
|
||||
if self.files.remove(&id).is_some() {
|
||||
Ok(0)
|
||||
} else {
|
||||
Err(Error::new(EBADF))
|
||||
}
|
||||
let file = self.files.remove(&id).ok_or(Error::new(EBADF))?;
|
||||
let file_info = self.fmap.get_mut(&file.node_ptr().id()).ok_or(Error::new(EBADFD))?;
|
||||
|
||||
file_info.open_fds = file_info.open_fds.checked_sub(1).expect("open_fds not tracked correctly");
|
||||
|
||||
// TODO: If open_fds reaches zero and there are no hardlinks (directory entries) to any
|
||||
// particular inode, remove that inode here.
|
||||
|
||||
Ok(0)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user