Minor improvements to ext2 inode

This commit is contained in:
Shaowei Song
2024-12-26 16:38:38 +00:00
committed by Tate, Hongliang Tian
parent 0799976018
commit 4d5d0942ad

View File

@ -95,16 +95,18 @@ impl Inode {
} }
pub fn resize(&self, new_size: usize) -> Result<()> { pub fn resize(&self, new_size: usize) -> Result<()> {
let inner = self.inner.upread(); if self.type_ != InodeType::File {
if inner.inode_type() != InodeType::File {
return_errno!(Errno::EISDIR); return_errno!(Errno::EISDIR);
} }
let inner = self.inner.upread();
if new_size == inner.file_size() { if new_size == inner.file_size() {
return Ok(()); return Ok(());
} }
let mut inner = inner.upgrade(); let mut inner = inner.upgrade();
inner.resize(new_size)?; inner.resize(new_size)?;
let now = now(); let now = now();
inner.set_mtime(now); inner.set_mtime(now);
inner.set_ctime(now); inner.set_ctime(now);
@ -121,11 +123,11 @@ impl Inode {
if name.len() > MAX_FNAME_LEN { if name.len() > MAX_FNAME_LEN {
return_errno!(Errno::ENAMETOOLONG); return_errno!(Errno::ENAMETOOLONG);
} }
if self.type_ != InodeType::Dir {
let inner = self.inner.upread();
if inner.inode_type() != InodeType::Dir {
return_errno!(Errno::ENOTDIR); return_errno!(Errno::ENOTDIR);
} }
let inner = self.inner.upread();
if inner.hard_links() == 0 { if inner.hard_links() == 0 {
return_errno_with_message!(Errno::ENOENT, "dir removed"); return_errno_with_message!(Errno::ENOENT, "dir removed");
} }
@ -171,11 +173,11 @@ impl Inode {
if name.len() > MAX_FNAME_LEN { if name.len() > MAX_FNAME_LEN {
return_errno!(Errno::ENAMETOOLONG); return_errno!(Errno::ENAMETOOLONG);
} }
if self.type_ != InodeType::Dir {
let inner = self.inner.read();
if inner.inode_type() != InodeType::Dir {
return_errno!(Errno::ENOTDIR); return_errno!(Errno::ENOTDIR);
} }
let inner = self.inner.read();
if inner.hard_links() == 0 { if inner.hard_links() == 0 {
return_errno_with_message!(Errno::ENOENT, "dir removed"); return_errno_with_message!(Errno::ENOENT, "dir removed");
} }
@ -192,11 +194,11 @@ impl Inode {
if name.len() > MAX_FNAME_LEN { if name.len() > MAX_FNAME_LEN {
return_errno!(Errno::ENAMETOOLONG); return_errno!(Errno::ENAMETOOLONG);
} }
if self.type_ != InodeType::Dir {
let inner = self.inner.upread();
if inner.inode_type() != InodeType::Dir {
return_errno!(Errno::ENOTDIR); return_errno!(Errno::ENOTDIR);
} }
let inner = self.inner.upread();
if inner.hard_links() == 0 { if inner.hard_links() == 0 {
return_errno_with_message!(Errno::ENOENT, "dir removed"); return_errno_with_message!(Errno::ENOENT, "dir removed");
} }
@ -315,10 +317,11 @@ impl Inode {
/// Rename within its own directory. /// Rename within its own directory.
fn rename_within(&self, old_name: &str, new_name: &str) -> Result<()> { fn rename_within(&self, old_name: &str, new_name: &str) -> Result<()> {
let self_inner = self.inner.upread(); if self.type_ != InodeType::Dir {
if self_inner.inode_type() != InodeType::Dir {
return_errno!(Errno::ENOTDIR); return_errno!(Errno::ENOTDIR);
} }
let self_inner = self.inner.upread();
if self_inner.hard_links() == 0 { if self_inner.hard_links() == 0 {
return_errno_with_message!(Errno::ENOENT, "dir removed"); return_errno_with_message!(Errno::ENOENT, "dir removed");
} }
@ -598,11 +601,12 @@ impl Inode {
} }
pub fn readdir_at(&self, offset: usize, visitor: &mut dyn DirentVisitor) -> Result<usize> { pub fn readdir_at(&self, offset: usize, visitor: &mut dyn DirentVisitor) -> Result<usize> {
if self.type_ != InodeType::Dir {
return_errno!(Errno::ENOTDIR);
}
let offset_read = { let offset_read = {
let inner = self.inner.read(); let inner = self.inner.read();
if inner.inode_type() != InodeType::Dir {
return_errno!(Errno::ENOTDIR);
}
if inner.hard_links() == 0 { if inner.hard_links() == 0 {
return_errno_with_message!(Errno::ENOENT, "dir removed"); return_errno_with_message!(Errno::ENOENT, "dir removed");
} }
@ -635,53 +639,48 @@ impl Inode {
} }
pub fn write_link(&self, target: &str) -> Result<()> { pub fn write_link(&self, target: &str) -> Result<()> {
let mut inner = self.inner.write(); if self.type_ != InodeType::SymLink {
if inner.inode_type() != InodeType::SymLink {
return_errno!(Errno::EISDIR); return_errno!(Errno::EISDIR);
} }
inner.write_link(target)?; let mut inner = self.inner.write();
Ok(()) inner.write_link(target)
} }
pub fn read_link(&self) -> Result<String> { pub fn read_link(&self) -> Result<String> {
let inner = self.inner.read(); if self.type_ != InodeType::SymLink {
if inner.inode_type() != InodeType::SymLink {
return_errno!(Errno::EISDIR); return_errno!(Errno::EISDIR);
} }
let inner = self.inner.read();
inner.read_link() inner.read_link()
} }
pub fn set_device_id(&self, device_id: u64) -> Result<()> { pub fn set_device_id(&self, device_id: u64) -> Result<()> {
let mut inner = self.inner.write(); if self.type_ != InodeType::BlockDevice && self.type_ != InodeType::CharDevice {
let inode_type = inner.inode_type();
if inode_type != InodeType::BlockDevice && inode_type != InodeType::CharDevice {
return_errno!(Errno::EISDIR); return_errno!(Errno::EISDIR);
} }
let mut inner = self.inner.write();
inner.set_device_id(device_id); inner.set_device_id(device_id);
Ok(()) Ok(())
} }
pub fn device_id(&self) -> u64 { pub fn device_id(&self) -> u64 {
let inner = self.inner.read(); if self.type_ != InodeType::BlockDevice && self.type_ != InodeType::CharDevice {
let inode_type = inner.inode_type();
if inode_type != InodeType::BlockDevice && inode_type != InodeType::CharDevice {
return 0; return 0;
} }
let inner = self.inner.read();
inner.device_id() inner.device_id()
} }
pub fn read_at(&self, offset: usize, writer: &mut VmWriter) -> Result<usize> { pub fn read_at(&self, offset: usize, writer: &mut VmWriter) -> Result<usize> {
let bytes_read = { if self.type_ != InodeType::File {
let inner = self.inner.read(); return_errno!(Errno::EISDIR);
if inner.inode_type() != InodeType::File { }
return_errno!(Errno::EISDIR);
}
inner.read_at(offset, writer)? let bytes_read = self.inner.read().read_at(offset, writer)?;
};
self.set_atime(now()); self.set_atime(now());
@ -690,17 +689,14 @@ impl Inode {
// The offset and the length of buffer must be multiples of the block size. // The offset and the length of buffer must be multiples of the block size.
pub fn read_direct_at(&self, offset: usize, writer: &mut VmWriter) -> Result<usize> { pub fn read_direct_at(&self, offset: usize, writer: &mut VmWriter) -> Result<usize> {
let bytes_read = { if self.type_ != InodeType::File {
let inner = self.inner.read(); return_errno!(Errno::EISDIR);
if inner.inode_type() != InodeType::File { }
return_errno!(Errno::EISDIR); if !is_block_aligned(offset) || !is_block_aligned(writer.avail()) {
} return_errno_with_message!(Errno::EINVAL, "not block-aligned");
if !is_block_aligned(offset) || !is_block_aligned(writer.avail()) { }
return_errno_with_message!(Errno::EINVAL, "not block-aligned");
}
inner.read_direct_at(offset, writer)? let bytes_read = self.inner.read().read_direct_at(offset, writer)?;
};
self.set_atime(now()); self.set_atime(now());
@ -708,47 +704,45 @@ impl Inode {
} }
pub fn write_at(&self, offset: usize, reader: &mut VmReader) -> Result<usize> { pub fn write_at(&self, offset: usize, reader: &mut VmReader) -> Result<usize> {
let bytes_written = { if self.type_ != InodeType::File {
let inner = self.inner.upread(); return_errno!(Errno::EISDIR);
if inner.inode_type() != InodeType::File { }
return_errno!(Errno::EISDIR);
}
let file_size = inner.file_size(); let inner = self.inner.upread();
let new_size = offset + reader.remain(); let file_size = inner.file_size();
if new_size > file_size { let new_size = offset + reader.remain();
let mut inner = inner.upgrade();
inner.extend_write_at(offset, reader)? let (bytes_written, mut upgraded_inner) = if new_size > file_size {
} else { let mut inner = inner.upgrade();
inner.write_at(offset, reader)? let len = inner.extend_write_at(offset, reader)?;
} (len, inner)
} else {
let len = inner.write_at(offset, reader)?;
(len, inner.upgrade())
}; };
let now = now(); let now = now();
self.set_mtime(now); upgraded_inner.set_mtime(now);
self.set_ctime(now); upgraded_inner.set_ctime(now);
Ok(bytes_written) Ok(bytes_written)
} }
// The offset and the length of buffer must be multiples of the block size. // The offset and the length of buffer must be multiples of the block size.
pub fn write_direct_at(&self, offset: usize, reader: &mut VmReader) -> Result<usize> { pub fn write_direct_at(&self, offset: usize, reader: &mut VmReader) -> Result<usize> {
let bytes_written = { if self.type_ != InodeType::File {
let inner = self.inner.upread(); return_errno!(Errno::EISDIR);
if inner.inode_type() != InodeType::File { }
return_errno!(Errno::EISDIR); if !is_block_aligned(offset) || !is_block_aligned(reader.remain()) {
} return_errno_with_message!(Errno::EINVAL, "not block aligned");
if !is_block_aligned(offset) || !is_block_aligned(reader.remain()) { }
return_errno_with_message!(Errno::EINVAL, "not block aligned");
}
let mut inner = inner.upgrade(); let mut inner = self.inner.write();
inner.write_direct_at(offset, reader)? let bytes_written = inner.write_direct_at(offset, reader)?;
};
let now = now(); let now = now();
self.set_mtime(now); inner.set_mtime(now);
self.set_ctime(now); inner.set_ctime(now);
Ok(bytes_written) Ok(bytes_written)
} }
@ -783,7 +777,7 @@ impl Inode {
} }
pub fn fallocate(&self, mode: FallocMode, offset: usize, len: usize) -> Result<()> { pub fn fallocate(&self, mode: FallocMode, offset: usize, len: usize) -> Result<()> {
if self.inode_type() != InodeType::File { if self.type_ != InodeType::File {
return_errno_with_message!(Errno::EISDIR, "not regular file"); return_errno_with_message!(Errno::EISDIR, "not regular file");
} }
@ -880,10 +874,15 @@ fn write_lock_two_inodes<'a>(
RwMutexWriteGuard<'a, InodeInner>, RwMutexWriteGuard<'a, InodeInner>,
RwMutexWriteGuard<'a, InodeInner>, RwMutexWriteGuard<'a, InodeInner>,
) { ) {
let mut write_guards = write_lock_multiple_inodes(vec![this, other]); if this.ino < other.ino {
let other_guard = write_guards.pop().unwrap(); let this = this.inner.write();
let this_guard = write_guards.pop().unwrap(); let other = other.inner.write();
(this_guard, other_guard) (this, other)
} else {
let other = other.inner.write();
let this = this.inner.write();
(this, other)
}
} }
fn write_lock_multiple_inodes(inodes: Vec<&Inode>) -> Vec<RwMutexWriteGuard<'_, InodeInner>> { fn write_lock_multiple_inodes(inodes: Vec<&Inode>) -> Vec<RwMutexWriteGuard<'_, InodeInner>> {