mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-27 11:23:25 +00:00
Optimize the RamFs to reduce the use of redundant locks
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
27bcece750
commit
e6b0fd8aa3
@ -418,6 +418,21 @@ impl RamInode {
|
|||||||
inode
|
inode
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn find(&self, name: &str) -> Result<Arc<Self>> {
|
||||||
|
let self_inode = self.0.read();
|
||||||
|
if self_inode.metadata.type_ != InodeType::Dir {
|
||||||
|
return_errno_with_message!(Errno::ENOTDIR, "self is not dir");
|
||||||
|
}
|
||||||
|
|
||||||
|
let (_, inode) = self_inode
|
||||||
|
.inner
|
||||||
|
.as_direntry()
|
||||||
|
.unwrap()
|
||||||
|
.get_entry(name)
|
||||||
|
.ok_or(Error::new(Errno::ENOENT))?;
|
||||||
|
Ok(inode)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PageCacheBackend for RamInode {
|
impl PageCacheBackend for RamInode {
|
||||||
@ -447,11 +462,12 @@ 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> {
|
||||||
if let Some(device) = self.0.read().inner.as_device() {
|
let self_inode = self.0.read();
|
||||||
|
|
||||||
|
if let Some(device) = self_inode.inner.as_device() {
|
||||||
return device.read(buf);
|
return device.read(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
let self_inode = self.0.read();
|
|
||||||
let Some(page_cache) = self_inode.inner.as_file() else {
|
let Some(page_cache) = self_inode.inner.as_file() else {
|
||||||
return_errno_with_message!(Errno::EISDIR, "read is not supported");
|
return_errno_with_message!(Errno::EISDIR, "read is not supported");
|
||||||
};
|
};
|
||||||
@ -472,11 +488,12 @@ impl Inode for RamInode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize> {
|
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize> {
|
||||||
if let Some(device) = self.0.read().inner.as_device() {
|
let self_inode = self.0.upread();
|
||||||
|
|
||||||
|
if let Some(device) = self_inode.inner.as_device() {
|
||||||
return device.write(buf);
|
return device.write(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
let self_inode = self.0.upread();
|
|
||||||
let Some(page_cache) = self_inode.inner.as_file() else {
|
let Some(page_cache) = self_inode.inner.as_file() else {
|
||||||
return_errno_with_message!(Errno::EISDIR, "write is not supported");
|
return_errno_with_message!(Errno::EISDIR, "write is not supported");
|
||||||
};
|
};
|
||||||
@ -580,18 +597,20 @@ impl Inode for RamInode {
|
|||||||
mode: InodeMode,
|
mode: InodeMode,
|
||||||
device: Arc<dyn Device>,
|
device: Arc<dyn Device>,
|
||||||
) -> Result<Arc<dyn Inode>> {
|
) -> Result<Arc<dyn Inode>> {
|
||||||
if self.0.read().metadata.type_ != InodeType::Dir {
|
|
||||||
return_errno_with_message!(Errno::ENOTDIR, "self is not dir");
|
|
||||||
}
|
|
||||||
if name.len() > NAME_MAX {
|
if name.len() > NAME_MAX {
|
||||||
return_errno!(Errno::ENAMETOOLONG);
|
return_errno!(Errno::ENAMETOOLONG);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut self_inode = self.0.write();
|
let self_inode = self.0.upread();
|
||||||
|
if self_inode.metadata.type_ != InodeType::Dir {
|
||||||
|
return_errno_with_message!(Errno::ENOTDIR, "self is not dir");
|
||||||
|
}
|
||||||
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_inode.fs.upgrade().unwrap(), mode, device);
|
||||||
|
|
||||||
|
let mut self_inode = self_inode.upgrade();
|
||||||
self_inode
|
self_inode
|
||||||
.inner
|
.inner
|
||||||
.as_direntry_mut()
|
.as_direntry_mut()
|
||||||
@ -606,14 +625,14 @@ impl Inode for RamInode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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 self.0.read().metadata.type_ != InodeType::Dir {
|
|
||||||
return_errno_with_message!(Errno::ENOTDIR, "self is not dir");
|
|
||||||
}
|
|
||||||
if name.len() > NAME_MAX {
|
if name.len() > NAME_MAX {
|
||||||
return_errno!(Errno::ENAMETOOLONG);
|
return_errno!(Errno::ENAMETOOLONG);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut self_inode = self.0.write();
|
let self_inode = self.0.upread();
|
||||||
|
if self_inode.metadata.type_ != InodeType::Dir {
|
||||||
|
return_errno_with_message!(Errno::ENOTDIR, "self is not dir");
|
||||||
|
}
|
||||||
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");
|
||||||
}
|
}
|
||||||
@ -622,15 +641,16 @@ impl Inode for RamInode {
|
|||||||
InodeType::File => RamInode::new_file(&fs, mode),
|
InodeType::File => RamInode::new_file(&fs, mode),
|
||||||
InodeType::SymLink => RamInode::new_symlink(&fs, mode),
|
InodeType::SymLink => RamInode::new_symlink(&fs, mode),
|
||||||
InodeType::Socket => RamInode::new_socket(&fs, mode),
|
InodeType::Socket => RamInode::new_socket(&fs, mode),
|
||||||
InodeType::Dir => {
|
InodeType::Dir => RamInode::new_dir(&fs, mode, &self_inode.this),
|
||||||
let dir_inode = RamInode::new_dir(&fs, mode, &self_inode.this);
|
|
||||||
self_inode.inc_nlinks();
|
|
||||||
dir_inode
|
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
panic!("unsupported inode type");
|
panic!("unsupported inode type");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut self_inode = self_inode.upgrade();
|
||||||
|
if InodeType::Dir == type_ {
|
||||||
|
self_inode.inc_nlinks();
|
||||||
|
}
|
||||||
self_inode
|
self_inode
|
||||||
.inner
|
.inner
|
||||||
.as_direntry_mut()
|
.as_direntry_mut()
|
||||||
@ -641,10 +661,10 @@ 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> {
|
||||||
if self.0.read().metadata.type_ != InodeType::Dir {
|
let self_inode = self.0.read();
|
||||||
|
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.0.read();
|
|
||||||
let cnt = self_inode
|
let cnt = self_inode
|
||||||
.inner
|
.inner
|
||||||
.as_direntry()
|
.as_direntry()
|
||||||
@ -654,25 +674,30 @@ impl Inode for RamInode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn link(&self, old: &Arc<dyn Inode>, name: &str) -> Result<()> {
|
fn link(&self, old: &Arc<dyn Inode>, name: &str) -> Result<()> {
|
||||||
if self.0.read().metadata.type_ != InodeType::Dir {
|
|
||||||
return_errno_with_message!(Errno::ENOTDIR, "self is not dir");
|
|
||||||
}
|
|
||||||
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");
|
||||||
}
|
}
|
||||||
let old = old
|
let old = old
|
||||||
.downcast_ref::<RamInode>()
|
.downcast_ref::<RamInode>()
|
||||||
.ok_or(Error::new(Errno::EXDEV))?;
|
.ok_or(Error::new(Errno::EXDEV))?;
|
||||||
if old.0.read().metadata.type_ == InodeType::Dir {
|
let old_arc = {
|
||||||
return_errno_with_message!(Errno::EPERM, "old is a dir");
|
let old_inode = old.0.read();
|
||||||
}
|
if old_inode.metadata.type_ == InodeType::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.0.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.0.read().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.0.write().inc_nlinks();
|
||||||
@ -680,44 +705,63 @@ impl Inode for RamInode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn unlink(&self, name: &str) -> Result<()> {
|
fn unlink(&self, name: &str) -> Result<()> {
|
||||||
if self.0.read().metadata.type_ != InodeType::Dir {
|
|
||||||
return_errno_with_message!(Errno::ENOTDIR, "self is not dir");
|
|
||||||
}
|
|
||||||
if name == "." || name == ".." {
|
if name == "." || name == ".." {
|
||||||
return_errno_with_message!(Errno::EISDIR, "unlink . or ..");
|
return_errno_with_message!(Errno::EISDIR, "unlink . or ..");
|
||||||
}
|
}
|
||||||
let mut self_inode = self.0.write();
|
|
||||||
let self_dir = self_inode.inner.as_direntry_mut().unwrap();
|
let target = self.find(name)?;
|
||||||
let (idx, target) = self_dir.get_entry(name).ok_or(Error::new(Errno::ENOENT))?;
|
if target.type_() == InodeType::Dir {
|
||||||
if target.0.read().metadata.type_ == InodeType::Dir {
|
|
||||||
return_errno_with_message!(Errno::EISDIR, "unlink on dir");
|
return_errno_with_message!(Errno::EISDIR, "unlink on dir");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// When we got the lock, the dir may have been modified by another thread
|
||||||
|
let (mut self_inode, mut target_inode) = write_lock_two_inodes(self, &target);
|
||||||
|
let self_dir = self_inode.inner.as_direntry_mut().unwrap();
|
||||||
|
let (idx, new_target) = self_dir.get_entry(name).ok_or(Error::new(Errno::ENOENT))?;
|
||||||
|
if !Arc::ptr_eq(&new_target, &target) {
|
||||||
|
return_errno!(Errno::ENOENT);
|
||||||
|
}
|
||||||
|
|
||||||
self_dir.remove_entry(idx);
|
self_dir.remove_entry(idx);
|
||||||
self_inode.dec_size();
|
self_inode.dec_size();
|
||||||
drop(self_inode);
|
target_inode.dec_nlinks();
|
||||||
target.0.write().dec_nlinks();
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rmdir(&self, name: &str) -> Result<()> {
|
fn rmdir(&self, name: &str) -> Result<()> {
|
||||||
if self.0.read().metadata.type_ != InodeType::Dir {
|
|
||||||
return_errno_with_message!(Errno::ENOTDIR, "self is not dir");
|
|
||||||
}
|
|
||||||
if name == "." {
|
if name == "." {
|
||||||
return_errno_with_message!(Errno::EINVAL, "rmdir on .");
|
return_errno_with_message!(Errno::EINVAL, "rmdir on .");
|
||||||
}
|
}
|
||||||
if name == ".." {
|
if name == ".." {
|
||||||
return_errno_with_message!(Errno::ENOTEMPTY, "rmdir on ..");
|
return_errno_with_message!(Errno::ENOTEMPTY, "rmdir on ..");
|
||||||
}
|
}
|
||||||
let mut self_inode = self.0.write();
|
|
||||||
let self_dir = self_inode.inner.as_direntry_mut().unwrap();
|
let target = self.find(name)?;
|
||||||
let (idx, target) = self_dir.get_entry(name).ok_or(Error::new(Errno::ENOENT))?;
|
let target_inode = target.0.read();
|
||||||
if target.0.read().metadata.type_ != 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");
|
||||||
}
|
}
|
||||||
if !target
|
if !target_inode
|
||||||
.0
|
.inner
|
||||||
.read()
|
.as_direntry()
|
||||||
|
.unwrap()
|
||||||
|
.is_empty_children()
|
||||||
|
{
|
||||||
|
return_errno_with_message!(Errno::ENOTEMPTY, "dir not empty");
|
||||||
|
}
|
||||||
|
drop(target_inode);
|
||||||
|
|
||||||
|
// When we got the lock, the dir may have been modified by another thread
|
||||||
|
let (mut self_inode, mut target_inode) = write_lock_two_inodes(self, &target);
|
||||||
|
let self_dir = self_inode.inner.as_direntry_mut().unwrap();
|
||||||
|
let (idx, new_target) = self_dir.get_entry(name).ok_or(Error::new(Errno::ENOENT))?;
|
||||||
|
if !Arc::ptr_eq(&new_target, &target) {
|
||||||
|
return_errno!(Errno::ENOENT);
|
||||||
|
}
|
||||||
|
if target_inode.metadata.type_ != InodeType::Dir {
|
||||||
|
return_errno_with_message!(Errno::ENOTDIR, "rmdir on not dir");
|
||||||
|
}
|
||||||
|
if !target_inode
|
||||||
.inner
|
.inner
|
||||||
.as_direntry()
|
.as_direntry()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@ -728,57 +772,68 @@ impl Inode for RamInode {
|
|||||||
self_dir.remove_entry(idx);
|
self_dir.remove_entry(idx);
|
||||||
self_inode.dec_size();
|
self_inode.dec_size();
|
||||||
self_inode.dec_nlinks();
|
self_inode.dec_nlinks();
|
||||||
drop(self_inode);
|
|
||||||
let mut target_inode = target.0.write();
|
|
||||||
target_inode.dec_nlinks();
|
target_inode.dec_nlinks();
|
||||||
target_inode.dec_nlinks();
|
target_inode.dec_nlinks();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lookup(&self, name: &str) -> Result<Arc<dyn Inode>> {
|
fn lookup(&self, name: &str) -> Result<Arc<dyn Inode>> {
|
||||||
if self.0.read().metadata.type_ != InodeType::Dir {
|
let inode = self.find(name)?;
|
||||||
return_errno_with_message!(Errno::ENOTDIR, "self is not dir");
|
|
||||||
}
|
|
||||||
|
|
||||||
let (_, inode) = self
|
|
||||||
.0
|
|
||||||
.read()
|
|
||||||
.inner
|
|
||||||
.as_direntry()
|
|
||||||
.unwrap()
|
|
||||||
.get_entry(name)
|
|
||||||
.ok_or(Error::new(Errno::ENOENT))?;
|
|
||||||
Ok(inode as _)
|
Ok(inode as _)
|
||||||
}
|
}
|
||||||
|
|
||||||
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<()> {
|
||||||
if self.0.read().metadata.type_ != InodeType::Dir {
|
|
||||||
return_errno_with_message!(Errno::ENOTDIR, "self is not dir");
|
|
||||||
}
|
|
||||||
if !Arc::ptr_eq(&self.fs(), &target.fs()) {
|
|
||||||
return_errno_with_message!(Errno::EXDEV, "not same fs");
|
|
||||||
}
|
|
||||||
let target = target
|
let target = target
|
||||||
.downcast_ref::<RamInode>()
|
.downcast_ref::<RamInode>()
|
||||||
.ok_or(Error::new(Errno::EXDEV))?;
|
.ok_or(Error::new(Errno::EXDEV))?;
|
||||||
if target.0.read().metadata.type_ != InodeType::Dir {
|
|
||||||
return_errno_with_message!(Errno::ENOTDIR, "target is not dir");
|
let (self_ino, target_ino) = {
|
||||||
}
|
if !Arc::ptr_eq(&self.fs(), &target.fs()) {
|
||||||
if old_name == "." || old_name == ".." {
|
return_errno_with_message!(Errno::EXDEV, "not same fs");
|
||||||
return_errno_with_message!(Errno::EISDIR, "old_name is . or ..");
|
}
|
||||||
}
|
|
||||||
if new_name == "." || new_name == ".." {
|
let (self_type, self_ino) = {
|
||||||
return_errno_with_message!(Errno::EISDIR, "new_name is . or ..");
|
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 == ".." {
|
||||||
|
return_errno_with_message!(Errno::EISDIR, "old_name is . or ..");
|
||||||
|
}
|
||||||
|
if new_name == "." || new_name == ".." {
|
||||||
|
return_errno_with_message!(Errno::EISDIR, "new_name is . or ..");
|
||||||
|
}
|
||||||
|
(self_ino, target_ino)
|
||||||
|
};
|
||||||
|
|
||||||
// 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<()> {
|
||||||
if src_inode.metadata().ino == dst_inode.metadata().ino {
|
let (src_type, src_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_inode.metadata().type_, dst_inode.metadata().type_) {
|
match (src_type, dst_type) {
|
||||||
(InodeType::Dir, InodeType::Dir) => {
|
(InodeType::Dir, InodeType::Dir) => {
|
||||||
if !dst_inode
|
if !dst_inode
|
||||||
.0
|
.0
|
||||||
@ -803,13 +858,13 @@ impl Inode for RamInode {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Rename in the same directory
|
// Rename in the same directory
|
||||||
if self.metadata().ino == target.metadata().ino {
|
if self_ino == target_ino {
|
||||||
let mut self_inode = self.0.write();
|
let mut self_inode = self.0.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.0.read().metadata.type_ == InodeType::Dir;
|
let is_dir = src_inode.type_() == 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)?;
|
||||||
@ -836,7 +891,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.0.read().metadata.type_ == InodeType::Dir;
|
let is_dir = src_inode.type_() == 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) {
|
||||||
@ -878,19 +933,19 @@ impl Inode for RamInode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn read_link(&self) -> Result<String> {
|
fn read_link(&self) -> Result<String> {
|
||||||
if self.0.read().metadata.type_ != InodeType::SymLink {
|
let self_inode = self.0.read();
|
||||||
|
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.0.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<()> {
|
||||||
if self.0.read().metadata.type_ != InodeType::SymLink {
|
let mut self_inode = self.0.write();
|
||||||
|
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.0.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.
|
||||||
@ -932,7 +987,9 @@ 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, Inode_>, RwMutexWriteGuard<'a, Inode_>) {
|
||||||
if this.0.read().metadata.ino < other.0.read().metadata.ino {
|
// TODO: It involves acquiring two read locks before doing the write locks.
|
||||||
|
// Need to move the immutable part out of the metadata.
|
||||||
|
if this.ino() < other.ino() {
|
||||||
let this = this.0.write();
|
let this = this.0.write();
|
||||||
let other = other.0.write();
|
let other = other.0.write();
|
||||||
(this, other)
|
(this, other)
|
||||||
|
Reference in New Issue
Block a user