Reimplement fmap/funmap using improvements to kernel
This commit is contained in:
@@ -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)?;
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
extern crate spin;
|
||||
|
||||
use syscall;
|
||||
use syscall::{Packet, Scheme};
|
||||
use std::fs::File;
|
||||
|
||||
+102
-97
@@ -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 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
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
let map = unsafe { Fmap::new(self.block, map, fs)? };
|
||||
let address = map.data.as_ptr() as usize;
|
||||
self.fmaps.insert(address, map);
|
||||
Ok(address)
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
fn funmap(&mut self, address: usize, fs: &mut FileSystem<D>) -> Result<usize> {
|
||||
if let Some(mut fmap) = self.fmaps.remove(&address) {
|
||||
fmap.sync(fs)?;
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+39
-96
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user