diff --git a/Cargo.lock b/Cargo.lock index dabb6df6fddcbe13f8ea35bda811fb0218a44833..9b30a29d6e602ef0c2da519d354179d57ae19f8b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,25 +1,11 @@ -[[package]] -name = "bitflags" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "cfg-if" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "fuchsia-zircon" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" +name = "fuchsia-cprng" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -27,16 +13,16 @@ name = "fuse" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "thread-scoped 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libc" -version = "0.2.45" +version = "0.2.51" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -52,7 +38,7 @@ name = "log" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -62,27 +48,49 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rand" -version = "0.3.22" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.4.3" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rdrand" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "redox_syscall" -version = "0.1.49" +version = "0.1.53" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -90,18 +98,12 @@ name = "redoxfs" version = "0.3.2" dependencies = [ "fuse 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.49 (registry+https://github.com/rust-lang/crates.io-index)", - "spin 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.53 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "spin" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "thread-scoped" version = "1.0.2" @@ -109,12 +111,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "time" -version = "0.1.41" +version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.49 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.53 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -122,12 +124,12 @@ name = "uuid" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "winapi" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -145,22 +147,22 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] -"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" -"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" -"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" +"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" +"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum fuse 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80e57070510966bfef93662a81cb8aa2b1c7db0964354fa9921434f04b9e8660" -"checksum libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)" = "2d2857ec59fadc0773853c664d2d18e7198e83883e7060b63c924cb077bd5c74" +"checksum libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)" = "bedcc7a809076656486ffe045abeeac163da1b558e963a31e29fbfbeba916917" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" -"checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" -"checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" -"checksum redox_syscall 0.1.49 (registry+https://github.com/rust-lang/crates.io-index)" = "f22c50afdcf3f0a31ebb6b47697f6a7c5e5a24967e842858118bce0615f0afad" -"checksum spin 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ceac490aa12c567115b40b7b7fceca03a6c9d53d5defea066123debc83c5dc1f" +"checksum rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c" +"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" +"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +"checksum redox_syscall 0.1.53 (registry+https://github.com/rust-lang/crates.io-index)" = "53848511b7ee6eb9d5c3db48481aaa5779b38fc0131bc133c98cb4f2b2411928" "checksum thread-scoped 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bcbb6aa301e5d3b0b5ef639c9a9c7e2f1c944f177b460c04dc24c69b1fa2bd99" -"checksum time 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "847da467bf0db05882a9e2375934a8a55cffdc9db0d128af1518200260ba1f6c" +"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" "checksum uuid 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcc7e3b898aa6f6c08e5295b6c89258d1331e9ac578cc992fb818759951bdc22" -"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" +"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml index 657aefd8ab468be0faa59ac331e24c7e766edb1c..80e0a89e6947a418811071631c1b956d8b9ba14c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,6 @@ path = "src/bin/mkfs.rs" doc = false [dependencies] -spin = "0.4" redox_syscall = "0.1" uuid = { version = "0.5", features = ["v4"] } diff --git a/src/disk/cache.rs b/src/disk/cache.rs index e11dfcbba1c8214104fafff3914c5259fc3b423c..cf0f96a8f8483a9e0297d41c249e6e3949222710 100644 --- a/src/disk/cache.rs +++ b/src/disk/cache.rs @@ -81,6 +81,7 @@ impl<T: Disk> Disk for DiskCache<T> { } fn write_at(&mut self, block: u64, buffer: &[u8]) -> Result<usize> { + //TODO: Write only blocks that have changed // println!("Cache write at {}", block); self.inner.write_at(block, buffer)?; diff --git a/src/mount/redox/mod.rs b/src/mount/redox/mod.rs index f4a8cb06a98ddc0a34f61ea97cdfe2dfd371eca8..139f6f39c2c84b86de1d76a5fe2c0e80ea8544ea 100644 --- a/src/mount/redox/mod.rs +++ b/src/mount/redox/mod.rs @@ -1,5 +1,3 @@ -extern crate spin; - use syscall; use syscall::{Packet, Scheme}; use std::fs::File; diff --git a/src/mount/redox/resource.rs b/src/mount/redox/resource.rs index 664efe66550a0a024a96e832d1857eca91372493..b5e47bdc0832c771a5c713ec9ddff7fa5873810a 100644 --- a/src/mount/redox/resource.rs +++ b/src/mount/redox/resource.rs @@ -1,13 +1,14 @@ use std::cmp::{min, max}; +use std::collections::BTreeMap; +use std::slice; use std::time::{SystemTime, UNIX_EPOCH}; use syscall::data::{Map, Stat, TimeSpec}; -use syscall::error::{Error, Result, EBADF, EBUSY, EINVAL, EISDIR, EPERM}; +use syscall::error::{Error, Result, EBADF, EINVAL, EISDIR, ENOMEM, EPERM}; use syscall::flag::{O_ACCMODE, O_RDONLY, O_WRONLY, O_RDWR, F_GETFL, F_SETFL, MODE_PERM, PROT_READ, PROT_WRITE, SEEK_SET, SEEK_CUR, SEEK_END}; use disk::Disk; use filesystem::FileSystem; -use super::scheme::{Fmaps, FmapKey, FmapValue}; pub trait Resource<D: Disk> { fn block(&self) -> u64; @@ -15,14 +16,14 @@ pub trait Resource<D: Disk> { fn read(&mut self, buf: &mut [u8], fs: &mut FileSystem<D>) -> Result<usize>; fn write(&mut self, buf: &[u8], fs: &mut FileSystem<D>) -> Result<usize>; fn seek(&mut self, offset: usize, whence: usize, fs: &mut FileSystem<D>) -> Result<usize>; - fn fmap(&mut self, map: &Map, maps: &mut Fmaps, fs: &mut FileSystem<D>) -> Result<usize>; - fn funmap(&mut self, maps: &mut Fmaps, fs: &mut FileSystem<D>) -> Result<usize>; + fn fmap(&mut self, map: &Map, fs: &mut FileSystem<D>) -> Result<usize>; + fn funmap(&mut self, address: usize, fs: &mut FileSystem<D>) -> Result<usize>; fn fchmod(&mut self, mode: u16, fs: &mut FileSystem<D>) -> Result<usize>; fn fchown(&mut self, uid: u32, gid: u32, fs: &mut FileSystem<D>) -> Result<usize>; fn fcntl(&mut self, cmd: usize, arg: usize) -> Result<usize>; fn path(&self, buf: &mut [u8]) -> Result<usize>; fn stat(&self, _stat: &mut Stat, fs: &mut FileSystem<D>) -> Result<usize>; - fn sync(&mut self, maps: &mut Fmaps, fs: &mut FileSystem<D>) -> Result<usize>; + fn sync(&mut self, fs: &mut FileSystem<D>) -> Result<usize>; fn truncate(&mut self, len: usize, fs: &mut FileSystem<D>) -> Result<usize>; fn utimens(&mut self, times: &[TimeSpec], fs: &mut FileSystem<D>) -> Result<usize>; } @@ -89,10 +90,10 @@ impl<D: Disk> Resource<D> for DirResource { Ok(self.seek) } - fn fmap(&mut self, _map: &Map, _maps: &mut Fmaps, _fs: &mut FileSystem<D>) -> Result<usize> { + fn fmap(&mut self, _map: &Map, _fs: &mut FileSystem<D>) -> Result<usize> { Err(Error::new(EBADF)) } - fn funmap(&mut self, _maps: &mut Fmaps, _fs: &mut FileSystem<D>) -> Result<usize> { + fn funmap(&mut self, _address: usize, _fs: &mut FileSystem<D>) -> Result<usize> { Err(Error::new(EBADF)) } @@ -167,7 +168,7 @@ impl<D: Disk> Resource<D> for DirResource { Ok(0) } - fn sync(&mut self, _maps: &mut Fmaps, _fs: &mut FileSystem<D>) -> Result<usize> { + fn sync(&mut self, _fs: &mut FileSystem<D>) -> Result<usize> { Err(Error::new(EBADF)) } @@ -180,13 +181,78 @@ impl<D: Disk> Resource<D> for DirResource { } } +pub struct Fmap { + block: u64, + offset: usize, + flags: usize, + data: &'static mut [u8], +} + +impl Fmap { + pub unsafe fn new<D: Disk>(block: u64, map: &Map, fs: &mut FileSystem<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)); + } + + // Read buffer from disk + let buf = slice::from_raw_parts_mut(address, map.size); + let count = match fs.read_node(block, map.offset as u64, buf) { + Ok(ok) => ok, + Err(err) => { + free(address); + return Err(err); + } + }; + + // Make sure remaining data is zeroed + for i in count..buf.len() { + buf[i] = 0; + } + + Ok(Self { + block, + offset: map.offset, + flags: map.flags, + data: &mut buf[..count], + }) + } + + pub fn sync<D: Disk>(&mut self, fs: &mut FileSystem<D>) -> Result<()> { + if self.flags & PROT_WRITE == PROT_WRITE { + let mtime = SystemTime::now().duration_since(UNIX_EPOCH).unwrap(); + fs.write_node(self.block, self.offset as u64, &self.data, mtime.as_secs(), mtime.subsec_nanos())?; + } + Ok(()) + } +} + +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, block: u64, flags: usize, seek: u64, uid: u32, - fmap: Option<(usize, FmapKey)> + fmaps: BTreeMap<usize, Fmap>, } impl FileResource { @@ -197,35 +263,9 @@ impl FileResource { flags: flags, seek: seek, uid: uid, - fmap: None + fmaps: BTreeMap::new(), } } - - fn sync_fmap<D: Disk>(&mut self, maps: &mut Fmaps, fs: &mut FileSystem<D>) -> Result<()> { - if let Some((i, key_exact)) = self.fmap.as_ref() { - let (key_round, value) = maps.index(*i).as_mut().expect("mapping dropped while still referenced"); - - let rel_offset = key_exact.offset - key_round.offset; - // Minimum out of our size and the original file size - let actual_size = (value.actual_size - rel_offset).min(key_exact.size); - - let mtime = SystemTime::now().duration_since(UNIX_EPOCH).unwrap(); - - let mut count = 0; - while count < actual_size { - match fs.write_node(self.block, key_exact.offset as u64 + count as u64, - &value.buffer[rel_offset..][count..actual_size], - mtime.as_secs(), mtime.subsec_nanos())? { - 0 => { - eprintln!("Fmap failed to write whole buffer, encountered EOF early."); - break; - } - n => count += n, - } - } - } - Ok(()) - } } impl<D: Disk> Resource<D> for FileResource { @@ -240,7 +280,7 @@ impl<D: Disk> Resource<D> for FileResource { flags: self.flags, seek: self.seek, uid: self.uid, - fmap: None + fmaps: BTreeMap::new(), })) } @@ -278,7 +318,7 @@ impl<D: Disk> Resource<D> for FileResource { Ok(self.seek as usize) } - fn fmap(&mut self, map: &Map, maps: &mut Fmaps, fs: &mut FileSystem<D>) -> Result<usize> { + fn fmap(&mut self, map: &Map, fs: &mut FileSystem<D>) -> Result<usize> { let accmode = self.flags & O_ACCMODE; if map.flags & PROT_READ > 0 && ! (accmode == O_RDWR || accmode == O_RDONLY) { return Err(Error::new(EBADF)); @@ -288,66 +328,20 @@ impl<D: Disk> Resource<D> for FileResource { } //TODO: PROT_EXEC? - let key_exact = FmapKey { - block: self.block, - offset: map.offset, - size: map.size - }; + let map = unsafe { Fmap::new(self.block, map, fs)? }; + let address = map.data.as_ptr() as usize; + self.fmaps.insert(address, map); + Ok(address) + } - let i = match maps.find_compatible(&key_exact) { - Ok((i, (key_existing, value))) => { - value.refcount += 1; - self.fmap = Some((i, key_exact)); - return Ok(value.buffer.as_ptr() as usize + (key_exact.offset - key_existing.offset)) - }, - Err(None) => { - // This is bad! - // We reached the limit of maps, and we can't reallocate - // because that would invalidate stuff. - // Sorry, nothing personal :( - return Err(Error::new(EBUSY)) - }, - Err(Some(i)) => { - // Can't do stuff in here because lifetime issues - i - } - }; - let key_round = key_exact.round(); - - let mut content = vec![0; key_round.size]; - let mut count = 0; - while count < key_round.size { - match fs.read_node(self.block, key_round.offset as u64 + count as u64, - &mut content[count..key_round.size])? { - 0 => break, - n => count += n - } - } + fn funmap(&mut self, address: usize, fs: &mut FileSystem<D>) -> Result<usize> { + if let Some(mut fmap) = self.fmaps.remove(&address) { + fmap.sync(fs)?; - let value = maps.insert(i, key_round, FmapValue { - buffer: content, - actual_size: count, - refcount: 1 - }); - - self.fmap = Some((i, key_exact)); - Ok(value.buffer.as_ptr() as usize + (key_exact.offset - key_round.offset)) - } - - fn funmap(&mut self, maps: &mut Fmaps, fs: &mut FileSystem<D>) -> Result<usize> { - self.sync_fmap(maps, fs)?; - if let Some((i, _)) = self.fmap.as_ref() { - let value = maps.index(*i); - let clear = { - let (_, value) = value.as_mut().expect("mapping dropped while still referenced"); - value.refcount -= 1; - value.refcount == 0 - }; - if clear { - *value = None; - } + Ok(0) + } else { + Err(Error::new(EINVAL)) } - Ok(0) } fn fchmod(&mut self, mode: u16, fs: &mut FileSystem<D>) -> Result<usize> { @@ -428,8 +422,11 @@ impl<D: Disk> Resource<D> for FileResource { Ok(0) } - fn sync(&mut self, maps: &mut Fmaps, fs: &mut FileSystem<D>) -> Result<usize> { - self.sync_fmap(maps, fs)?; + fn sync(&mut self, fs: &mut FileSystem<D>) -> Result<usize> { + for fmap in self.fmaps.values_mut() { + fmap.sync(fs)?; + } + Ok(0) } @@ -462,3 +459,11 @@ 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!", self.path, self.fmaps.len()); + } + } +} diff --git a/src/mount/redox/scheme.rs b/src/mount/redox/scheme.rs index 198085745a0d3d38a600c0a8d1489015fd57f4a3..8d5dc9fbc1bf0c65c6ede5c0dde1ae17967ff6bd 100644 --- a/src/mount/redox/scheme.rs +++ b/src/mount/redox/scheme.rs @@ -1,6 +1,5 @@ use std::cell::RefCell; use std::collections::BTreeMap; -use std::result::Result as StdResult; use std::str; use std::sync::atomic::{AtomicUsize, Ordering}; use std::time::{SystemTime, UNIX_EPOCH}; @@ -16,83 +15,13 @@ use filesystem::FileSystem; use node::Node; use super::resource::{Resource, DirResource, FileResource}; -use super::spin::Mutex; - -/// The size to round offset/len up to. -/// This ensures more fmaps can share the same memory even with different parameters. -const PAGE_SIZE: usize = 4096; -/// The max amount of fmaps that can be held simultaneously. -/// This restriction is here because we can under no circumstances reallocate, -/// that would invalidate previous mappings. -const FMAP_AMOUNT: usize = 1024; - -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub struct FmapKey { - pub block: u64, - pub offset: usize, - pub size: usize -} -impl FmapKey { - pub fn round(&self) -> FmapKey { - let remainder = self.size % PAGE_SIZE; - FmapKey { - block: self.block, - offset: self.offset - self.offset % PAGE_SIZE, - size: if remainder == 0 { self.size } else { self.size - remainder + PAGE_SIZE } - } - } - pub fn is_compatible(&self, other: &FmapKey) -> bool { - self.block == other.block - && self.offset <= other.offset - && self.offset + self.size >= other.offset + other.size - } -} -#[derive(Clone)] -pub struct FmapValue { - pub buffer: Vec<u8>, - /// The actual file length. Syncing only writes &buffer[..actual_size]. - pub actual_size: usize, - pub refcount: usize -} - -// NOTE: This can NOT reallocate. That would invalidate previous mappings. -pub struct Fmaps(Vec<Option<(FmapKey, FmapValue)>>); -impl Default for Fmaps { - fn default() -> Fmaps { - Fmaps(vec![None; FMAP_AMOUNT]) - } -} - -impl Fmaps { - pub fn find_compatible(&mut self, key: &FmapKey) -> StdResult<(usize, &mut (FmapKey, FmapValue)), Option<usize>> { - let mut first_empty = None; - for (i, entry) in self.0.iter_mut().enumerate() { - match entry { - None if first_empty.is_none() => first_empty = Some(i), - Some(entry) if entry.0.is_compatible(key) => return Ok((i, entry)), - _ => () - } - } - Err(first_empty) - } - pub fn index(&mut self, index: usize) -> &mut Option<(FmapKey, FmapValue)> { - &mut self.0[index] - } - pub fn insert(&mut self, index: usize, key: FmapKey, value: FmapValue) -> &mut FmapValue { - let elem = &mut self.0[index]; - assert!(elem.is_none()); - *elem = Some((key, value)); - - &mut elem.as_mut().unwrap().1 - } -} pub struct FileScheme<D: Disk> { name: String, fs: RefCell<FileSystem<D>>, next_id: AtomicUsize, - files: Mutex<BTreeMap<usize, Box<Resource<D>>>>, - fmaps: Mutex<Fmaps> + files: RefCell<BTreeMap<usize, Box<Resource<D>>>>, + fmap: RefCell<BTreeMap<usize, usize>>, } impl<D: Disk> FileScheme<D> { @@ -101,8 +30,8 @@ impl<D: Disk> FileScheme<D> { name: name, fs: RefCell::new(fs), next_id: AtomicUsize::new(1), - files: Mutex::new(BTreeMap::new()), - fmaps: Mutex::new(Fmaps::default()) + files: RefCell::new(BTreeMap::new()), + fmap: RefCell::new(BTreeMap::new()), } } @@ -381,7 +310,7 @@ impl<D: Disk> Scheme for FileScheme<D> { }; let id = self.next_id.fetch_add(1, Ordering::SeqCst); - self.files.lock().insert(id, resource); + self.files.borrow_mut().insert(id, resource); Ok(id) } @@ -494,7 +423,7 @@ impl<D: Disk> Scheme for FileScheme<D> { return Err(Error::new(EINVAL)); } - let mut files = self.files.lock(); + let mut files = self.files.borrow_mut(); let resource = if let Some(old_resource) = files.get(&old_id) { old_resource.dup()? } else { @@ -510,7 +439,7 @@ impl<D: Disk> Scheme for FileScheme<D> { #[allow(unused_variables)] fn read(&self, id: usize, buf: &mut [u8]) -> Result<usize> { // println!("Read {}, {:X} {}", id, buf.as_ptr() as usize, buf.len()); - let mut files = self.files.lock(); + let mut files = self.files.borrow_mut(); if let Some(file) = files.get_mut(&id) { file.read(buf, &mut self.fs.borrow_mut()) } else { @@ -520,7 +449,7 @@ impl<D: Disk> Scheme for FileScheme<D> { fn write(&self, id: usize, buf: &[u8]) -> Result<usize> { // println!("Write {}, {:X} {}", id, buf.as_ptr() as usize, buf.len()); - let mut files = self.files.lock(); + let mut files = self.files.borrow_mut(); if let Some(file) = files.get_mut(&id) { file.write(buf, &mut self.fs.borrow_mut()) } else { @@ -530,7 +459,7 @@ impl<D: Disk> Scheme for FileScheme<D> { fn seek(&self, id: usize, pos: usize, whence: usize) -> Result<usize> { // println!("Seek {}, {} {}", id, pos, whence); - let mut files = self.files.lock(); + let mut files = self.files.borrow_mut(); if let Some(file) = files.get_mut(&id) { file.seek(pos, whence, &mut self.fs.borrow_mut()) } else { @@ -539,7 +468,7 @@ impl<D: Disk> Scheme for FileScheme<D> { } fn fchmod(&self, id: usize, mode: u16) -> Result<usize> { - let mut files = self.files.lock(); + let mut files = self.files.borrow_mut(); if let Some(file) = files.get_mut(&id) { file.fchmod(mode, &mut self.fs.borrow_mut()) } else { @@ -548,7 +477,7 @@ impl<D: Disk> Scheme for FileScheme<D> { } fn fchown(&self, id: usize, uid: u32, gid: u32) -> Result<usize> { - let mut files = self.files.lock(); + let mut files = self.files.borrow_mut(); if let Some(file) = files.get_mut(&id) { file.fchown(uid, gid, &mut self.fs.borrow_mut()) } else { @@ -557,7 +486,7 @@ impl<D: Disk> Scheme for FileScheme<D> { } fn fcntl(&self, id: usize, cmd: usize, arg: usize) -> Result<usize> { - let mut files = self.files.lock(); + let mut files = self.files.borrow_mut(); if let Some(file) = files.get_mut(&id) { file.fcntl(cmd, arg) } else { @@ -567,7 +496,7 @@ impl<D: Disk> Scheme for FileScheme<D> { fn fpath(&self, id: usize, buf: &mut [u8]) -> Result<usize> { // println!("Fpath {}, {:X} {}", id, buf.as_ptr() as usize, buf.len()); - let files = self.files.lock(); + let files = self.files.borrow_mut(); if let Some(file) = files.get(&id) { let name = self.name.as_bytes(); @@ -596,7 +525,7 @@ impl<D: Disk> Scheme for FileScheme<D> { // println!("Frename {}, {} from {}, {}", id, path, uid, gid); - let files = self.files.lock(); + let files = self.files.borrow_mut(); if let Some(file) = files.get(&id) { //TODO: Check for EINVAL // The new pathname contained a path prefix of the old, or, more generally, @@ -692,7 +621,7 @@ impl<D: Disk> Scheme for FileScheme<D> { fn fstat(&self, id: usize, stat: &mut Stat) -> Result<usize> { // println!("Fstat {}, {:X}", id, stat as *mut Stat as usize); - let files = self.files.lock(); + let files = self.files.borrow_mut(); if let Some(file) = files.get(&id) { file.stat(stat, &mut self.fs.borrow_mut()) } else { @@ -701,7 +630,7 @@ impl<D: Disk> Scheme for FileScheme<D> { } fn fstatvfs(&self, id: usize, stat: &mut StatVfs) -> Result<usize> { - let files = self.files.lock(); + let files = self.files.borrow_mut(); if let Some(_file) = files.get(&id) { let mut fs = self.fs.borrow_mut(); @@ -721,9 +650,9 @@ impl<D: Disk> Scheme for FileScheme<D> { fn fsync(&self, id: usize) -> Result<usize> { // println!("Fsync {}", id); - let mut files = self.files.lock(); + let mut files = self.files.borrow_mut(); if let Some(file) = files.get_mut(&id) { - file.sync(&mut self.fmaps.lock(), &mut self.fs.borrow_mut()) + file.sync(&mut self.fs.borrow_mut()) } else { Err(Error::new(EBADF)) } @@ -731,7 +660,7 @@ impl<D: Disk> Scheme for FileScheme<D> { fn ftruncate(&self, id: usize, len: usize) -> Result<usize> { // println!("Ftruncate {}, {}", id, len); - let mut files = self.files.lock(); + let mut files = self.files.borrow_mut(); if let Some(file) = files.get_mut(&id) { file.truncate(len, &mut self.fs.borrow_mut()) } else { @@ -741,7 +670,7 @@ impl<D: Disk> Scheme for FileScheme<D> { fn futimens(&self, id: usize, times: &[TimeSpec]) -> Result<usize> { // println!("Futimens {}, {}", id, times.len()); - let mut files = self.files.lock(); + let mut files = self.files.borrow_mut(); if let Some(file) = files.get_mut(&id) { file.utimens(times, &mut self.fs.borrow_mut()) } else { @@ -751,19 +680,33 @@ impl<D: Disk> Scheme for FileScheme<D> { fn fmap(&self, id: usize, map: &Map) -> Result<usize> { // println!("Fmap {}, {:?}", id, map); - let mut files = self.files.lock(); + let mut files = self.files.borrow_mut(); if let Some(file) = files.get_mut(&id) { - file.fmap(map, &mut self.fmaps.lock(), &mut self.fs.borrow_mut()) + let address = file.fmap(map, &mut self.fs.borrow_mut())?; + self.fmap.borrow_mut().insert(address, id); + Ok(address) } else { Err(Error::new(EBADF)) } } + fn funmap(&self, address: usize) -> Result<usize> { + if let Some(id) = self.fmap.borrow_mut().remove(&address) { + let mut files = self.files.borrow_mut(); + if let Some(file) = files.get_mut(&id) { + file.funmap(address, &mut self.fs.borrow_mut()) + } else { + Err(Error::new(EINVAL)) + } + } else { + Err(Error::new(EINVAL)) + } + } + fn close(&self, id: usize) -> Result<usize> { // println!("Close {}", id); - let mut files = self.files.lock(); - if let Some(mut file) = files.remove(&id) { - let _ = file.funmap(&mut self.fmaps.lock(), &mut self.fs.borrow_mut()); + let mut files = self.files.borrow_mut(); + if files.remove(&id).is_some() { Ok(0) } else { Err(Error::new(EBADF))