mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-26 19:03:27 +00:00
Refine RamFs by extracting immutable metadata from the lock
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
e7298bb276
commit
6ff8497101
@ -1,7 +1,7 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
use core::{
|
use core::{
|
||||||
sync::atomic::{AtomicUsize, Ordering},
|
sync::atomic::{AtomicU64, Ordering},
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -30,39 +30,41 @@ use crate::{
|
|||||||
|
|
||||||
/// A volatile file system whose data and metadata exists only in memory.
|
/// A volatile file system whose data and metadata exists only in memory.
|
||||||
pub struct RamFS {
|
pub struct RamFS {
|
||||||
metadata: RwLock<SuperBlock>,
|
/// The super block
|
||||||
|
sb: SuperBlock,
|
||||||
|
/// Root inode
|
||||||
root: Arc<RamInode>,
|
root: Arc<RamInode>,
|
||||||
inode_allocator: AtomicUsize,
|
/// An inode allocator
|
||||||
|
inode_allocator: AtomicU64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RamFS {
|
impl RamFS {
|
||||||
pub fn new() -> Arc<Self> {
|
pub fn new() -> Arc<Self> {
|
||||||
let sb = SuperBlock::new(RAMFS_MAGIC, BLOCK_SIZE, NAME_MAX);
|
Arc::new_cyclic(|weak_fs| Self {
|
||||||
let root = Arc::new(RamInode(RwMutex::new(Inode_::new_dir(
|
sb: SuperBlock::new(RAMFS_MAGIC, BLOCK_SIZE, NAME_MAX),
|
||||||
ROOT_INO,
|
root: Arc::new_cyclic(|weak_root| RamInode {
|
||||||
|
node: RwMutex::new(Node::new_dir(
|
||||||
InodeMode::from_bits_truncate(0o755),
|
InodeMode::from_bits_truncate(0o755),
|
||||||
&sb,
|
Uid::new_root(),
|
||||||
))));
|
Gid::new_root(),
|
||||||
let ramfs = Arc::new(Self {
|
weak_root.clone(),
|
||||||
metadata: RwLock::new(sb),
|
weak_root.clone(),
|
||||||
root,
|
)),
|
||||||
inode_allocator: AtomicUsize::new(ROOT_INO + 1),
|
ino: ROOT_INO,
|
||||||
});
|
typ: InodeType::Dir,
|
||||||
let mut root = ramfs.root.0.write();
|
this: weak_root.clone(),
|
||||||
root.inner
|
fs: weak_fs.clone(),
|
||||||
.as_direntry_mut()
|
}),
|
||||||
.unwrap()
|
inode_allocator: AtomicU64::new(ROOT_INO + 1),
|
||||||
.init(Arc::downgrade(&ramfs.root), Arc::downgrade(&ramfs.root));
|
})
|
||||||
root.this = Arc::downgrade(&ramfs.root);
|
|
||||||
root.fs = Arc::downgrade(&ramfs);
|
|
||||||
drop(root);
|
|
||||||
ramfs
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alloc_id(&self) -> usize {
|
fn alloc_id(&self) -> u64 {
|
||||||
let next_id = self.inode_allocator.fetch_add(1, Ordering::SeqCst);
|
self.inode_allocator.fetch_add(1, Ordering::SeqCst)
|
||||||
self.metadata.write().files += 1;
|
}
|
||||||
next_id
|
|
||||||
|
fn device_id(&self) -> u64 {
|
||||||
|
0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,7 +79,7 @@ impl FileSystem for RamFS {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn sb(&self) -> SuperBlock {
|
fn sb(&self) -> SuperBlock {
|
||||||
self.metadata.read().clone()
|
self.sb.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flags(&self) -> FsFlags {
|
fn flags(&self) -> FsFlags {
|
||||||
@ -85,68 +87,63 @@ impl FileSystem for RamFS {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RamInode(RwMutex<Inode_>);
|
struct RamInode {
|
||||||
|
/// The mutable part of the inode
|
||||||
struct Inode_ {
|
node: RwMutex<Node>,
|
||||||
inner: Inner,
|
/// Inode number
|
||||||
metadata: Metadata,
|
ino: u64,
|
||||||
|
/// Type of the inode
|
||||||
|
typ: InodeType,
|
||||||
|
/// Reference to self
|
||||||
this: Weak<RamInode>,
|
this: Weak<RamInode>,
|
||||||
|
/// Reference to fs
|
||||||
fs: Weak<RamFS>,
|
fs: Weak<RamFS>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Inode_ {
|
struct Node {
|
||||||
pub fn new_dir(ino: usize, mode: InodeMode, sb: &SuperBlock) -> Self {
|
inner: Inner,
|
||||||
Self {
|
metadata: InodeMeta,
|
||||||
inner: Inner::Dir(DirEntry::new()),
|
|
||||||
metadata: Metadata::new_dir(ino, mode, sb),
|
|
||||||
this: Weak::default(),
|
|
||||||
fs: Weak::default(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_file(
|
impl Node {
|
||||||
ino: usize,
|
pub fn new_dir(
|
||||||
mode: InodeMode,
|
mode: InodeMode,
|
||||||
sb: &SuperBlock,
|
uid: Uid,
|
||||||
weak_inode: Weak<RamInode>,
|
gid: Gid,
|
||||||
|
this: Weak<RamInode>,
|
||||||
|
parent: Weak<RamInode>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
inner: Inner::File(PageCache::new(weak_inode).unwrap()),
|
inner: Inner::Dir(DirEntry::new(this, parent)),
|
||||||
metadata: Metadata::new_file(ino, mode, sb),
|
metadata: InodeMeta::new_dir(mode, uid, gid),
|
||||||
this: Weak::default(),
|
|
||||||
fs: Weak::default(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_symlink(ino: usize, mode: InodeMode, sb: &SuperBlock) -> Self {
|
pub fn new_file(mode: InodeMode, uid: Uid, gid: Gid, this: Weak<RamInode>) -> Self {
|
||||||
|
Self {
|
||||||
|
inner: Inner::File(PageCache::new(this).unwrap()),
|
||||||
|
metadata: InodeMeta::new(mode, uid, gid),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_symlink(mode: InodeMode, uid: Uid, gid: Gid) -> Self {
|
||||||
Self {
|
Self {
|
||||||
inner: Inner::SymLink(String::from("")),
|
inner: Inner::SymLink(String::from("")),
|
||||||
metadata: Metadata::new_symlink(ino, mode, sb),
|
metadata: InodeMeta::new(mode, uid, gid),
|
||||||
this: Weak::default(),
|
|
||||||
fs: Weak::default(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_socket(ino: usize, mode: InodeMode, sb: &SuperBlock) -> Self {
|
pub fn new_socket(mode: InodeMode, uid: Uid, gid: Gid) -> Self {
|
||||||
Self {
|
Self {
|
||||||
inner: Inner::Socket,
|
inner: Inner::Socket,
|
||||||
metadata: Metadata::new_socket(ino, mode, sb),
|
metadata: InodeMeta::new(mode, uid, gid),
|
||||||
this: Weak::default(),
|
|
||||||
fs: Weak::default(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_device(
|
pub fn new_device(mode: InodeMode, uid: Uid, gid: Gid, device: Arc<dyn Device>) -> Self {
|
||||||
ino: usize,
|
|
||||||
mode: InodeMode,
|
|
||||||
sb: &SuperBlock,
|
|
||||||
device: Arc<dyn Device>,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
Self {
|
||||||
metadata: Metadata::new_device(ino, mode, sb, device.as_ref()),
|
|
||||||
inner: Inner::Device(device),
|
inner: Inner::Device(device),
|
||||||
this: Weak::default(),
|
metadata: InodeMeta::new(mode, uid, gid),
|
||||||
fs: Weak::default(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,6 +173,49 @@ impl Inode_ {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
struct InodeMeta {
|
||||||
|
size: usize,
|
||||||
|
blocks: usize,
|
||||||
|
atime: Duration,
|
||||||
|
mtime: Duration,
|
||||||
|
ctime: Duration,
|
||||||
|
mode: InodeMode,
|
||||||
|
nlinks: usize,
|
||||||
|
uid: Uid,
|
||||||
|
gid: Gid,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InodeMeta {
|
||||||
|
pub fn new(mode: InodeMode, uid: Uid, gid: Gid) -> Self {
|
||||||
|
Self {
|
||||||
|
size: 0,
|
||||||
|
blocks: 0,
|
||||||
|
atime: Default::default(),
|
||||||
|
mtime: Default::default(),
|
||||||
|
ctime: Default::default(),
|
||||||
|
mode,
|
||||||
|
nlinks: 1,
|
||||||
|
uid,
|
||||||
|
gid,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_dir(mode: InodeMode, uid: Uid, gid: Gid) -> Self {
|
||||||
|
Self {
|
||||||
|
size: 2,
|
||||||
|
blocks: 1,
|
||||||
|
atime: Default::default(),
|
||||||
|
mtime: Default::default(),
|
||||||
|
ctime: Default::default(),
|
||||||
|
mode,
|
||||||
|
nlinks: 2,
|
||||||
|
uid,
|
||||||
|
gid,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::large_enum_variant)]
|
#[allow(clippy::large_enum_variant)]
|
||||||
enum Inner {
|
enum Inner {
|
||||||
Dir(DirEntry),
|
Dir(DirEntry),
|
||||||
@ -236,19 +276,14 @@ struct DirEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DirEntry {
|
impl DirEntry {
|
||||||
fn new() -> Self {
|
fn new(this: Weak<RamInode>, parent: Weak<RamInode>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
children: SlotVec::new(),
|
children: SlotVec::new(),
|
||||||
this: Weak::default(),
|
this,
|
||||||
parent: Weak::default(),
|
parent,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init(&mut self, this: Weak<RamInode>, parent: Weak<RamInode>) {
|
|
||||||
self.this = this;
|
|
||||||
self.set_parent(parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_parent(&mut self, parent: Weak<RamInode>) {
|
fn set_parent(&mut self, parent: Weak<RamInode>) {
|
||||||
self.parent = parent;
|
self.parent = parent;
|
||||||
}
|
}
|
||||||
@ -299,22 +334,12 @@ impl DirEntry {
|
|||||||
// Read the two special entries("." and "..").
|
// Read the two special entries("." and "..").
|
||||||
if *idx == 0 {
|
if *idx == 0 {
|
||||||
let this_inode = self.this.upgrade().unwrap();
|
let this_inode = self.this.upgrade().unwrap();
|
||||||
visitor.visit(
|
visitor.visit(".", this_inode.ino, this_inode.typ, *idx)?;
|
||||||
".",
|
|
||||||
this_inode.metadata().ino as u64,
|
|
||||||
this_inode.metadata().type_,
|
|
||||||
*idx,
|
|
||||||
)?;
|
|
||||||
*idx += 1;
|
*idx += 1;
|
||||||
}
|
}
|
||||||
if *idx == 1 {
|
if *idx == 1 {
|
||||||
let parent_inode = self.parent.upgrade().unwrap();
|
let parent_inode = self.parent.upgrade().unwrap();
|
||||||
visitor.visit(
|
visitor.visit("..", parent_inode.ino, parent_inode.typ, *idx)?;
|
||||||
"..",
|
|
||||||
parent_inode.metadata().ino as u64,
|
|
||||||
parent_inode.metadata().type_,
|
|
||||||
*idx,
|
|
||||||
)?;
|
|
||||||
*idx += 1;
|
*idx += 1;
|
||||||
}
|
}
|
||||||
// Read the normal child entries.
|
// Read the normal child entries.
|
||||||
@ -325,12 +350,7 @@ impl DirEntry {
|
|||||||
.map(|(offset, (name, child))| (offset + 2, (name, child)))
|
.map(|(offset, (name, child))| (offset + 2, (name, child)))
|
||||||
.skip_while(|(offset, _)| offset < &start_idx)
|
.skip_while(|(offset, _)| offset < &start_idx)
|
||||||
{
|
{
|
||||||
visitor.visit(
|
visitor.visit(name.as_str().unwrap(), child.ino, child.typ, offset)?;
|
||||||
name.as_str().unwrap(),
|
|
||||||
child.metadata().ino as u64,
|
|
||||||
child.metadata().type_,
|
|
||||||
offset,
|
|
||||||
)?;
|
|
||||||
*idx = offset + 1;
|
*idx = offset + 1;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -349,82 +369,80 @@ impl DirEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl RamInode {
|
impl RamInode {
|
||||||
fn new_dir(fs: &Arc<RamFS>, mode: InodeMode, parent: &Weak<Self>) -> Arc<Self> {
|
fn new_dir(
|
||||||
Arc::new_cyclic(|weak_self| {
|
fs: &Arc<RamFS>,
|
||||||
let inode = RamInode(RwMutex::new(Inode_::new_dir(fs.alloc_id(), mode, &fs.sb())));
|
mode: InodeMode,
|
||||||
inode.0.write().fs = Arc::downgrade(fs);
|
uid: Uid,
|
||||||
inode.0.write().this = weak_self.clone();
|
gid: Gid,
|
||||||
inode
|
parent: &Weak<RamInode>,
|
||||||
.0
|
) -> Arc<Self> {
|
||||||
.write()
|
Arc::new_cyclic(|weak_self| RamInode {
|
||||||
.inner
|
node: RwMutex::new(Node::new_dir(
|
||||||
.as_direntry_mut()
|
|
||||||
.unwrap()
|
|
||||||
.init(weak_self.clone(), parent.clone());
|
|
||||||
inode
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new_file(fs: &Arc<RamFS>, mode: InodeMode) -> Arc<Self> {
|
|
||||||
Arc::new_cyclic(|weak_self| {
|
|
||||||
let inode = RamInode(RwMutex::new(Inode_::new_file(
|
|
||||||
fs.alloc_id(),
|
|
||||||
mode,
|
mode,
|
||||||
&fs.sb(),
|
uid,
|
||||||
|
gid,
|
||||||
weak_self.clone(),
|
weak_self.clone(),
|
||||||
)));
|
parent.clone(),
|
||||||
inode.0.write().fs = Arc::downgrade(fs);
|
)),
|
||||||
inode.0.write().this = weak_self.clone();
|
ino: fs.alloc_id(),
|
||||||
inode
|
typ: InodeType::Dir,
|
||||||
|
this: weak_self.clone(),
|
||||||
|
fs: Arc::downgrade(fs),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_socket(fs: &Arc<RamFS>, mode: InodeMode) -> Arc<Self> {
|
fn new_file(fs: &Arc<RamFS>, mode: InodeMode, uid: Uid, gid: Gid) -> Arc<Self> {
|
||||||
Arc::new_cyclic(|weak_self| {
|
Arc::new_cyclic(|weak_self| RamInode {
|
||||||
let inode = RamInode(RwMutex::new(Inode_::new_socket(
|
node: RwMutex::new(Node::new_file(mode, uid, gid, weak_self.clone())),
|
||||||
fs.alloc_id(),
|
ino: fs.alloc_id(),
|
||||||
mode,
|
typ: InodeType::File,
|
||||||
&fs.sb(),
|
this: weak_self.clone(),
|
||||||
)));
|
fs: Arc::downgrade(fs),
|
||||||
inode.0.write().fs = Arc::downgrade(fs);
|
|
||||||
inode.0.write().this = weak_self.clone();
|
|
||||||
inode
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_symlink(fs: &Arc<RamFS>, mode: InodeMode) -> Arc<Self> {
|
fn new_symlink(fs: &Arc<RamFS>, mode: InodeMode, uid: Uid, gid: Gid) -> Arc<Self> {
|
||||||
Arc::new_cyclic(|weak_self| {
|
Arc::new_cyclic(|weak_self| RamInode {
|
||||||
let inode = RamInode(RwMutex::new(Inode_::new_symlink(
|
node: RwMutex::new(Node::new_symlink(mode, uid, gid)),
|
||||||
fs.alloc_id(),
|
ino: fs.alloc_id(),
|
||||||
mode,
|
typ: InodeType::SymLink,
|
||||||
&fs.sb(),
|
this: weak_self.clone(),
|
||||||
)));
|
fs: Arc::downgrade(fs),
|
||||||
inode.0.write().fs = Arc::downgrade(fs);
|
|
||||||
inode.0.write().this = weak_self.clone();
|
|
||||||
inode
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_device(fs: &Arc<RamFS>, mode: InodeMode, device: Arc<dyn Device>) -> Arc<Self> {
|
fn new_socket(fs: &Arc<RamFS>, mode: InodeMode, uid: Uid, gid: Gid) -> Arc<Self> {
|
||||||
Arc::new_cyclic(|weak_self| {
|
Arc::new_cyclic(|weak_self| RamInode {
|
||||||
let inode = RamInode(RwMutex::new(Inode_::new_device(
|
node: RwMutex::new(Node::new_socket(mode, uid, gid)),
|
||||||
fs.alloc_id(),
|
ino: fs.alloc_id(),
|
||||||
mode,
|
typ: InodeType::Socket,
|
||||||
&fs.sb(),
|
this: weak_self.clone(),
|
||||||
device,
|
fs: Arc::downgrade(fs),
|
||||||
)));
|
})
|
||||||
inode.0.write().fs = Arc::downgrade(fs);
|
}
|
||||||
inode.0.write().this = weak_self.clone();
|
|
||||||
inode
|
fn new_device(
|
||||||
|
fs: &Arc<RamFS>,
|
||||||
|
mode: InodeMode,
|
||||||
|
uid: Uid,
|
||||||
|
gid: Gid,
|
||||||
|
device: Arc<dyn Device>,
|
||||||
|
) -> Arc<Self> {
|
||||||
|
Arc::new_cyclic(|weak_self| RamInode {
|
||||||
|
node: RwMutex::new(Node::new_device(mode, uid, gid, device.clone())),
|
||||||
|
ino: fs.alloc_id(),
|
||||||
|
typ: InodeType::from(device.type_()),
|
||||||
|
this: weak_self.clone(),
|
||||||
|
fs: Arc::downgrade(fs),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find(&self, name: &str) -> Result<Arc<Self>> {
|
fn find(&self, name: &str) -> Result<Arc<Self>> {
|
||||||
let self_inode = self.0.read();
|
if self.typ != InodeType::Dir {
|
||||||
if self_inode.metadata.type_ != InodeType::Dir {
|
|
||||||
return_errno_with_message!(Errno::ENOTDIR, "self is not dir");
|
return_errno_with_message!(Errno::ENOTDIR, "self is not dir");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let self_inode = self.node.read();
|
||||||
let (_, inode) = self_inode
|
let (_, inode) = self_inode
|
||||||
.inner
|
.inner
|
||||||
.as_direntry()
|
.as_direntry()
|
||||||
@ -448,13 +466,13 @@ impl PageCacheBackend for RamInode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn npages(&self) -> usize {
|
fn npages(&self) -> usize {
|
||||||
self.0.read().metadata.blocks
|
self.node.read().metadata.blocks
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Inode for RamInode {
|
impl Inode for RamInode {
|
||||||
fn page_cache(&self) -> Option<Vmo<Full>> {
|
fn page_cache(&self) -> Option<Vmo<Full>> {
|
||||||
self.0
|
self.node
|
||||||
.read()
|
.read()
|
||||||
.inner
|
.inner
|
||||||
.as_file()
|
.as_file()
|
||||||
@ -462,7 +480,7 @@ impl Inode for RamInode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> {
|
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> {
|
||||||
let self_inode = self.0.read();
|
let self_inode = self.node.read();
|
||||||
|
|
||||||
if let Some(device) = self_inode.inner.as_device() {
|
if let Some(device) = self_inode.inner.as_device() {
|
||||||
return device.read(buf);
|
return device.read(buf);
|
||||||
@ -488,7 +506,7 @@ impl Inode for RamInode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize> {
|
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize> {
|
||||||
let self_inode = self.0.upread();
|
let self_inode = self.node.upread();
|
||||||
|
|
||||||
if let Some(device) = self_inode.inner.as_device() {
|
if let Some(device) = self_inode.inner.as_device() {
|
||||||
return device.write(buf);
|
return device.write(buf);
|
||||||
@ -517,15 +535,15 @@ impl Inode for RamInode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn size(&self) -> usize {
|
fn size(&self) -> usize {
|
||||||
self.0.read().metadata.size
|
self.node.read().metadata.size
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resize(&self, new_size: usize) -> Result<()> {
|
fn resize(&self, new_size: usize) -> Result<()> {
|
||||||
let self_inode = self.0.upread();
|
if self.typ != InodeType::File {
|
||||||
if self_inode.inner.as_file().is_none() {
|
return_errno_with_message!(Errno::EISDIR, "not regular file");
|
||||||
return_errno!(Errno::EISDIR);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let self_inode = self.node.upread();
|
||||||
let file_size = self_inode.metadata.size;
|
let file_size = self_inode.metadata.size;
|
||||||
if file_size == new_size {
|
if file_size == new_size {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@ -541,53 +559,53 @@ impl Inode for RamInode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn atime(&self) -> Duration {
|
fn atime(&self) -> Duration {
|
||||||
self.0.read().metadata.atime
|
self.node.read().metadata.atime
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_atime(&self, time: Duration) {
|
fn set_atime(&self, time: Duration) {
|
||||||
self.0.write().metadata.atime = time;
|
self.node.write().metadata.atime = time;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mtime(&self) -> Duration {
|
fn mtime(&self) -> Duration {
|
||||||
self.0.read().metadata.mtime
|
self.node.read().metadata.mtime
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_mtime(&self, time: Duration) {
|
fn set_mtime(&self, time: Duration) {
|
||||||
self.0.write().metadata.mtime = time;
|
self.node.write().metadata.mtime = time;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ino(&self) -> u64 {
|
fn ino(&self) -> u64 {
|
||||||
self.0.read().metadata.ino as _
|
self.ino
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_(&self) -> InodeType {
|
fn type_(&self) -> InodeType {
|
||||||
self.0.read().metadata.type_
|
self.typ
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mode(&self) -> Result<InodeMode> {
|
fn mode(&self) -> Result<InodeMode> {
|
||||||
Ok(self.0.read().metadata.mode)
|
Ok(self.node.read().metadata.mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_mode(&self, mode: InodeMode) -> Result<()> {
|
fn set_mode(&self, mode: InodeMode) -> Result<()> {
|
||||||
self.0.write().metadata.mode = mode;
|
self.node.write().metadata.mode = mode;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn owner(&self) -> Result<Uid> {
|
fn owner(&self) -> Result<Uid> {
|
||||||
Ok(self.0.read().metadata.uid)
|
Ok(self.node.read().metadata.uid)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_owner(&self, uid: Uid) -> Result<()> {
|
fn set_owner(&self, uid: Uid) -> Result<()> {
|
||||||
self.0.write().metadata.uid = uid;
|
self.node.write().metadata.uid = uid;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn group(&self) -> Result<Gid> {
|
fn group(&self) -> Result<Gid> {
|
||||||
Ok(self.0.read().metadata.gid)
|
Ok(self.node.read().metadata.gid)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_group(&self, gid: Gid) -> Result<()> {
|
fn set_group(&self, gid: Gid) -> Result<()> {
|
||||||
self.0.write().metadata.gid = gid;
|
self.node.write().metadata.gid = gid;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -600,15 +618,21 @@ impl Inode for RamInode {
|
|||||||
if name.len() > NAME_MAX {
|
if name.len() > NAME_MAX {
|
||||||
return_errno!(Errno::ENAMETOOLONG);
|
return_errno!(Errno::ENAMETOOLONG);
|
||||||
}
|
}
|
||||||
|
if self.typ != InodeType::Dir {
|
||||||
let self_inode = self.0.upread();
|
|
||||||
if self_inode.metadata.type_ != InodeType::Dir {
|
|
||||||
return_errno_with_message!(Errno::ENOTDIR, "self is not dir");
|
return_errno_with_message!(Errno::ENOTDIR, "self is not dir");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let self_inode = self.node.upread();
|
||||||
if self_inode.inner.as_direntry().unwrap().contains_entry(name) {
|
if self_inode.inner.as_direntry().unwrap().contains_entry(name) {
|
||||||
return_errno_with_message!(Errno::EEXIST, "entry exists");
|
return_errno_with_message!(Errno::EEXIST, "entry exists");
|
||||||
}
|
}
|
||||||
let device_inode = RamInode::new_device(&self_inode.fs.upgrade().unwrap(), mode, device);
|
let device_inode = RamInode::new_device(
|
||||||
|
&self.fs.upgrade().unwrap(),
|
||||||
|
mode,
|
||||||
|
Uid::new_root(),
|
||||||
|
Gid::new_root(),
|
||||||
|
device,
|
||||||
|
);
|
||||||
|
|
||||||
let mut self_inode = self_inode.upgrade();
|
let mut self_inode = self_inode.upgrade();
|
||||||
self_inode
|
self_inode
|
||||||
@ -621,27 +645,31 @@ impl Inode for RamInode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn as_device(&self) -> Option<Arc<dyn Device>> {
|
fn as_device(&self) -> Option<Arc<dyn Device>> {
|
||||||
self.0.read().inner.as_device().cloned()
|
self.node.read().inner.as_device().cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result<Arc<dyn Inode>> {
|
fn create(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result<Arc<dyn Inode>> {
|
||||||
if name.len() > NAME_MAX {
|
if name.len() > NAME_MAX {
|
||||||
return_errno!(Errno::ENAMETOOLONG);
|
return_errno!(Errno::ENAMETOOLONG);
|
||||||
}
|
}
|
||||||
|
if self.typ != InodeType::Dir {
|
||||||
let self_inode = self.0.upread();
|
|
||||||
if self_inode.metadata.type_ != InodeType::Dir {
|
|
||||||
return_errno_with_message!(Errno::ENOTDIR, "self is not dir");
|
return_errno_with_message!(Errno::ENOTDIR, "self is not dir");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let self_inode = self.node.upread();
|
||||||
if self_inode.inner.as_direntry().unwrap().contains_entry(name) {
|
if self_inode.inner.as_direntry().unwrap().contains_entry(name) {
|
||||||
return_errno_with_message!(Errno::EEXIST, "entry exists");
|
return_errno_with_message!(Errno::EEXIST, "entry exists");
|
||||||
}
|
}
|
||||||
let fs = self_inode.fs.upgrade().unwrap();
|
let fs = self.fs.upgrade().unwrap();
|
||||||
let new_inode = match type_ {
|
let new_inode = match type_ {
|
||||||
InodeType::File => RamInode::new_file(&fs, mode),
|
InodeType::File => RamInode::new_file(&fs, mode, Uid::new_root(), Gid::new_root()),
|
||||||
InodeType::SymLink => RamInode::new_symlink(&fs, mode),
|
InodeType::SymLink => {
|
||||||
InodeType::Socket => RamInode::new_socket(&fs, mode),
|
RamInode::new_symlink(&fs, mode, Uid::new_root(), Gid::new_root())
|
||||||
InodeType::Dir => RamInode::new_dir(&fs, mode, &self_inode.this),
|
}
|
||||||
|
InodeType::Socket => RamInode::new_socket(&fs, mode, Uid::new_root(), Gid::new_root()),
|
||||||
|
InodeType::Dir => {
|
||||||
|
RamInode::new_dir(&fs, mode, Uid::new_root(), Gid::new_root(), &self.this)
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
panic!("unsupported inode type");
|
panic!("unsupported inode type");
|
||||||
}
|
}
|
||||||
@ -661,10 +689,11 @@ impl Inode for RamInode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn readdir_at(&self, offset: usize, visitor: &mut dyn DirentVisitor) -> Result<usize> {
|
fn readdir_at(&self, offset: usize, visitor: &mut dyn DirentVisitor) -> Result<usize> {
|
||||||
let self_inode = self.0.read();
|
if self.typ != InodeType::Dir {
|
||||||
if self_inode.metadata.type_ != InodeType::Dir {
|
|
||||||
return_errno_with_message!(Errno::ENOTDIR, "self is not dir");
|
return_errno_with_message!(Errno::ENOTDIR, "self is not dir");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let self_inode = self.node.read();
|
||||||
let cnt = self_inode
|
let cnt = self_inode
|
||||||
.inner
|
.inner
|
||||||
.as_direntry()
|
.as_direntry()
|
||||||
@ -677,30 +706,26 @@ impl Inode for RamInode {
|
|||||||
if !Arc::ptr_eq(&self.fs(), &old.fs()) {
|
if !Arc::ptr_eq(&self.fs(), &old.fs()) {
|
||||||
return_errno_with_message!(Errno::EXDEV, "not same fs");
|
return_errno_with_message!(Errno::EXDEV, "not same fs");
|
||||||
}
|
}
|
||||||
|
if self.typ != InodeType::Dir {
|
||||||
|
return_errno_with_message!(Errno::ENOTDIR, "self is not dir");
|
||||||
|
}
|
||||||
let old = old
|
let old = old
|
||||||
.downcast_ref::<RamInode>()
|
.downcast_ref::<RamInode>()
|
||||||
.ok_or(Error::new(Errno::EXDEV))?;
|
.ok_or(Error::new(Errno::EXDEV))?;
|
||||||
let old_arc = {
|
if old.typ == InodeType::Dir {
|
||||||
let old_inode = old.0.read();
|
|
||||||
if old_inode.metadata.type_ == InodeType::Dir {
|
|
||||||
return_errno_with_message!(Errno::EPERM, "old is a dir");
|
return_errno_with_message!(Errno::EPERM, "old is a dir");
|
||||||
}
|
}
|
||||||
old_inode.this.upgrade().unwrap()
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut self_inode = self.0.write();
|
let mut self_inode = self.node.write();
|
||||||
if self_inode.metadata.type_ != InodeType::Dir {
|
|
||||||
return_errno_with_message!(Errno::ENOTDIR, "self is not dir");
|
|
||||||
}
|
|
||||||
let self_dir = self_inode.inner.as_direntry_mut().unwrap();
|
let self_dir = self_inode.inner.as_direntry_mut().unwrap();
|
||||||
if self_dir.contains_entry(name) {
|
if self_dir.contains_entry(name) {
|
||||||
return_errno_with_message!(Errno::EEXIST, "entry exist");
|
return_errno_with_message!(Errno::EEXIST, "entry exist");
|
||||||
}
|
}
|
||||||
|
self_dir.append_entry(name, old.this.upgrade().unwrap());
|
||||||
self_dir.append_entry(name, old_arc);
|
|
||||||
self_inode.inc_size();
|
self_inode.inc_size();
|
||||||
drop(self_inode);
|
drop(self_inode);
|
||||||
old.0.write().inc_nlinks();
|
old.node.write().inc_nlinks();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -710,7 +735,7 @@ impl Inode for RamInode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let target = self.find(name)?;
|
let target = self.find(name)?;
|
||||||
if target.type_() == InodeType::Dir {
|
if target.typ == InodeType::Dir {
|
||||||
return_errno_with_message!(Errno::EISDIR, "unlink on dir");
|
return_errno_with_message!(Errno::EISDIR, "unlink on dir");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -737,10 +762,11 @@ impl Inode for RamInode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let target = self.find(name)?;
|
let target = self.find(name)?;
|
||||||
let target_inode = target.0.read();
|
if target.typ != InodeType::Dir {
|
||||||
if target_inode.metadata.type_ != InodeType::Dir {
|
|
||||||
return_errno_with_message!(Errno::ENOTDIR, "rmdir on not dir");
|
return_errno_with_message!(Errno::ENOTDIR, "rmdir on not dir");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let target_inode = target.node.read();
|
||||||
if !target_inode
|
if !target_inode
|
||||||
.inner
|
.inner
|
||||||
.as_direntry()
|
.as_direntry()
|
||||||
@ -758,9 +784,6 @@ impl Inode for RamInode {
|
|||||||
if !Arc::ptr_eq(&new_target, &target) {
|
if !Arc::ptr_eq(&new_target, &target) {
|
||||||
return_errno!(Errno::ENOENT);
|
return_errno!(Errno::ENOENT);
|
||||||
}
|
}
|
||||||
if target_inode.metadata.type_ != InodeType::Dir {
|
|
||||||
return_errno_with_message!(Errno::ENOTDIR, "rmdir on not dir");
|
|
||||||
}
|
|
||||||
if !target_inode
|
if !target_inode
|
||||||
.inner
|
.inner
|
||||||
.as_direntry()
|
.as_direntry()
|
||||||
@ -783,60 +806,38 @@ impl Inode for RamInode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn rename(&self, old_name: &str, target: &Arc<dyn Inode>, new_name: &str) -> Result<()> {
|
fn rename(&self, old_name: &str, target: &Arc<dyn Inode>, new_name: &str) -> Result<()> {
|
||||||
let target = target
|
|
||||||
.downcast_ref::<RamInode>()
|
|
||||||
.ok_or(Error::new(Errno::EXDEV))?;
|
|
||||||
|
|
||||||
let (self_ino, target_ino) = {
|
|
||||||
if !Arc::ptr_eq(&self.fs(), &target.fs()) {
|
|
||||||
return_errno_with_message!(Errno::EXDEV, "not same fs");
|
|
||||||
}
|
|
||||||
|
|
||||||
let (self_type, self_ino) = {
|
|
||||||
let self_inode = self.0.read();
|
|
||||||
(self_inode.metadata.type_, self_inode.metadata.ino as u64)
|
|
||||||
};
|
|
||||||
let (target_type, target_ino) = {
|
|
||||||
let target_inode = target.0.read();
|
|
||||||
(
|
|
||||||
target_inode.metadata.type_,
|
|
||||||
target_inode.metadata.ino as u64,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
if self_type != InodeType::Dir {
|
|
||||||
return_errno_with_message!(Errno::ENOTDIR, "self is not dir");
|
|
||||||
}
|
|
||||||
if target_type != InodeType::Dir {
|
|
||||||
return_errno_with_message!(Errno::ENOTDIR, "target is not dir");
|
|
||||||
}
|
|
||||||
if old_name == "." || old_name == ".." {
|
if old_name == "." || old_name == ".." {
|
||||||
return_errno_with_message!(Errno::EISDIR, "old_name is . or ..");
|
return_errno_with_message!(Errno::EISDIR, "old_name is . or ..");
|
||||||
}
|
}
|
||||||
if new_name == "." || new_name == ".." {
|
if new_name == "." || new_name == ".." {
|
||||||
return_errno_with_message!(Errno::EISDIR, "new_name is . or ..");
|
return_errno_with_message!(Errno::EISDIR, "new_name is . or ..");
|
||||||
}
|
}
|
||||||
(self_ino, target_ino)
|
|
||||||
};
|
let target = target
|
||||||
|
.downcast_ref::<RamInode>()
|
||||||
|
.ok_or(Error::new(Errno::EXDEV))?;
|
||||||
|
|
||||||
|
if !Arc::ptr_eq(&self.fs(), &target.fs()) {
|
||||||
|
return_errno_with_message!(Errno::EXDEV, "not same fs");
|
||||||
|
}
|
||||||
|
if self.typ != InodeType::Dir {
|
||||||
|
return_errno_with_message!(Errno::ENOTDIR, "self is not dir");
|
||||||
|
}
|
||||||
|
if target.typ != InodeType::Dir {
|
||||||
|
return_errno_with_message!(Errno::ENOTDIR, "target is not dir");
|
||||||
|
}
|
||||||
|
|
||||||
// Perform necessary checks to ensure that `dst_inode` can be replaced by `src_inode`.
|
// Perform necessary checks to ensure that `dst_inode` can be replaced by `src_inode`.
|
||||||
let check_replace_inode =
|
let check_replace_inode =
|
||||||
|src_inode: &Arc<RamInode>, dst_inode: &Arc<RamInode>| -> Result<()> {
|
|src_inode: &Arc<RamInode>, dst_inode: &Arc<RamInode>| -> Result<()> {
|
||||||
let (src_type, src_ino) = {
|
if src_inode.ino == dst_inode.ino {
|
||||||
let src_inode = src_inode.0.read();
|
|
||||||
(src_inode.metadata.type_, src_inode.metadata.ino as u64)
|
|
||||||
};
|
|
||||||
let (dst_type, dst_ino) = {
|
|
||||||
let dst_inode = dst_inode.0.read();
|
|
||||||
(dst_inode.metadata.type_, dst_inode.metadata.ino as u64)
|
|
||||||
};
|
|
||||||
if src_ino == dst_ino {
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
match (src_type, dst_type) {
|
match (src_inode.typ, dst_inode.typ) {
|
||||||
(InodeType::Dir, InodeType::Dir) => {
|
(InodeType::Dir, InodeType::Dir) => {
|
||||||
if !dst_inode
|
if !dst_inode
|
||||||
.0
|
.node
|
||||||
.read()
|
.read()
|
||||||
.inner
|
.inner
|
||||||
.as_direntry()
|
.as_direntry()
|
||||||
@ -858,13 +859,13 @@ impl Inode for RamInode {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Rename in the same directory
|
// Rename in the same directory
|
||||||
if self_ino == target_ino {
|
if self.ino == target.ino {
|
||||||
let mut self_inode = self.0.write();
|
let mut self_inode = self.node.write();
|
||||||
let self_dir = self_inode.inner.as_direntry_mut().unwrap();
|
let self_dir = self_inode.inner.as_direntry_mut().unwrap();
|
||||||
let (src_idx, src_inode) = self_dir
|
let (src_idx, src_inode) = self_dir
|
||||||
.get_entry(old_name)
|
.get_entry(old_name)
|
||||||
.ok_or(Error::new(Errno::ENOENT))?;
|
.ok_or(Error::new(Errno::ENOENT))?;
|
||||||
let is_dir = src_inode.type_() == InodeType::Dir;
|
let is_dir = src_inode.typ == InodeType::Dir;
|
||||||
|
|
||||||
if let Some((dst_idx, dst_inode)) = self_dir.get_entry(new_name) {
|
if let Some((dst_idx, dst_inode)) = self_dir.get_entry(new_name) {
|
||||||
check_replace_inode(&src_inode, &dst_inode)?;
|
check_replace_inode(&src_inode, &dst_inode)?;
|
||||||
@ -881,8 +882,8 @@ impl Inode for RamInode {
|
|||||||
// Or rename across different directories
|
// Or rename across different directories
|
||||||
else {
|
else {
|
||||||
let (mut self_inode, mut target_inode) = write_lock_two_inodes(self, target);
|
let (mut self_inode, mut target_inode) = write_lock_two_inodes(self, target);
|
||||||
let self_inode_arc = self_inode.this.upgrade().unwrap();
|
let self_inode_arc = self.this.upgrade().unwrap();
|
||||||
let target_inode_arc = target_inode.this.upgrade().unwrap();
|
let target_inode_arc = target.this.upgrade().unwrap();
|
||||||
let self_dir = self_inode.inner.as_direntry_mut().unwrap();
|
let self_dir = self_inode.inner.as_direntry_mut().unwrap();
|
||||||
let (src_idx, src_inode) = self_dir
|
let (src_idx, src_inode) = self_dir
|
||||||
.get_entry(old_name)
|
.get_entry(old_name)
|
||||||
@ -891,7 +892,7 @@ impl Inode for RamInode {
|
|||||||
if Arc::ptr_eq(&src_inode, &target_inode_arc) {
|
if Arc::ptr_eq(&src_inode, &target_inode_arc) {
|
||||||
return_errno!(Errno::EINVAL);
|
return_errno!(Errno::EINVAL);
|
||||||
}
|
}
|
||||||
let is_dir = src_inode.type_() == InodeType::Dir;
|
let is_dir = src_inode.typ == InodeType::Dir;
|
||||||
|
|
||||||
let target_dir = target_inode.inner.as_direntry_mut().unwrap();
|
let target_dir = target_inode.inner.as_direntry_mut().unwrap();
|
||||||
if let Some((dst_idx, dst_inode)) = target_dir.get_entry(new_name) {
|
if let Some((dst_idx, dst_inode)) = target_dir.get_entry(new_name) {
|
||||||
@ -921,31 +922,33 @@ impl Inode for RamInode {
|
|||||||
drop(target_inode);
|
drop(target_inode);
|
||||||
if is_dir {
|
if is_dir {
|
||||||
src_inode
|
src_inode
|
||||||
.0
|
.node
|
||||||
.write()
|
.write()
|
||||||
.inner
|
.inner
|
||||||
.as_direntry_mut()
|
.as_direntry_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.set_parent(target.0.read().this.clone());
|
.set_parent(target.this.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_link(&self) -> Result<String> {
|
fn read_link(&self) -> Result<String> {
|
||||||
let self_inode = self.0.read();
|
if self.typ != InodeType::SymLink {
|
||||||
if self_inode.metadata.type_ != InodeType::SymLink {
|
|
||||||
return_errno_with_message!(Errno::EINVAL, "self is not symlink");
|
return_errno_with_message!(Errno::EINVAL, "self is not symlink");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let self_inode = self.node.read();
|
||||||
let link = self_inode.inner.as_symlink().unwrap();
|
let link = self_inode.inner.as_symlink().unwrap();
|
||||||
Ok(String::from(link))
|
Ok(String::from(link))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_link(&self, target: &str) -> Result<()> {
|
fn write_link(&self, target: &str) -> Result<()> {
|
||||||
let mut self_inode = self.0.write();
|
if self.typ != InodeType::SymLink {
|
||||||
if self_inode.metadata.type_ != InodeType::SymLink {
|
|
||||||
return_errno_with_message!(Errno::EINVAL, "self is not symlink");
|
return_errno_with_message!(Errno::EINVAL, "self is not symlink");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut self_inode = self.node.write();
|
||||||
let link = self_inode.inner.as_symlink_mut().unwrap();
|
let link = self_inode.inner.as_symlink_mut().unwrap();
|
||||||
*link = String::from(target);
|
*link = String::from(target);
|
||||||
// Symlink's metadata.blocks should be 0, so just set the size.
|
// Symlink's metadata.blocks should be 0, so just set the size.
|
||||||
@ -954,7 +957,29 @@ impl Inode for RamInode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn metadata(&self) -> Metadata {
|
fn metadata(&self) -> Metadata {
|
||||||
self.0.read().metadata
|
let self_inode = self.node.read();
|
||||||
|
Metadata {
|
||||||
|
dev: self.fs.upgrade().unwrap().device_id(),
|
||||||
|
ino: self.ino as _,
|
||||||
|
size: self_inode.metadata.size,
|
||||||
|
blk_size: BLOCK_SIZE,
|
||||||
|
blocks: self_inode.metadata.blocks,
|
||||||
|
atime: self_inode.metadata.atime,
|
||||||
|
mtime: self_inode.metadata.mtime,
|
||||||
|
ctime: self_inode.metadata.ctime,
|
||||||
|
type_: self.typ,
|
||||||
|
mode: self_inode.metadata.mode,
|
||||||
|
nlinks: self_inode.metadata.nlinks,
|
||||||
|
uid: self_inode.metadata.uid,
|
||||||
|
gid: self_inode.metadata.gid,
|
||||||
|
rdev: {
|
||||||
|
if let Some(device) = self_inode.inner.as_device() {
|
||||||
|
device.id().into()
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sync(&self) -> Result<()> {
|
fn sync(&self) -> Result<()> {
|
||||||
@ -963,7 +988,7 @@ impl Inode for RamInode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
|
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
|
||||||
if let Some(device) = self.0.read().inner.as_device() {
|
if let Some(device) = self.node.read().inner.as_device() {
|
||||||
device.poll(mask, poller)
|
device.poll(mask, poller)
|
||||||
} else {
|
} else {
|
||||||
let events = IoEvents::IN | IoEvents::OUT;
|
let events = IoEvents::IN | IoEvents::OUT;
|
||||||
@ -972,11 +997,11 @@ impl Inode for RamInode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn fs(&self) -> Arc<dyn FileSystem> {
|
fn fs(&self) -> Arc<dyn FileSystem> {
|
||||||
Weak::upgrade(&self.0.read().fs).unwrap()
|
Weak::upgrade(&self.fs).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result<i32> {
|
fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result<i32> {
|
||||||
if let Some(device) = self.0.read().inner.as_device() {
|
if let Some(device) = self.node.read().inner.as_device() {
|
||||||
return device.ioctl(cmd, arg);
|
return device.ioctl(cmd, arg);
|
||||||
}
|
}
|
||||||
return_errno_with_message!(Errno::EINVAL, "ioctl is not supported");
|
return_errno_with_message!(Errno::EINVAL, "ioctl is not supported");
|
||||||
@ -986,16 +1011,14 @@ impl Inode for RamInode {
|
|||||||
fn write_lock_two_inodes<'a>(
|
fn write_lock_two_inodes<'a>(
|
||||||
this: &'a RamInode,
|
this: &'a RamInode,
|
||||||
other: &'a RamInode,
|
other: &'a RamInode,
|
||||||
) -> (RwMutexWriteGuard<'a, Inode_>, RwMutexWriteGuard<'a, Inode_>) {
|
) -> (RwMutexWriteGuard<'a, Node>, RwMutexWriteGuard<'a, Node>) {
|
||||||
// TODO: It involves acquiring two read locks before doing the write locks.
|
if this.ino < other.ino {
|
||||||
// Need to move the immutable part out of the metadata.
|
let this = this.node.write();
|
||||||
if this.ino() < other.ino() {
|
let other = other.node.write();
|
||||||
let this = this.0.write();
|
|
||||||
let other = other.0.write();
|
|
||||||
(this, other)
|
(this, other)
|
||||||
} else {
|
} else {
|
||||||
let other = other.0.write();
|
let other = other.node.write();
|
||||||
let this = this.0.write();
|
let this = this.node.write();
|
||||||
(this, other)
|
(this, other)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,5 +8,5 @@ mod fs;
|
|||||||
|
|
||||||
const RAMFS_MAGIC: u64 = 0x0102_1994;
|
const RAMFS_MAGIC: u64 = 0x0102_1994;
|
||||||
const BLOCK_SIZE: usize = 4096;
|
const BLOCK_SIZE: usize = 4096;
|
||||||
const ROOT_INO: usize = 1;
|
const ROOT_INO: u64 = 1;
|
||||||
const NAME_MAX: usize = 255;
|
const NAME_MAX: usize = 255;
|
||||||
|
Reference in New Issue
Block a user