refactor(vfs): 重构statx系统调用的实现 (#1149)

- 将kstat的获取,与posix statx的获取进行分离.
- 修复statx没有处理dirfd的bug
- 在Metadata结构体中新增btime字段,表示文件的创建时间
- 更新多个文件系统的metadata实现,添加对btime的支持
- 引入derive_builder crate以简化Metadata构建过程
- 重构vfs模块,将core重命名为vcore以避免命名冲突
- 实现vfs_statx和vfs_getattr函数,支持更详细的文件属性查询
- 新增LookUpFlags定义,用于路径查找时的标志位

Signed-off-by: longjin <longjin@dragonos.org>
This commit is contained in:
LoGin 2025-05-09 14:46:10 +08:00 committed by GitHub
parent bc9bb9607f
commit 0b89d7130e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
25 changed files with 641 additions and 221 deletions

85
kernel/Cargo.lock generated
View File

@ -361,6 +361,41 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
[[package]]
name = "darling"
version = "0.20.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee"
dependencies = [
"darling_core",
"darling_macro",
]
[[package]]
name = "darling_core"
version = "0.20.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim",
"syn 2.0.100",
]
[[package]]
name = "darling_macro"
version = "0.20.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
dependencies = [
"darling_core",
"quote",
"syn 2.0.100",
]
[[package]] [[package]]
name = "defer" name = "defer"
version = "0.2.1" version = "0.2.1"
@ -399,6 +434,37 @@ dependencies = [
"thiserror", "thiserror",
] ]
[[package]]
name = "derive_builder"
version = "0.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947"
dependencies = [
"derive_builder_macro",
]
[[package]]
name = "derive_builder_core"
version = "0.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8"
dependencies = [
"darling",
"proc-macro2",
"quote",
"syn 2.0.100",
]
[[package]]
name = "derive_builder_macro"
version = "0.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c"
dependencies = [
"derive_builder_core",
"syn 2.0.100",
]
[[package]] [[package]]
name = "derive_more" name = "derive_more"
version = "0.99.19" version = "0.99.19"
@ -435,6 +501,7 @@ dependencies = [
"bitmap", "bitmap",
"cfg-if", "cfg-if",
"defer", "defer",
"derive_builder",
"driver_base_macros", "driver_base_macros",
"elf 0.7.2", "elf 0.7.2",
"fdt", "fdt",
@ -546,6 +613,12 @@ name = "fdt"
version = "0.2.0-alpha1" version = "0.2.0-alpha1"
source = "git+https://git.mirrors.dragonos.org.cn/DragonOS-Community/fdt?rev=9862813020#98628130200086c2e55dae0d997ac4daeb590e90" source = "git+https://git.mirrors.dragonos.org.cn/DragonOS-Community/fdt?rev=9862813020#98628130200086c2e55dae0d997ac4daeb590e90"
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]] [[package]]
name = "foldhash" name = "foldhash"
version = "0.1.5" version = "0.1.5"
@ -668,6 +741,12 @@ dependencies = [
"kdepends", "kdepends",
] ]
[[package]]
name = "ident_case"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "1.9.3" version = "1.9.3"
@ -1558,6 +1637,12 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0"
[[package]]
name = "strsim"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.109" version = "1.0.109"

View File

@ -79,6 +79,7 @@ static-keys = { version = "=0.7" }
defer = "0.2.1" defer = "0.2.1"
cfg-if = { version = "1.0.0" } cfg-if = { version = "1.0.0" }
derive_builder = { version = "0.20.2", default-features = false, features = ["alloc"] }
# target为x86_64时使用下面的依赖 # target为x86_64时使用下面的依赖

View File

