Fixes for shm handling
This commit is contained in:
committed by
Jeremy Soller
parent
2c423e9a44
commit
97cefd26a1
+121
-9
@@ -5,13 +5,15 @@ use std::{
|
||||
rc::Rc,
|
||||
};
|
||||
use syscall::{
|
||||
error::*, schemev2::NewFdFlags, Error, Map, MapFlags, Result, MAP_PRIVATE, PAGE_SIZE,
|
||||
error::*, schemev2::NewFdFlags, Error, Map, MapFlags, Result, MAP_PRIVATE, MAP_SHARED,
|
||||
PAGE_SIZE, PROT_READ, PROT_WRITE,
|
||||
};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct ShmHandle {
|
||||
buffer: Option<MmapGuard>,
|
||||
refs: usize,
|
||||
unlinked: bool,
|
||||
}
|
||||
pub struct ShmScheme {
|
||||
maps: HashMap<Rc<str>, ShmHandle>,
|
||||
@@ -29,12 +31,23 @@ impl ShmScheme {
|
||||
}
|
||||
|
||||
impl SchemeSync for ShmScheme {
|
||||
fn open(&mut self, path: &str, _flags: usize, _ctx: &CallerCtx) -> Result<OpenResult> {
|
||||
//FIXME: Handle O_RDONLY/O_WRONLY/O_RDWR
|
||||
fn open(&mut self, path: &str, flags: usize, _ctx: &CallerCtx) -> Result<OpenResult> {
|
||||
let path = Rc::from(path);
|
||||
let entry = self
|
||||
.maps
|
||||
.entry(Rc::clone(&path))
|
||||
.or_insert(ShmHandle::default());
|
||||
let entry = match self.maps.entry(Rc::clone(&path)) {
|
||||
Entry::Occupied(mut e) => {
|
||||
if flags & syscall::O_EXCL != 0 && flags & syscall::O_CREAT != 0 {
|
||||
return Err(Error::new(EEXIST));
|
||||
}
|
||||
e.into_mut()
|
||||
}
|
||||
Entry::Vacant(e) => {
|
||||
if flags & syscall::O_CREAT == 0 {
|
||||
return Err(Error::new(ENOENT));
|
||||
}
|
||||
e.insert(ShmHandle::default())
|
||||
}
|
||||
};
|
||||
entry.refs += 1;
|
||||
self.handles.insert(self.next_id, path);
|
||||
|
||||
@@ -42,12 +55,12 @@ impl SchemeSync for ShmScheme {
|
||||
self.next_id += 1;
|
||||
Ok(OpenResult::ThisScheme {
|
||||
number: id,
|
||||
flags: NewFdFlags::empty(),
|
||||
flags: NewFdFlags::POSITIONED,
|
||||
})
|
||||
}
|
||||
fn fpath(&mut self, id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> Result<usize> {
|
||||
// Write scheme name
|
||||
const PREFIX: &[u8] = b"shm:";
|
||||
const PREFIX: &[u8] = b"/scheme/shm/";
|
||||
let len = cmp::min(PREFIX.len(), buf.len());
|
||||
buf[..len].copy_from_slice(&PREFIX[..len]);
|
||||
if len < PREFIX.len() {
|
||||
@@ -68,10 +81,32 @@ impl SchemeSync for ShmScheme {
|
||||
Entry::Vacant(_) => panic!("handle pointing to nothing"),
|
||||
};
|
||||
entry.get_mut().refs -= 1;
|
||||
if entry.get().refs == 0 && entry.get().unlinked {
|
||||
// There is no other reference to this entry, drop
|
||||
entry.remove_entry();
|
||||
}
|
||||
}
|
||||
fn unlink(&mut self, path: &str, ctx: &CallerCtx) -> Result<()> {
|
||||
let path = Rc::from(path);
|
||||
let mut entry = match self.maps.entry(Rc::clone(&path)) {
|
||||
Entry::Occupied(e) => e,
|
||||
Entry::Vacant(_) => return Err(Error::new(ENOENT)),
|
||||
};
|
||||
|
||||
entry.get_mut().unlinked = true;
|
||||
if entry.get().refs == 0 {
|
||||
// There is no other reference to this entry, drop
|
||||
entry.remove_entry();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
fn ftruncate(&mut self, id: usize, len: u64, _ctx: &CallerCtx) -> Result<()> {
|
||||
let path = self.handles.get(&id).ok_or(Error::new(EBADF))?;
|
||||
self.maps
|
||||
.get_mut(path)
|
||||
.expect("handle pointing to nothing")
|
||||
.buffer = Some(MmapGuard::alloc((len as usize).div_ceil(PAGE_SIZE))?);
|
||||
Ok(())
|
||||
}
|
||||
fn mmap_prep(
|
||||
&mut self,
|
||||
@@ -95,12 +130,51 @@ impl SchemeSync for ShmScheme {
|
||||
}
|
||||
Ok(buf.as_ptr() + offset as usize)
|
||||
}
|
||||
//TODO: this should be only handled by ftruncate
|
||||
ref mut buf @ None => {
|
||||
*buf = Some(MmapGuard::alloc(size.div_ceil(PAGE_SIZE))?);
|
||||
Ok(buf.as_mut().unwrap().as_ptr() + offset as usize)
|
||||
}
|
||||
}
|
||||
}
|
||||
fn read(
|
||||
&mut self,
|
||||
id: usize,
|
||||
buf: &mut [u8],
|
||||
offset: u64,
|
||||
fcntl_flags: u32,
|
||||
ctx: &CallerCtx,
|
||||
) -> Result<usize> {
|
||||
let path = self.handles.get(&id).ok_or(Error::new(EBADF))?;
|
||||
match self
|
||||
.maps
|
||||
.get_mut(path)
|
||||
.expect("handle pointing to nothing")
|
||||
.buffer
|
||||
{
|
||||
Some(ref mut map) => map.read(offset as usize, buf),
|
||||
None => Err(Error::new(ERANGE)),
|
||||
}
|
||||
}
|
||||
fn write(
|
||||
&mut self,
|
||||
id: usize,
|
||||
buf: &[u8],
|
||||
offset: u64,
|
||||
fcntl_flags: u32,
|
||||
ctx: &CallerCtx,
|
||||
) -> Result<usize> {
|
||||
let path = self.handles.get(&id).ok_or(Error::new(EBADF))?;
|
||||
match self
|
||||
.maps
|
||||
.get_mut(path)
|
||||
.expect("handle pointing to nothing")
|
||||
.buffer
|
||||
{
|
||||
Some(ref mut map) => map.write(offset as usize, buf),
|
||||
None => Err(Error::new(ERANGE)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MmapGuard {
|
||||
@@ -116,7 +190,7 @@ impl MmapGuard {
|
||||
&Map {
|
||||
offset: 0,
|
||||
size,
|
||||
flags: MAP_PRIVATE,
|
||||
flags: MAP_PRIVATE | PROT_READ | PROT_WRITE,
|
||||
address: 0,
|
||||
},
|
||||
)
|
||||
@@ -130,6 +204,44 @@ impl MmapGuard {
|
||||
pub fn as_ptr(&self) -> usize {
|
||||
self.base
|
||||
}
|
||||
pub fn as_slice(&self) -> &[u8] {
|
||||
unsafe { core::slice::from_raw_parts(self.base as *const u8, self.size) }
|
||||
}
|
||||
pub fn as_slice_mut(&mut self) -> &mut [u8] {
|
||||
unsafe { core::slice::from_raw_parts_mut(self.base as *mut u8, self.size) }
|
||||
}
|
||||
pub fn read(&self, offset: usize, buf: &mut [u8]) -> Result<usize> {
|
||||
let read_len = buf.len();
|
||||
let end = offset
|
||||
.checked_add(read_len)
|
||||
.ok_or_else(|| Error::new(ERANGE))?;
|
||||
|
||||
if end > self.size {
|
||||
return Err(Error::new(ERANGE));
|
||||
}
|
||||
|
||||
let mmap_slice = Self::as_slice(self);
|
||||
let source_slice = &mmap_slice[offset..end];
|
||||
buf.copy_from_slice(source_slice);
|
||||
|
||||
Ok(read_len)
|
||||
}
|
||||
pub fn write(&mut self, offset: usize, buf: &[u8]) -> Result<usize> {
|
||||
let write_len = buf.len();
|
||||
let end = offset
|
||||
.checked_add(write_len)
|
||||
.ok_or_else(|| Error::new(ERANGE))?;
|
||||
|
||||
if end > self.size {
|
||||
return Err(Error::new(ERANGE));
|
||||
}
|
||||
|
||||
let mmap_slice = Self::as_slice_mut(self);
|
||||
let dest_slice = &mut mmap_slice[offset..end];
|
||||
dest_slice.copy_from_slice(buf);
|
||||
|
||||
Ok(write_len)
|
||||
}
|
||||
}
|
||||
impl Drop for MmapGuard {
|
||||
fn drop(&mut self) {
|
||||
|
||||
Reference in New Issue
Block a user