Make ext2 handle fifo and devices correctly

This commit is contained in:
jiangjianfeng 2025-12-02 11:54:58 +00:00 committed by Tate, Hongliang Tian
parent 35708f9485
commit c4fdd390a9
4 changed files with 54 additions and 10 deletions

View File

@ -2,14 +2,18 @@
use core::time::Duration;
use device_id::DeviceId;
use crate::{
device::get_device,
fs::{
ext2::{FilePerm, Inode as Ext2Inode},
inode_handle::FileIo,
notify::FsEventPublisher,
utils::{
DirentVisitor, Extension, FallocMode, FileSystem, Inode, InodeIo, InodeMode, InodeType,
Metadata, MknodType, StatusFlags, SymbolicLink, XattrName, XattrNamespace,
XattrSetFlags,
AccessMode, DirentVisitor, Extension, FallocMode, FileSystem, Inode, InodeIo,
InodeMode, InodeType, Metadata, MknodType, StatusFlags, SymbolicLink, XattrName,
XattrNamespace, XattrSetFlags,
},
},
prelude::*,
@ -121,6 +125,25 @@ impl Inode for Ext2Inode {
Some(self.page_cache())
}
fn open(
&self,
access_mode: AccessMode,
status_flags: StatusFlags,
) -> Option<Result<Box<dyn FileIo>>> {
match self.inode_type() {
InodeType::BlockDevice | InodeType::CharDevice => {
let device_id = self.device_id();
let device = match get_device(DeviceId::from_encoded_u64(device_id)) {
Ok(device) => device,
Err(e) => return Some(Err(e)),
};
Some(device.open())
}
InodeType::NamedPipe => Some(self.open_named_pipe(access_mode, status_flags)),
_ => None,
}
}
fn create(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result<Arc<dyn Inode>> {
Ok(self.create(name, type_, mode.into())?)
}
@ -133,7 +156,7 @@ impl Inode for Ext2Inode {
inode.set_device_id(dev.id().as_encoded_u64()).unwrap();
inode
}
_ => todo!(),
MknodType::NamedPipe => self.create(name, inode_type, mode.into())?,
};
Ok(inode)

View File

@ -20,11 +20,13 @@ use super::{
};
use crate::{
fs::{
inode_handle::FileIo,
notify::FsEventPublisher,
path::{is_dot, is_dot_or_dotdot, is_dotdot},
pipe::NamedPipe,
utils::{
Extension, FallocMode, Inode as _, InodeMode, Metadata, Permission, XattrName,
XattrNamespace, XattrSetFlags,
AccessMode, Extension, FallocMode, Inode as _, InodeMode, Metadata, Permission,
StatusFlags, XattrName, XattrNamespace, XattrSetFlags,
},
},
process::{posix_thread::AsPosixThread, Gid, Uid},
@ -688,6 +690,16 @@ impl Inode {
inner.device_id()
}
pub(super) fn open_named_pipe(
&self,
access_mode: AccessMode,
status_flags: StatusFlags,
) -> Result<Box<dyn FileIo>> {
let inner = self.inner.read();
let named_pipe = inner.named_pipe.as_ref().unwrap();
named_pipe.open(access_mode, status_flags)
}
pub fn read_at(&self, offset: usize, writer: &mut VmWriter) -> Result<usize> {
if self.type_ != InodeType::File {
return_errno!(Errno::EISDIR);
@ -960,11 +972,19 @@ fn write_lock_multiple_inodes(inodes: Vec<&Inode>) -> Vec<RwMutexWriteGuard<'_,
struct InodeInner {
inode_impl: InodeImpl,
page_cache: PageCache,
// This corresponds to the `i_pipe` field in `struct inode` in Linux.
// Reference: <https://elixir.bootlin.com/linux/v6.17/source/include/linux/fs.h#L771>.
named_pipe: Option<NamedPipe>,
}
impl InodeInner {
pub fn new(desc: Dirty<InodeDesc>, weak_self: Weak<Inode>, fs: Weak<Ext2>) -> Self {
let num_page_bytes = desc.num_page_bytes();
let named_pipe = if desc.type_ == InodeType::NamedPipe {
Some(NamedPipe::new())
} else {
None
};
let inode_impl = InodeImpl::new(desc, weak_self, fs);
Self {
page_cache: PageCache::with_capacity(
@ -973,6 +993,7 @@ impl InodeInner {
)
.unwrap(),
inode_impl,
named_pipe,
}
}

View File

@ -134,11 +134,11 @@ pub struct NamedPipe {
impl NamedPipe {
/// Creates a new named pipe.
pub fn new() -> Result<Self> {
Ok(Self {
pub fn new() -> Self {
Self {
pipe: Mutex::new(NamedPipeInner::default()),
wait_queue: WaitQueue::new(),
})
}
}
/// Opens the named pipe with the specified access mode and status flags.

View File

@ -154,7 +154,7 @@ impl Inner {
}
pub(self) fn new_named_pipe() -> Self {
Self::NamedPipe(NamedPipe::new().unwrap())
Self::NamedPipe(NamedPipe::new())
}
pub(self) fn new_file_in_memfd(this: Weak<MemfdInode>) -> Self {