@ -162,7 +162,7 @@ macro_rules! define_event_trace{
#[derive(Debug)] #[derive(Debug)]
#[repr(C)] #[repr(C)]
#[allow(non_snake_case)] #[allow(non_snake_case)]
#[allow(non_camel_case_types)]
struct [<__ $name _TracePointMeta>]{ struct [<__ $name _TracePointMeta>]{
trace_point: &'static $crate::debug::tracing::tracepoint::TracePoint, trace_point: &'static $crate::debug::tracing::tracepoint::TracePoint,
print_func: fn(&mut (dyn core::any::Any+Send+Sync),$($arg_type),*), print_func: fn(&mut (dyn core::any::Any+Send+Sync),$($arg_type),*),

View File

@ -31,7 +31,7 @@ use crate::{
devfs::{devfs_register, DevFS, DeviceINode}, devfs::{devfs_register, DevFS, DeviceINode},
kernfs::KernFSInode, kernfs::KernFSInode,
vfs::{ vfs::{
core::generate_inode_id, syscall::ModeType, utils::DName, FilePrivateData, FileSystem, syscall::ModeType, utils::DName, vcore::generate_inode_id, FilePrivateData, FileSystem,
FileType, IndexNode, Metadata, FileType, IndexNode, Metadata,
}, },
}, },
@ -198,6 +198,7 @@ impl Ps2MouseDevice {
atime: PosixTimeSpec::default(), atime: PosixTimeSpec::default(),
mtime: PosixTimeSpec::default(), mtime: PosixTimeSpec::default(),
ctime: PosixTimeSpec::default(), ctime: PosixTimeSpec::default(),
btime: PosixTimeSpec::default(),
file_type: FileType::CharDevice, // 文件夹block设备char设备 file_type: FileType::CharDevice, // 文件夹block设备char设备
mode: ModeType::from_bits_truncate(0o644), mode: ModeType::from_bits_truncate(0o644),
nlinks: 1, nlinks: 1,

View File

@ -22,7 +22,7 @@ use crate::{
filesystem::{ filesystem::{
devfs::{devfs_register, DevFS, DeviceINode}, devfs::{devfs_register, DevFS, DeviceINode},
vfs::{ vfs::{
core::generate_inode_id, file::FileMode, syscall::ModeType, FilePrivateData, file::FileMode, syscall::ModeType, vcore::generate_inode_id, FilePrivateData,
FileSystem, FileType, IndexNode, Metadata, FileSystem, FileType, IndexNode, Metadata,
}, },
}, },
@ -86,6 +86,7 @@ impl LockedPS2KeyBoardInode {
atime: PosixTimeSpec::default(), atime: PosixTimeSpec::default(),
mtime: PosixTimeSpec::default(), mtime: PosixTimeSpec::default(),
ctime: PosixTimeSpec::default(), ctime: PosixTimeSpec::default(),
btime: PosixTimeSpec::default(),
file_type: FileType::CharDevice, // 文件夹block设备char设备 file_type: FileType::CharDevice, // 文件夹block设备char设备
mode: ModeType::from_bits_truncate(0o666), mode: ModeType::from_bits_truncate(0o666),
nlinks: 1, nlinks: 1,
@ -155,6 +156,7 @@ impl IndexNode for LockedPS2KeyBoardInode {
inode.metadata.atime = metadata.atime; inode.metadata.atime = metadata.atime;
inode.metadata.mtime = metadata.mtime; inode.metadata.mtime = metadata.mtime;
inode.metadata.ctime = metadata.ctime; inode.metadata.ctime = metadata.ctime;
inode.metadata.btime = metadata.btime;
inode.metadata.mode = metadata.mode; inode.metadata.mode = metadata.mode;
inode.metadata.uid = metadata.uid; inode.metadata.uid = metadata.uid;
inode.metadata.gid = metadata.gid; inode.metadata.gid = metadata.gid;

View File

@ -3,10 +3,10 @@ pub mod null_dev;
pub mod zero_dev; pub mod zero_dev;
use super::vfs::{ use super::vfs::{
core::{generate_inode_id, ROOT_INODE},
file::FileMode, file::FileMode,
syscall::ModeType, syscall::ModeType,
utils::DName, utils::DName,
vcore::{generate_inode_id, ROOT_INODE},
FilePrivateData, FileSystem, FileType, FsInfo, IndexNode, Magic, Metadata, SuperBlock, FilePrivateData, FileSystem, FileType, FsInfo, IndexNode, Magic, Metadata, SuperBlock,
}; };
use crate::{ use crate::{
@ -284,6 +284,7 @@ impl DevFSInode {
atime: PosixTimeSpec::default(), atime: PosixTimeSpec::default(),
mtime: PosixTimeSpec::default(), mtime: PosixTimeSpec::default(),
ctime: PosixTimeSpec::default(), ctime: PosixTimeSpec::default(),
btime: PosixTimeSpec::default(),
file_type: dev_type_, // 文件夹 file_type: dev_type_, // 文件夹
mode, mode,
nlinks: 1, nlinks: 1,
@ -375,6 +376,7 @@ impl LockedDevFSInode {
atime: PosixTimeSpec::default(), atime: PosixTimeSpec::default(),
mtime: PosixTimeSpec::default(), mtime: PosixTimeSpec::default(),
ctime: PosixTimeSpec::default(), ctime: PosixTimeSpec::default(),
btime: PosixTimeSpec::default(),
file_type, file_type,
mode, mode,
nlinks: 1, nlinks: 1,
@ -531,6 +533,7 @@ impl IndexNode for LockedDevFSInode {
inode.metadata.atime = metadata.atime; inode.metadata.atime = metadata.atime;
inode.metadata.mtime = metadata.mtime; inode.metadata.mtime = metadata.mtime;
inode.metadata.ctime = metadata.ctime; inode.metadata.ctime = metadata.ctime;
inode.metadata.btime = metadata.btime;
inode.metadata.mode = metadata.mode; inode.metadata.mode = metadata.mode;
inode.metadata.uid = metadata.uid; inode.metadata.uid = metadata.uid;
inode.metadata.gid = metadata.gid; inode.metadata.gid = metadata.gid;

View File

@ -2,7 +2,7 @@ use crate::driver::base::device::device_number::DeviceNumber;
use crate::filesystem::vfs::file::FileMode; use crate::filesystem::vfs::file::FileMode;
use crate::filesystem::vfs::syscall::ModeType; use crate::filesystem::vfs::syscall::ModeType;
use crate::filesystem::vfs::{ use crate::filesystem::vfs::{
core::generate_inode_id, FilePrivateData, FileSystem, FileType, IndexNode, Metadata, vcore::generate_inode_id, FilePrivateData, FileSystem, FileType, IndexNode, Metadata,
}; };
use crate::libs::spinlock::SpinLockGuard; use crate::libs::spinlock::SpinLockGuard;
use crate::{libs::spinlock::SpinLock, time::PosixTimeSpec}; use crate::{libs::spinlock::SpinLock, time::PosixTimeSpec};
@ -45,6 +45,7 @@ impl LockedNullInode {
atime: PosixTimeSpec::default(), atime: PosixTimeSpec::default(),
mtime: PosixTimeSpec::default(), mtime: PosixTimeSpec::default(),
ctime: PosixTimeSpec::default(), ctime: PosixTimeSpec::default(),
btime: PosixTimeSpec::default(),
file_type: FileType::CharDevice, // 文件夹block设备char设备 file_type: FileType::CharDevice, // 文件夹block设备char设备
mode: ModeType::from_bits_truncate(0o666), mode: ModeType::from_bits_truncate(0o666),
nlinks: 1, nlinks: 1,
@ -101,6 +102,7 @@ impl IndexNode for LockedNullInode {
inode.metadata.atime = metadata.atime; inode.metadata.atime = metadata.atime;
inode.metadata.mtime = metadata.mtime; inode.metadata.mtime = metadata.mtime;
inode.metadata.ctime = metadata.ctime; inode.metadata.ctime = metadata.ctime;
inode.metadata.btime = metadata.btime;
inode.metadata.mode = metadata.mode; inode.metadata.mode = metadata.mode;
inode.metadata.uid = metadata.uid; inode.metadata.uid = metadata.uid;
inode.metadata.gid = metadata.gid; inode.metadata.gid = metadata.gid;

View File

@ -2,7 +2,7 @@ use crate::driver::base::device::device_number::DeviceNumber;
use crate::filesystem::vfs::file::FileMode; use crate::filesystem::vfs::file::FileMode;
use crate::filesystem::vfs::syscall::ModeType; use crate::filesystem::vfs::syscall::ModeType;
use crate::filesystem::vfs::{ use crate::filesystem::vfs::{
core::generate_inode_id, FilePrivateData, FileSystem, FileType, IndexNode, Metadata, vcore::generate_inode_id, FilePrivateData, FileSystem, FileType, IndexNode, Metadata,
}; };
use crate::libs::spinlock::SpinLockGuard; use crate::libs::spinlock::SpinLockGuard;
use crate::{libs::spinlock::SpinLock, time::PosixTimeSpec}; use crate::{libs::spinlock::SpinLock, time::PosixTimeSpec};
@ -45,6 +45,7 @@ impl LockedZeroInode {
atime: PosixTimeSpec::default(), atime: PosixTimeSpec::default(),
mtime: PosixTimeSpec::default(), mtime: PosixTimeSpec::default(),
ctime: PosixTimeSpec::default(), ctime: PosixTimeSpec::default(),
btime: PosixTimeSpec::default(),
file_type: FileType::CharDevice, // 文件夹block设备char设备 file_type: FileType::CharDevice, // 文件夹block设备char设备
mode: ModeType::from_bits_truncate(0o666), mode: ModeType::from_bits_truncate(0o666),
nlinks: 1, nlinks: 1,
@ -101,6 +102,7 @@ impl IndexNode for LockedZeroInode {
inode.metadata.atime = metadata.atime; inode.metadata.atime = metadata.atime;
inode.metadata.mtime = metadata.mtime; inode.metadata.mtime = metadata.mtime;
inode.metadata.ctime = metadata.ctime; inode.metadata.ctime = metadata.ctime;
inode.metadata.btime = metadata.btime;
inode.metadata.mode = metadata.mode; inode.metadata.mode = metadata.mode;
inode.metadata.uid = metadata.uid; inode.metadata.uid = metadata.uid;
inode.metadata.gid = metadata.gid; inode.metadata.gid = metadata.gid;

View File

@ -22,14 +22,14 @@ use crate::{
tty_device::{PtyType, TtyDevice, TtyType}, tty_device::{PtyType, TtyDevice, TtyType},
}, },
}, },
filesystem::vfs::{core::do_mount_mkdir, syscall::ModeType, FileType}, filesystem::vfs::{syscall::ModeType, vcore::do_mount_mkdir, FileType},
init::initcall::INITCALL_FS, init::initcall::INITCALL_FS,
libs::spinlock::{SpinLock, SpinLockGuard}, libs::spinlock::{SpinLock, SpinLockGuard},
time::PosixTimeSpec, time::PosixTimeSpec,
}; };
use super::vfs::{ use super::vfs::{
core::generate_inode_id, FilePrivateData, FileSystem, FsInfo, IndexNode, Metadata, vcore::generate_inode_id, FilePrivateData, FileSystem, FsInfo, IndexNode, Metadata,
}; };
const DEV_PTYFS_MAX_NAMELEN: usize = 16; const DEV_PTYFS_MAX_NAMELEN: usize = 16;
@ -109,6 +109,7 @@ impl LockedDevPtsFSInode {
atime: PosixTimeSpec::default(), atime: PosixTimeSpec::default(),
mtime: PosixTimeSpec::default(), mtime: PosixTimeSpec::default(),
ctime: PosixTimeSpec::default(), ctime: PosixTimeSpec::default(),
btime: PosixTimeSpec::default(),
file_type: FileType::Dir, file_type: FileType::Dir,
mode: ModeType::from_bits_truncate(0o777), mode: ModeType::from_bits_truncate(0o777),
nlinks: 1, nlinks: 1,

View File

@ -23,9 +23,9 @@ use crate::mm::VmFaultReason;
use crate::{ use crate::{
driver::base::block::{block_device::LBA_SIZE, disk_info::Partition, SeekFrom}, driver::base::block::{block_device::LBA_SIZE, disk_info::Partition, SeekFrom},
filesystem::vfs::{ filesystem::vfs::{
core::generate_inode_id,
file::{FileMode, FilePrivateData}, file::{FileMode, FilePrivateData},
syscall::ModeType, syscall::ModeType,
vcore::generate_inode_id,
FileSystem, FileType, IndexNode, InodeId, Metadata, FileSystem, FileType, IndexNode, InodeId, Metadata,
}, },
libs::{ libs::{
@ -227,6 +227,7 @@ impl LockedFATInode {
atime: PosixTimeSpec::default(), atime: PosixTimeSpec::default(),
mtime: PosixTimeSpec::default(), mtime: PosixTimeSpec::default(),
ctime: PosixTimeSpec::default(), ctime: PosixTimeSpec::default(),
btime: PosixTimeSpec::default(),
file_type, file_type,
mode: ModeType::from_bits_truncate(0o777), mode: ModeType::from_bits_truncate(0o777),
nlinks: 1, nlinks: 1,
@ -377,6 +378,7 @@ impl FATFileSystem {
atime: PosixTimeSpec::default(), atime: PosixTimeSpec::default(),
mtime: PosixTimeSpec::default(), mtime: PosixTimeSpec::default(),
ctime: PosixTimeSpec::default(), ctime: PosixTimeSpec::default(),
btime: PosixTimeSpec::default(),
file_type: FileType::Dir, file_type: FileType::Dir,
mode: ModeType::from_bits_truncate(0o777), mode: ModeType::from_bits_truncate(0o777),
nlinks: 1, nlinks: 1,

View File

@ -22,7 +22,7 @@ use crate::{
use self::callback::{KernCallbackData, KernFSCallback, KernInodePrivateData}; use self::callback::{KernCallbackData, KernFSCallback, KernInodePrivateData};
use super::vfs::{ use super::vfs::{
core::generate_inode_id, file::FileMode, syscall::ModeType, FilePrivateData, FileSystem, file::FileMode, syscall::ModeType, vcore::generate_inode_id, FilePrivateData, FileSystem,
FileType, FsInfo, IndexNode, InodeId, Magic, Metadata, SuperBlock, FileType, FsInfo, IndexNode, InodeId, Magic, Metadata, SuperBlock,
}; };
@ -94,6 +94,7 @@ impl KernFS {
atime: PosixTimeSpec::new(0, 0), atime: PosixTimeSpec::new(0, 0),
mtime: PosixTimeSpec::new(0, 0), mtime: PosixTimeSpec::new(0, 0),
ctime: PosixTimeSpec::new(0, 0), ctime: PosixTimeSpec::new(0, 0),
btime: PosixTimeSpec::new(0, 0),
dev_id: 0, dev_id: 0,
inode_id: generate_inode_id(), inode_id: generate_inode_id(),
file_type: FileType::Dir, file_type: FileType::Dir,
@ -525,6 +526,7 @@ impl KernFSInode {
atime: PosixTimeSpec::new(0, 0), atime: PosixTimeSpec::new(0, 0),
mtime: PosixTimeSpec::new(0, 0), mtime: PosixTimeSpec::new(0, 0),
ctime: PosixTimeSpec::new(0, 0), ctime: PosixTimeSpec::new(0, 0),
btime: PosixTimeSpec::new(0, 0),
dev_id: 0, dev_id: 0,
inode_id: generate_inode_id(), inode_id: generate_inode_id(),
file_type: file_type.into(), file_type: file_type.into(),

View File

@ -15,7 +15,7 @@ use crate::{
arch::mm::LockedFrameAllocator, arch::mm::LockedFrameAllocator,
driver::base::device::device_number::DeviceNumber, driver::base::device::device_number::DeviceNumber,
filesystem::vfs::{ filesystem::vfs::{
core::{generate_inode_id, ROOT_INODE}, vcore::{generate_inode_id, ROOT_INODE},
FileType, FileType,
}, },
libs::{ libs::{
@ -361,6 +361,7 @@ impl ProcFS {
atime: PosixTimeSpec::default(), atime: PosixTimeSpec::default(),
mtime: PosixTimeSpec::default(), mtime: PosixTimeSpec::default(),
ctime: PosixTimeSpec::default(), ctime: PosixTimeSpec::default(),
btime: PosixTimeSpec::default(),
file_type: FileType::Dir, file_type: FileType::Dir,
mode: ModeType::from_bits_truncate(0o555), mode: ModeType::from_bits_truncate(0o555),
nlinks: 1, nlinks: 1,
@ -656,6 +657,7 @@ impl IndexNode for LockedProcFSInode {
inode.metadata.atime = metadata.atime; inode.metadata.atime = metadata.atime;
inode.metadata.mtime = metadata.mtime; inode.metadata.mtime = metadata.mtime;
inode.metadata.ctime = metadata.ctime; inode.metadata.ctime = metadata.ctime;
inode.metadata.btime = metadata.btime;
inode.metadata.mode = metadata.mode; inode.metadata.mode = metadata.mode;
inode.metadata.uid = metadata.uid; inode.metadata.uid = metadata.uid;
inode.metadata.gid = metadata.gid; inode.metadata.gid = metadata.gid;
@ -708,6 +710,7 @@ impl IndexNode for LockedProcFSInode {
atime: PosixTimeSpec::default(), atime: PosixTimeSpec::default(),
mtime: PosixTimeSpec::default(), mtime: PosixTimeSpec::default(),
ctime: PosixTimeSpec::default(), ctime: PosixTimeSpec::default(),
btime: PosixTimeSpec::default(),
file_type, file_type,
mode, mode,
nlinks: 1, nlinks: 1,

View File

@ -5,7 +5,7 @@ use crate::filesystem::vfs::{FileSystemMakerData, FSMAKER};
use crate::libs::rwlock::RwLock; use crate::libs::rwlock::RwLock;
use crate::{ use crate::{
driver::base::device::device_number::DeviceNumber, driver::base::device::device_number::DeviceNumber,
filesystem::vfs::{core::generate_inode_id, FileType}, filesystem::vfs::{vcore::generate_inode_id, FileType},
ipc::pipe::LockedPipeInode, ipc::pipe::LockedPipeInode,
libs::casting::DowncastArc, libs::casting::DowncastArc,
libs::spinlock::{SpinLock, SpinLockGuard}, libs::spinlock::{SpinLock, SpinLockGuard},
@ -86,6 +86,7 @@ impl RamFSInode {
atime: PosixTimeSpec::default(), atime: PosixTimeSpec::default(),
mtime: PosixTimeSpec::default(), mtime: PosixTimeSpec::default(),
ctime: PosixTimeSpec::default(), ctime: PosixTimeSpec::default(),
btime: PosixTimeSpec::default(),
file_type: FileType::Dir, file_type: FileType::Dir,
mode: ModeType::from_bits_truncate(0o777), mode: ModeType::from_bits_truncate(0o777),
nlinks: 1, nlinks: 1,
@ -281,6 +282,7 @@ impl IndexNode for LockedRamFSInode {
inode.metadata.atime = metadata.atime; inode.metadata.atime = metadata.atime;
inode.metadata.mtime = metadata.mtime; inode.metadata.mtime = metadata.mtime;
inode.metadata.ctime = metadata.ctime; inode.metadata.ctime = metadata.ctime;
inode.metadata.btime = metadata.btime;
inode.metadata.mode = metadata.mode; inode.metadata.mode = metadata.mode;
inode.metadata.uid = metadata.uid; inode.metadata.uid = metadata.uid;
inode.metadata.gid = metadata.gid; inode.metadata.gid = metadata.gid;
@ -332,6 +334,7 @@ impl IndexNode for LockedRamFSInode {
atime: PosixTimeSpec::default(), atime: PosixTimeSpec::default(),
mtime: PosixTimeSpec::default(), mtime: PosixTimeSpec::default(),
ctime: PosixTimeSpec::default(), ctime: PosixTimeSpec::default(),
btime: PosixTimeSpec::default(),
file_type, file_type,
mode, mode,
nlinks: 1, nlinks: 1,
@ -594,6 +597,7 @@ impl IndexNode for LockedRamFSInode {
atime: PosixTimeSpec::default(), atime: PosixTimeSpec::default(),
mtime: PosixTimeSpec::default(), mtime: PosixTimeSpec::default(),
ctime: PosixTimeSpec::default(), ctime: PosixTimeSpec::default(),
btime: PosixTimeSpec::default(),
file_type: FileType::Pipe, file_type: FileType::Pipe,
mode, mode,
nlinks: 1, nlinks: 1,

View File

@ -101,6 +101,8 @@ bitflags! {
/// 应用于整个子树。 /// 应用于整个子树。
/// AT_RECURSIVE: 0x8000 /// AT_RECURSIVE: 0x8000
const AT_RECURSIVE = 0x8000; const AT_RECURSIVE = 0x8000;
const AT_GETATTR_NOSEC = i32::MIN;
} }
} }

View File

@ -1,13 +1,15 @@
pub mod core;
pub mod fcntl; pub mod fcntl;
pub mod file; pub mod file;
pub mod mount; pub mod mount;
pub mod open; pub mod open;
pub mod stat;
pub mod syscall; pub mod syscall;
pub mod utils; pub mod utils;
pub mod vcore;
use ::core::{any::Any, fmt::Debug, sync::atomic::AtomicUsize}; use ::core::{any::Any, fmt::Debug, sync::atomic::AtomicUsize};
use alloc::{string::String, sync::Arc, vec::Vec}; use alloc::{string::String, sync::Arc, vec::Vec};
use derive_builder::Builder;
use intertrait::CastFromSync; use intertrait::CastFromSync;
use system_error::SystemError; use system_error::SystemError;
@ -25,8 +27,8 @@ use crate::{
time::PosixTimeSpec, time::PosixTimeSpec,
}; };
use self::{core::generate_inode_id, file::FileMode, syscall::ModeType, utils::DName}; use self::{file::FileMode, syscall::ModeType, utils::DName, vcore::generate_inode_id};
pub use self::{core::ROOT_INODE, file::FilePrivateData, mount::MountFS}; pub use self::{file::FilePrivateData, mount::MountFS, vcore::ROOT_INODE};
use super::page_cache::PageCache; use super::page_cache::PageCache;
@ -59,6 +61,22 @@ pub enum FileType {
Socket, Socket,
} }
impl From<FileType> for ModeType {
fn from(val: FileType) -> Self {
match val {
FileType::File => ModeType::S_IFREG,
FileType::Dir => ModeType::S_IFDIR,
FileType::BlockDevice => ModeType::S_IFBLK,
FileType::CharDevice => ModeType::S_IFCHR,
FileType::SymLink => ModeType::S_IFLNK,
FileType::Socket => ModeType::S_IFSOCK,
FileType::Pipe => ModeType::S_IFIFO,
FileType::KvmDevice => ModeType::S_IFCHR,
FileType::FramebufferDevice => ModeType::S_IFCHR,
}
}
}
#[allow(dead_code)] #[allow(dead_code)]
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum SpecialNodeData { pub enum SpecialNodeData {
@ -781,7 +799,8 @@ impl dyn IndexNode {
/// IndexNode的元数据 /// IndexNode的元数据
/// ///
/// 对应Posix2008中的sys/stat.h中的定义 https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_stat.h.html /// 对应Posix2008中的sys/stat.h中的定义 https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_stat.h.html
#[derive(Debug, PartialEq, Eq, Clone)] #[derive(Debug, PartialEq, Eq, Clone, Builder)]
#[builder(no_std, setter(into))]
pub struct Metadata { pub struct Metadata {
/// 当前inode所在的文件系统的设备号 /// 当前inode所在的文件系统的设备号
pub dev_id: usize, pub dev_id: usize,
@ -803,12 +822,15 @@ pub struct Metadata {
/// inode最后一次被访问的时间 /// inode最后一次被访问的时间
pub atime: PosixTimeSpec, pub atime: PosixTimeSpec,
/// inode最后一次修改的时间 /// inode的文件数据最后一次修改的时间
pub mtime: PosixTimeSpec, pub mtime: PosixTimeSpec,
/// inode的创建时间 /// inode的元数据、权限或文件内容最后一次发生改变的时间
pub ctime: PosixTimeSpec, pub ctime: PosixTimeSpec,
/// inode的创建时间
pub btime: PosixTimeSpec,
/// 文件类型 /// 文件类型
pub file_type: FileType, pub file_type: FileType,
@ -839,6 +861,7 @@ impl Default for Metadata {
atime: PosixTimeSpec::default(), atime: PosixTimeSpec::default(),
mtime: PosixTimeSpec::default(), mtime: PosixTimeSpec::default(),
ctime: PosixTimeSpec::default(), ctime: PosixTimeSpec::default(),
btime: PosixTimeSpec::default(),
file_type: FileType::File, file_type: FileType::File,
mode: ModeType::empty(), mode: ModeType::empty(),
nlinks: 1, nlinks: 1,
@ -975,6 +998,7 @@ impl Metadata {
atime: PosixTimeSpec::default(), atime: PosixTimeSpec::default(),
mtime: PosixTimeSpec::default(), mtime: PosixTimeSpec::default(),
ctime: PosixTimeSpec::default(), ctime: PosixTimeSpec::default(),
btime: PosixTimeSpec::default(),
file_type, file_type,
mode, mode,
nlinks: 1, nlinks: 1,

View File

@ -749,3 +749,18 @@ impl Debug for MountList {
f.debug_map().entries(MOUNT_LIST().0.read().iter()).finish() f.debug_map().entries(MOUNT_LIST().0.read().iter()).finish()
} }
} }
/// 判断给定的inode是否为其所在文件系统的根inode
///
/// ## 返回值
///
/// - `true`: 是根inode
/// - `false`: 不是根inode或者传入的inode不是MountFSInode类型或者调用inode的metadata方法时报错了。
pub fn is_mountpoint_root(inode: &Arc<dyn IndexNode>) -> bool {
let mnt_inode = inode.as_any_ref().downcast_ref::<MountFSInode>();
if let Some(mnt) = mnt_inode {
return mnt.is_mountpoint_root().unwrap_or(false);
}
return false;
}

View File

@ -0,0 +1,398 @@
use system_error::SystemError;
use crate::{
filesystem::vfs::{mount::is_mountpoint_root, vcore::do_file_lookup_at},
syscall::user_access::UserBufferWriter,
time::PosixTimeSpec,
};
use alloc::sync::Arc;
use super::{
fcntl::AtFlags,
syscall::{ModeType, PosixStatx, PosixStatxMask, StxAttributes},
IndexNode,
};
#[derive(Clone)]
pub struct KStat {
pub result_mask: PosixStatxMask, // What fields the user got
pub mode: ModeType, // umode_t
pub nlink: u32,
pub blksize: u32, // Preferred I/O size
pub attributes: StxAttributes,
pub attributes_mask: StxAttributes,
pub ino: u64,
pub dev: i64, // dev_t
pub rdev: i64, // dev_t
pub uid: u32, // kuid_t
pub gid: u32, // kgid_t
pub size: usize, // loff_t
pub atime: PosixTimeSpec, // struct timespec64
pub mtime: PosixTimeSpec, // struct timespec64
pub ctime: PosixTimeSpec, // struct timespec64
pub btime: PosixTimeSpec, // File creation time
pub blocks: u64,
pub mnt_id: u64,
pub dio_mem_align: u32,
pub dio_offset_align: u32,
}
impl Default for KStat {
fn default() -> Self {
Self {
result_mask: PosixStatxMask::empty(),
mode: ModeType::empty(),
nlink: Default::default(),
blksize: Default::default(),
attributes: StxAttributes::empty(),
attributes_mask: StxAttributes::empty(),
ino: Default::default(),
dev: Default::default(),
rdev: Default::default(),
uid: Default::default(),
gid: Default::default(),
size: Default::default(),
atime: Default::default(),
mtime: Default::default(),
ctime: Default::default(),
btime: Default::default(),
blocks: Default::default(),
mnt_id: Default::default(),
dio_mem_align: Default::default(),
dio_offset_align: Default::default(),
}
}
}
bitflags! {
/// https://code.dragonos.org.cn/xref/linux-6.6.21/include/linux/namei.h?fi=LOOKUP_FOLLOW#21
pub struct LookUpFlags: u32 {
/// follow links at the end
const FOLLOW = 0x0001;
/// require a directory
const DIRECTORY = 0x0002;
/// force terminal automount
const AUTOMOUNT = 0x0004;
/// accept empty path [user_... only]
const EMPTY = 0x4000;
/// follow mounts in the starting point
const DOWN = 0x8000;
/// follow mounts in the end
const MOUNTPOINT = 0x0080;
/// tell ->d_revalidate() to trust no cache
const REVAL = 0x0020;
/// RCU pathwalk mode; semi-internal
const RCU = 0x0040;
/// ... in open
const OPEN = 0x0100;
/// ... in object creation
const CREATE = 0x0200;
/// ... in exclusive creation
const EXCL = 0x0400;
/// ... in destination of rename()
const RENAME_TARGET = 0x0800;
/// internal use only
const PARENT = 0x0010;
/// No symlink crossing
const NO_SYMLINKS = 0x010000;
/// No nd_jump_link() crossing
const NO_MAGICLINKS = 0x020000;
/// No mountpoint crossing
const NO_XDEV = 0x040000;
/// No escaping from starting point
const BENEATH = 0x080000;
/// Treat dirfd as fs root
const IN_ROOT = 0x100000;
/// Only do cached lookup
const CACHED = 0x200000;
/// LOOKUP_* flags which do scope-related checks based on the dirfd.
const IS_SCOPED = LookUpFlags::BENEATH.bits | LookUpFlags::IN_ROOT.bits;
}
}
impl From<AtFlags> for LookUpFlags {
fn from(value: AtFlags) -> Self {
let mut lookup_flags = LookUpFlags::empty();
if !value.contains(AtFlags::AT_SYMLINK_NOFOLLOW) {
lookup_flags |= LookUpFlags::FOLLOW;
}
if !value.contains(AtFlags::AT_NO_AUTOMOUNT) {
lookup_flags |= LookUpFlags::AUTOMOUNT;
}
if value.contains(AtFlags::AT_EMPTY_PATH) {
lookup_flags |= LookUpFlags::EMPTY;
}
lookup_flags
}
}
/// https://code.dragonos.org.cn/xref/linux-6.6.21/fs/stat.c#232
#[inline(never)]
pub fn vfs_statx(
dfd: i32,
filename: &str,
flags: AtFlags,
request_mask: PosixStatxMask,
) -> Result<KStat, SystemError> {
let lookup_flags: LookUpFlags = flags.into();
// Validate flags - only allowed flags are AT_SYMLINK_NOFOLLOW, AT_NO_AUTOMOUNT, AT_EMPTY_PATH, AT_STATX_SYNC_TYPE
if flags.intersects(
!(AtFlags::AT_SYMLINK_NOFOLLOW
| AtFlags::AT_NO_AUTOMOUNT
| AtFlags::AT_EMPTY_PATH
| AtFlags::AT_STATX_SYNC_TYPE),
) {
return Err(SystemError::EINVAL);
}
let inode = do_file_lookup_at(dfd, filename, lookup_flags)?;
let mut kstat = vfs_getattr(&inode, request_mask, flags)?;
if is_mountpoint_root(&inode) {
kstat
.attributes
.insert(StxAttributes::STATX_ATTR_MOUNT_ROOT);
}
kstat
.attributes_mask
.insert(StxAttributes::STATX_ATTR_MOUNT_ROOT);
// todo: 添加 https://code.dragonos.org.cn/xref/linux-6.6.21/fs/stat.c#266 这里的逻辑
Ok(kstat)
}
/// 获取文件的增强基本属性
///
/// # 参数
/// - `path`: 目标文件路径
/// - `stat`: 用于返回统计信息的结构体
/// - `request_mask`: PosixStatxMask标志位指示调用者需要哪些属性
/// - `query_flags`: 查询模式(AT_STATX_SYNC_TYPE)
///
/// # 描述
/// 向文件系统请求文件的属性。调用者必须通过request_mask和query_flags指定需要的信息。
///
/// 如果文件是远程的:
/// - 可以通过传递AT_STATX_FORCE_SYNC强制文件系统从后端存储更新属性
/// - 可以通过传递AT_STATX_DONT_SYNC禁止更新
///
/// request_mask中必须设置相应的位来指示调用者需要检索哪些属性。
/// 未请求的属性也可能被返回,但其值可能是近似的,如果是远程文件,
/// 可能没有与服务器同步。
///
/// # 返回值
/// 成功时返回0失败时返回负的错误码
///
/// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/fs/stat.c#165
#[inline(never)]
pub fn vfs_getattr(
inode: &Arc<dyn IndexNode>,
request_mask: PosixStatxMask,
mut at_flags: AtFlags,
) -> Result<KStat, SystemError> {
if at_flags.contains(AtFlags::AT_GETATTR_NOSEC) {
return Err(SystemError::EPERM);
}
let mut kstat = KStat::default();
kstat.result_mask |= PosixStatxMask::STATX_BASIC_STATS;
at_flags &= AtFlags::AT_STATX_SYNC_TYPE;
let metadata = inode.metadata()?;
if metadata.atime.is_empty() {
kstat.result_mask.remove(PosixStatxMask::STATX_ATIME);
}
// todo: 添加automount和dax属性
kstat.blksize = metadata.blk_size as u32;
if request_mask.contains(PosixStatxMask::STATX_MODE)
|| request_mask.contains(PosixStatxMask::STATX_TYPE)
{
kstat.mode = metadata.mode;
}
if request_mask.contains(PosixStatxMask::STATX_NLINK) {
kstat.nlink = metadata.nlinks as u32;
}
if request_mask.contains(PosixStatxMask::STATX_UID) {
kstat.uid = metadata.uid as u32;
}
if request_mask.contains(PosixStatxMask::STATX_GID) {
kstat.gid = metadata.gid as u32;
}
if request_mask.contains(PosixStatxMask::STATX_ATIME) {
kstat.atime.tv_sec = metadata.atime.tv_sec;
kstat.atime.tv_nsec = metadata.atime.tv_nsec;
}
if request_mask.contains(PosixStatxMask::STATX_MTIME) {
kstat.mtime.tv_sec = metadata.mtime.tv_sec;
kstat.mtime.tv_nsec = metadata.mtime.tv_nsec;
}
if request_mask.contains(PosixStatxMask::STATX_CTIME) {
// ctime是文件上次修改状态的时间
kstat.ctime.tv_sec = metadata.ctime.tv_sec;
kstat.ctime.tv_nsec = metadata.ctime.tv_nsec;
}
if request_mask.contains(PosixStatxMask::STATX_INO) {
kstat.ino = metadata.inode_id.into() as u64;
}
if request_mask.contains(PosixStatxMask::STATX_SIZE) {
kstat.size = metadata.size as usize;
}
if request_mask.contains(PosixStatxMask::STATX_BLOCKS) {
kstat.blocks = metadata.blocks as u64;
}
if request_mask.contains(PosixStatxMask::STATX_BTIME) {
// btime是文件创建时间
kstat.btime.tv_sec = metadata.btime.tv_sec;
kstat.btime.tv_nsec = metadata.btime.tv_nsec;
}
if request_mask.contains(PosixStatxMask::STATX_ALL) {
kstat.attributes = StxAttributes::STATX_ATTR_APPEND;
kstat.attributes_mask |=
StxAttributes::STATX_ATTR_AUTOMOUNT | StxAttributes::STATX_ATTR_DAX;
kstat.dev = metadata.dev_id as i64;
kstat.rdev = metadata.raw_dev.data() as i64;
}
// 把文件类型加入mode里面 todo: 在具体的文件系统里面去实现这个操作。这里只是权宜之计)
kstat.mode |= metadata.file_type.into();
return Ok(kstat);
}
/// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/fs/stat.c#660
pub(super) fn do_statx(
dfd: i32,
filename: &str,
flags: u32,
mask: u32,
user_kstat_ptr: usize,
) -> Result<(), SystemError> {
let mask = PosixStatxMask::from_bits_truncate(mask);
if mask.contains(PosixStatxMask::STATX_RESERVED) {
return Err(SystemError::EINVAL);
}
let flags = AtFlags::from_bits_truncate(flags as i32);
if flags.contains(AtFlags::AT_STATX_SYNC_TYPE) {
return Err(SystemError::EINVAL);
}
let kstat = vfs_statx(dfd, filename, flags, mask)?;
cp_statx(kstat, user_kstat_ptr)
}
/// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/fs/stat.c#622
#[inline(never)]
fn cp_statx(kstat: KStat, user_buf_ptr: usize) -> Result<(), SystemError> {
let mut userbuf = UserBufferWriter::new(
user_buf_ptr as *mut PosixStatx,
size_of::<PosixStatx>(),
true,
)?;
let mut statx: PosixStatx = PosixStatx::new();
// Copy fields from KStat to PosixStatx
statx.stx_mask = kstat.result_mask & !PosixStatxMask::STATX_CHANGE_COOKIE;
statx.stx_blksize = kstat.blksize;
statx.stx_attributes = kstat.attributes & !StxAttributes::STATX_ATTR_CHANGE_MONOTONIC;
statx.stx_nlink = kstat.nlink;
statx.stx_uid = kstat.uid;
statx.stx_gid = kstat.gid;
statx.stx_mode = kstat.mode;
statx.stx_inode = kstat.ino;
statx.stx_size = kstat.size as i64;
statx.stx_blocks = kstat.blocks;
statx.stx_attributes_mask = kstat.attributes_mask;
// Copy time fields
statx.stx_atime = kstat.atime;
statx.stx_btime = kstat.btime;
statx.stx_ctime = kstat.ctime;
statx.stx_mtime = kstat.mtime;
// Convert device numbers
statx.stx_rdev_major = ((kstat.rdev >> 32) & 0xffff_ffff) as u32; // MAJOR equivalent
statx.stx_rdev_minor = (kstat.rdev & 0xffff_ffff) as u32; // MINOR equivalent
statx.stx_dev_major = ((kstat.dev >> 32) & 0xffff_ffff) as u32; // MAJOR equivalent
statx.stx_dev_minor = (kstat.dev & 0xffff_ffff) as u32; // MINOR equivalent
statx.stx_mnt_id = kstat.mnt_id;
statx.stx_dio_mem_align = kstat.dio_mem_align;
statx.stx_dio_offset_align = kstat.dio_offset_align;
// Write to user space
userbuf.copy_one_to_user(&statx, 0)?;
Ok(())
}
// 注意!这个结构体定义的貌似不太对,需要修改!
#[repr(C)]
#[derive(Clone, Copy)]
/// # 文件信息结构体
pub struct PosixKstat {
/// 硬件设备ID
pub dev_id: u64,
/// inode号
pub inode: u64,
/// 硬链接数
pub nlink: u64,
/// 文件权限
pub mode: ModeType,
/// 所有者用户ID
pub uid: i32,
/// 所有者组ID
pub gid: i32,
/// 设备ID
pub rdev: i64,
/// 文件大小
pub size: i64,
/// 文件系统块大小
pub blcok_size: i64,
/// 分配的512B块数
pub blocks: u64,
/// 最后访问时间
pub atime: PosixTimeSpec,
/// 最后修改时间
pub mtime: PosixTimeSpec,
/// 最后状态变化时间
pub ctime: PosixTimeSpec,
/// 用于填充结构体大小的空白数据
pub _pad: [i8; 24],
}
impl PosixKstat {
pub(super) fn new() -> Self {
Self {
inode: 0,
dev_id: 0,
mode: ModeType::empty(),
nlink: 0,
uid: 0,
gid: 0,
rdev: 0,
size: 0,
atime: PosixTimeSpec {
tv_sec: 0,
tv_nsec: 0,
},
mtime: PosixTimeSpec {
tv_sec: 0,
tv_nsec: 0,
},
ctime: PosixTimeSpec {
tv_sec: 0,
tv_nsec: 0,
},
blcok_size: 0,
blocks: 0,
_pad: Default::default(),
}
}
}

View File

@ -10,7 +10,7 @@ use crate::producefs;
use crate::syscall::user_access::UserBufferReader; use crate::syscall::user_access::UserBufferReader;
use crate::{ use crate::{
driver::base::{block::SeekFrom, device::device_number::DeviceNumber}, driver::base::{block::SeekFrom, device::device_number::DeviceNumber},
filesystem::vfs::{core as Vcore, file::FileDescriptorVec}, filesystem::vfs::{file::FileDescriptorVec, vcore as Vcore},
libs::rwlock::RwLockWriteGuard, libs::rwlock::RwLockWriteGuard,
mm::{verify_area, VirtAddr}, mm::{verify_area, VirtAddr},
process::ProcessManager, process::ProcessManager,
@ -21,15 +21,16 @@ use crate::{
time::{syscall::PosixTimeval, PosixTimeSpec}, time::{syscall::PosixTimeval, PosixTimeSpec},
}; };
use super::core::do_symlinkat; use super::stat::{do_statx, PosixKstat};
use super::vcore::do_symlinkat;
use super::{ use super::{
core::{do_mkdir_at, do_remove_dir, do_unlink_at},
fcntl::{AtFlags, FcntlCommand, FD_CLOEXEC}, fcntl::{AtFlags, FcntlCommand, FD_CLOEXEC},
file::{File, FileMode}, file::{File, FileMode},
open::{ open::{
do_faccessat, do_fchmodat, do_fchownat, do_sys_open, do_utimensat, do_utimes, ksys_fchown, do_faccessat, do_fchmodat, do_fchownat, do_sys_open, do_utimensat, do_utimes, ksys_fchown,
}, },
utils::{rsplit_path, user_path_at}, utils::{rsplit_path, user_path_at},
vcore::{do_mkdir_at, do_remove_dir, do_unlink_at},
Dirent, FileType, IndexNode, SuperBlock, FSMAKER, MAX_PATHLEN, ROOT_INODE, Dirent, FileType, IndexNode, SuperBlock, FSMAKER, MAX_PATHLEN, ROOT_INODE,
VFS_MAX_FOLLOW_SYMLINK_TIMES, VFS_MAX_FOLLOW_SYMLINK_TIMES,
}; };
@ -88,126 +89,65 @@ bitflags! {
} }
} }
#[repr(C)]
#[derive(Clone, Copy)]
/// # 文件信息结构体
pub struct PosixKstat {
/// 硬件设备ID
dev_id: u64,
/// inode号
inode: u64,
/// 硬链接数
nlink: u64,
/// 文件权限
mode: ModeType,
/// 所有者用户ID
uid: i32,
/// 所有者组ID
gid: i32,
/// 设备ID
rdev: i64,
/// 文件大小
size: i64,
/// 文件系统块大小
blcok_size: i64,
/// 分配的512B块数
blocks: u64,
/// 最后访问时间
atime: PosixTimeSpec,
/// 最后修改时间
mtime: PosixTimeSpec,
/// 最后状态变化时间
ctime: PosixTimeSpec,
/// 用于填充结构体大小的空白数据
pub _pad: [i8; 24],
}
impl PosixKstat {
fn new() -> Self {
Self {
inode: 0,
dev_id: 0,
mode: ModeType { bits: 0 },
nlink: 0,
uid: 0,
gid: 0,
rdev: 0,
size: 0,
atime: PosixTimeSpec {
tv_sec: 0,
tv_nsec: 0,
},
mtime: PosixTimeSpec {
tv_sec: 0,
tv_nsec: 0,
},
ctime: PosixTimeSpec {
tv_sec: 0,
tv_nsec: 0,
},
blcok_size: 0,
blocks: 0,
_pad: Default::default(),
}
}
}
#[repr(C)] #[repr(C)]
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
/// # 文件信息结构体X /// # 文件信息结构体X
pub struct PosixStatx { pub struct PosixStatx {
/* 0x00 */ /* 0x00 */
stx_mask: PosixStatxMask, pub stx_mask: PosixStatxMask,
/// 文件系统块大小 /// 文件系统块大小
stx_blksize: u32, pub stx_blksize: u32,
/// Flags conveying information about the file [uncond] /// Flags conveying information about the file [uncond]
stx_attributes: StxAttributes, pub stx_attributes: StxAttributes,
/* 0x10 */ /* 0x10 */
/// 硬链接数 /// 硬链接数
stx_nlink: u32, pub stx_nlink: u32,
/// 所有者用户ID /// 所有者用户ID
stx_uid: u32, pub stx_uid: u32,
/// 所有者组ID /// 所有者组ID
stx_gid: u32, pub stx_gid: u32,
/// 文件权限 /// 文件权限
stx_mode: ModeType, pub stx_mode: ModeType,
/* 0x20 */ /* 0x20 */
/// inode号 /// inode号
stx_inode: u64, pub stx_inode: u64,
/// 文件大小 /// 文件大小
stx_size: i64, pub stx_size: i64,
/// 分配的512B块数 /// 分配的512B块数
stx_blocks: u64, pub stx_blocks: u64,
/// Mask to show what's supported in stx_attributes /// Mask to show what's supported in stx_attributes
stx_attributes_mask: StxAttributes, pub stx_attributes_mask: StxAttributes,
/* 0x40 */ /* 0x40 */
/// 最后访问时间 /// 最后访问时间
stx_atime: PosixTimeSpec, pub stx_atime: PosixTimeSpec,
/// 文件创建时间 /// 文件创建时间
stx_btime: PosixTimeSpec, pub stx_btime: PosixTimeSpec,
/// 最后状态变化时间 /// 最后状态变化时间
stx_ctime: PosixTimeSpec, pub stx_ctime: PosixTimeSpec,
/// 最后修改时间 /// 最后修改时间
stx_mtime: PosixTimeSpec, pub stx_mtime: PosixTimeSpec,
/* 0x80 */ /* 0x80 */
/// 主设备ID /// 主设备ID
stx_rdev_major: u32, pub stx_rdev_major: u32,
/// 次设备ID /// 次设备ID
stx_rdev_minor: u32, pub stx_rdev_minor: u32,
/// 主硬件设备ID /// 主硬件设备ID
stx_dev_major: u32, pub stx_dev_major: u32,
/// 次硬件设备ID /// 次硬件设备ID
stx_dev_minor: u32, pub stx_dev_minor: u32,
/* 0x90 */ /* 0x90 */
stx_mnt_id: u64, pub stx_mnt_id: u64,
stx_dio_mem_align: u32, pub stx_dio_mem_align: u32,
stx_dio_offset_align: u32, pub stx_dio_offset_align: u32,
} }
impl PosixStatx { impl PosixStatx {
fn new() -> Self { #[inline(never)]
pub(super) fn new() -> Self {
Self { Self {
stx_mask: PosixStatxMask::STATX_BASIC_STATS, stx_mask: PosixStatxMask::STATX_BASIC_STATS,
stx_blksize: 0, stx_blksize: 0,
@ -301,6 +241,9 @@ bitflags! {
/// Reserved for future struct statx expansion /// Reserved for future struct statx expansion
const STATX_RESERVED = 0x80000000; const STATX_RESERVED = 0x80000000;
/// Want/got stx_change_attr
const STATX_CHANGE_COOKIE = 0x40000000;
} }
} }
@ -324,6 +267,8 @@ bitflags! {
const STATX_ATTR_VERITY = 0x00100000; const STATX_ATTR_VERITY = 0x00100000;
/// 文件当前处于 DAX 状态 CPU直接访问 /// 文件当前处于 DAX 状态 CPU直接访问
const STATX_ATTR_DAX = 0x00200000; const STATX_ATTR_DAX = 0x00200000;
/// version monotonically increases
const STATX_ATTR_CHANGE_MONOTONIC = 0x8000000000000000;
} }
} }
@ -1411,112 +1356,22 @@ impl Syscall {
return Ok(0); return Ok(0);
} }
pub fn do_statx( #[inline(never)]
fd: i32, pub fn statx(
path: *const u8, dfd: i32,
filename_ptr: usize,
flags: u32, flags: u32,
mask: u32, mask: u32,
usr_kstat: *mut PosixStatx, user_kstat_ptr: usize,
) -> Result<usize, SystemError> { ) -> Result<usize, SystemError> {
if usr_kstat.is_null() { if user_kstat_ptr == 0 {
return Err(SystemError::EFAULT); return Err(SystemError::EFAULT);
} }
let mask = PosixStatxMask::from_bits_truncate(mask); let filename = check_and_clone_cstr(filename_ptr as *const u8, Some(MAX_PATHLEN))?;
let filename_str = filename.to_str().map_err(|_| SystemError::EINVAL)?;
if mask.contains(PosixStatxMask::STATX_RESERVED) { do_statx(dfd, filename_str, flags, mask, user_kstat_ptr).map(|_| 0)
return Err(SystemError::ENAVAIL);
}
let flags = FileMode::from_bits_truncate(flags);
let ofd = Self::open(path, flags.bits(), ModeType::empty().bits, true)?;
let binding = ProcessManager::current_pcb().fd_table();
let fd_table_guard = binding.read();
let file = fd_table_guard
.get_file_by_fd(ofd as i32)
.ok_or(SystemError::EBADF)?;
// drop guard 以避免无法调度的问题
drop(fd_table_guard);
let mut writer = UserBufferWriter::new(usr_kstat, size_of::<PosixStatx>(), true)?;
let mut tmp: PosixStatx = PosixStatx::new();
// 获取文件信息
let metadata = file.metadata()?;
tmp.stx_mask |= PosixStatxMask::STATX_BASIC_STATS;
tmp.stx_blksize = metadata.blk_size as u32;
if mask.contains(PosixStatxMask::STATX_MODE) || mask.contains(PosixStatxMask::STATX_TYPE) {
tmp.stx_mode = metadata.mode;
}
if mask.contains(PosixStatxMask::STATX_NLINK) {
tmp.stx_nlink = metadata.nlinks as u32;
}
if mask.contains(PosixStatxMask::STATX_UID) {
tmp.stx_uid = metadata.uid as u32;
}
if mask.contains(PosixStatxMask::STATX_GID) {
tmp.stx_gid = metadata.gid as u32;
}
if mask.contains(PosixStatxMask::STATX_ATIME) {
tmp.stx_atime.tv_sec = metadata.atime.tv_sec;
tmp.stx_atime.tv_nsec = metadata.atime.tv_nsec;
}
if mask.contains(PosixStatxMask::STATX_MTIME) {
tmp.stx_mtime.tv_sec = metadata.ctime.tv_sec;
tmp.stx_mtime.tv_nsec = metadata.ctime.tv_nsec;
}
if mask.contains(PosixStatxMask::STATX_CTIME) {
// ctime是文件上次修改状态的时间
tmp.stx_ctime.tv_sec = metadata.mtime.tv_sec;
tmp.stx_ctime.tv_nsec = metadata.mtime.tv_nsec;
}
if mask.contains(PosixStatxMask::STATX_INO) {
tmp.stx_inode = metadata.inode_id.into() as u64;
}
if mask.contains(PosixStatxMask::STATX_SIZE) {
tmp.stx_size = metadata.size;
}
if mask.contains(PosixStatxMask::STATX_BLOCKS) {
tmp.stx_blocks = metadata.blocks as u64;
}
if mask.contains(PosixStatxMask::STATX_BTIME) {
// btime是文件创建时间
tmp.stx_btime.tv_sec = metadata.ctime.tv_sec;
tmp.stx_btime.tv_nsec = metadata.ctime.tv_nsec;
}
if mask.contains(PosixStatxMask::STATX_ALL) {
tmp.stx_attributes = StxAttributes::STATX_ATTR_APPEND;
tmp.stx_attributes_mask |=
StxAttributes::STATX_ATTR_AUTOMOUNT | StxAttributes::STATX_ATTR_DAX;
tmp.stx_dev_major = metadata.dev_id as u32;
tmp.stx_dev_minor = metadata.dev_id as u32; //
tmp.stx_rdev_major = metadata.raw_dev.data();
tmp.stx_rdev_minor = metadata.raw_dev.data();
}
if mask.contains(PosixStatxMask::STATX_MNT_ID) {
tmp.stx_mnt_id = 0;
}
if mask.contains(PosixStatxMask::STATX_DIOALIGN) {
tmp.stx_dio_mem_align = 0;
tmp.stx_dio_offset_align = 0;
}
match file.file_type() {
FileType::File => tmp.stx_mode.insert(ModeType::S_IFREG),
FileType::Dir => tmp.stx_mode.insert(ModeType::S_IFDIR),
FileType::BlockDevice => tmp.stx_mode.insert(ModeType::S_IFBLK),
FileType::CharDevice => tmp.stx_mode.insert(ModeType::S_IFCHR),
FileType::SymLink => tmp.stx_mode.insert(ModeType::S_IFLNK),
FileType::Socket => tmp.stx_mode.insert(ModeType::S_IFSOCK),
FileType::Pipe => tmp.stx_mode.insert(ModeType::S_IFIFO),
FileType::KvmDevice => tmp.stx_mode.insert(ModeType::S_IFCHR),
FileType::FramebufferDevice => tmp.stx_mode.insert(ModeType::S_IFCHR),
}
writer.copy_one_to_user(&tmp, 0)?;
Self::close(fd as usize).ok();
return Ok(0);
} }
pub fn mknod( pub fn mknod(

View File

@ -26,6 +26,7 @@ use super::{
fcntl::AtFlags, fcntl::AtFlags,
file::FileMode, file::FileMode,
mount::{init_mountlist, MOUNT_LIST}, mount::{init_mountlist, MOUNT_LIST},
stat::LookUpFlags,
syscall::UmountFlag, syscall::UmountFlag,
utils::{rsplit_path, user_path_at}, utils::{rsplit_path, user_path_at},
FilePrivateData, IndexNode, InodeId, VFS_MAX_FOLLOW_SYMLINK_TIMES, FilePrivateData, IndexNode, InodeId, VFS_MAX_FOLLOW_SYMLINK_TIMES,
@ -396,3 +397,13 @@ pub fn do_umount2(
}; };
return do_umount(); return do_umount();
} }
pub(super) fn do_file_lookup_at(
dfd: i32,
path: &str,
lookup_flags: LookUpFlags,
) -> Result<Arc<dyn IndexNode>, SystemError> {
let (inode, path) = user_path_at(&ProcessManager::current_pcb(), dfd, path)?;
let follow_final = lookup_flags.contains(LookUpFlags::FOLLOW);
return inode.lookup_follow_symlink2(&path, VFS_MAX_FOLLOW_SYMLINK_TIMES, follow_final);
}

View File

@ -9,7 +9,7 @@ use crate::{
video::VideoRefreshManager, video::VideoRefreshManager,
}, },
exception::{init::irq_init, softirq::softirq_init, InterruptArch}, exception::{init::irq_init, softirq::softirq_init, InterruptArch},
filesystem::vfs::core::vfs_init, filesystem::vfs::vcore::vfs_init,
init::init_intertrait, init::init_intertrait,
libs::{ libs::{
futex::futex::Futex, futex::futex::Futex,

View File

@ -9,7 +9,7 @@ use system_error::SystemError;
use crate::{ use crate::{
arch::{interrupt::TrapFrame, process::arch_switch_to_user}, arch::{interrupt::TrapFrame, process::arch_switch_to_user},
driver::net::e1000e::e1000e::e1000e_init, driver::net::e1000e::e1000e::e1000e_init,
filesystem::vfs::core::mount_root_fs, filesystem::vfs::vcore::mount_root_fs,
namespaces::NsProxy, namespaces::NsProxy,
net::net_core::net_init, net::net_core::net_init,
process::{ process::{

View File

@ -3,7 +3,7 @@ use core::sync::atomic::compiler_fence;
use crate::{ use crate::{
arch::ipc::signal::{SigCode, Signal}, arch::ipc::signal::{SigCode, Signal},
filesystem::vfs::{ filesystem::vfs::{
core::generate_inode_id, file::FileMode, syscall::ModeType, FilePrivateData, FileSystem, file::FileMode, syscall::ModeType, vcore::generate_inode_id, FilePrivateData, FileSystem,
FileType, IndexNode, Metadata, PollableInode, FileType, IndexNode, Metadata, PollableInode,
}, },
libs::{ libs::{
@ -128,6 +128,7 @@ impl LockedPipeInode {
atime: PosixTimeSpec::default(), atime: PosixTimeSpec::default(),
mtime: PosixTimeSpec::default(), mtime: PosixTimeSpec::default(),
ctime: PosixTimeSpec::default(), ctime: PosixTimeSpec::default(),
btime: PosixTimeSpec::default(),
file_type: FileType::Pipe, file_type: FileType::Pipe,
mode: ModeType::from_bits_truncate(0o666), mode: ModeType::from_bits_truncate(0o666),
nlinks: 1, nlinks: 1,

View File

@ -5,7 +5,7 @@ use core::{
use crate::{ use crate::{
arch::{ipc::signal::SigSet, syscall::nr::*}, arch::{ipc::signal::SigSet, syscall::nr::*},
filesystem::vfs::syscall::{PosixStatfs, PosixStatx}, filesystem::vfs::syscall::PosixStatfs,
ipc::shm::{ShmCtlCmd, ShmFlags, ShmId, ShmKey}, ipc::shm::{ShmCtlCmd, ShmFlags, ShmId, ShmKey},
libs::{futex::constant::FutexFlag, rand::GRandFlags}, libs::{futex::constant::FutexFlag, rand::GRandFlags},
mm::{page::PAGE_4K_SIZE, syscall::MremapFlags}, mm::{page::PAGE_4K_SIZE, syscall::MremapFlags},
@ -29,7 +29,8 @@ use crate::{
filesystem::vfs::{ filesystem::vfs::{
fcntl::{AtFlags, FcntlCommand}, fcntl::{AtFlags, FcntlCommand},
file::FileMode, file::FileMode,
syscall::{ModeType, PosixKstat, UtimensFlags}, stat::PosixKstat,
syscall::{ModeType, UtimensFlags},
MAX_PATHLEN, MAX_PATHLEN,
}, },
libs::align::page_align_up, libs::align::page_align_up,
@ -811,15 +812,13 @@ impl Syscall {
Self::fstatfs(fd, statfs) Self::fstatfs(fd, statfs)
} }
SYS_STATX => { SYS_STATX => Self::statx(
let fd = args[0] as i32; args[0] as i32,
let path = args[1] as *const u8; args[1],
let flags = args[2] as u32; args[2] as u32,
let mask = args[3] as u32; args[3] as u32,
let kstat = args[4] as *mut PosixStatx; args[4],
),
Self::do_statx(fd, path, flags, mask, kstat)
}
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
SYS_EPOLL_CREATE => Self::epoll_create(args[0] as i32), SYS_EPOLL_CREATE => Self::epoll_create(args[0] as i32),

View File

@ -65,6 +65,10 @@ impl PosixTimeSpec {
}; };
} }
pub fn is_empty(&self) -> bool {
self.tv_nsec == 0 && self.tv_sec == 0
}
/// 获取当前时间 /// 获取当前时间
#[inline(always)] #[inline(always)]
pub fn now() -> Self { pub fn now() -> Self {

View File

@ -13,9 +13,9 @@ use crate::{
filesystem::{ filesystem::{
devfs::{devfs_register, DevFS, DeviceINode}, devfs::{devfs_register, DevFS, DeviceINode},
vfs::{ vfs::{
core::generate_inode_id,
file::{File, FileMode}, file::{File, FileMode},
syscall::ModeType, syscall::ModeType,
vcore::generate_inode_id,
FileType, IndexNode, Metadata, FileType, IndexNode, Metadata,
}, },
}, },
@ -61,6 +61,7 @@ impl LockedKvmInode {
atime: PosixTimeSpec::default(), atime: PosixTimeSpec::default(),
mtime: PosixTimeSpec::default(), mtime: PosixTimeSpec::default(),
ctime: PosixTimeSpec::default(), ctime: PosixTimeSpec::default(),
btime: PosixTimeSpec::default(),
file_type: FileType::KvmDevice, // 文件夹block设备char设备 file_type: FileType::KvmDevice, // 文件夹block设备char设备
mode: ModeType::S_IALLUGO, mode: ModeType::S_IALLUGO,
nlinks: 1, nlinks: 1,
@ -202,6 +203,7 @@ impl KvmInstance {
atime: PosixTimeSpec::default(), atime: PosixTimeSpec::default(),
mtime: PosixTimeSpec::default(), mtime: PosixTimeSpec::default(),
ctime: PosixTimeSpec::default(), ctime: PosixTimeSpec::default(),
btime: PosixTimeSpec::default(),
file_type: FileType::KvmDevice, file_type: FileType::KvmDevice,
mode: ModeType::S_IALLUGO, mode: ModeType::S_IALLUGO,
nlinks: 1, nlinks: 1,
@ -332,6 +334,7 @@ impl KvmVcpuDev {
atime: PosixTimeSpec::default(), atime: PosixTimeSpec::default(),
mtime: PosixTimeSpec::default(), mtime: PosixTimeSpec::default(),
ctime: PosixTimeSpec::default(), ctime: PosixTimeSpec::default(),
btime: PosixTimeSpec::default(),
file_type: FileType::KvmDevice, // 文件夹block设备char设备 file_type: FileType::KvmDevice, // 文件夹block设备char设备
mode: ModeType::S_IALLUGO, mode: ModeType::S_IALLUGO,
nlinks: 1, nlinks: 1,