Refactor `Metadata`'s fields and document them.
Besides, change `MajorId`'s lower bound to 0, which is used to represents a invalid or absent device (pseudo filesystems).
This commit is contained in:
parent
9652538807
commit
aa33845967
|
|
@ -722,6 +722,8 @@ name = "device-id"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"aster-util",
|
||||
"id-alloc",
|
||||
"spin",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ edition.workspace = true
|
|||
|
||||
[dependencies]
|
||||
aster-util.workspace = true
|
||||
id-alloc.workspace = true
|
||||
spin.workspace = true
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
|
|
|||
|
|
@ -13,6 +13,61 @@
|
|||
#![deny(unsafe_code)]
|
||||
|
||||
use aster_util::ranged_integer::{RangedU16, RangedU32};
|
||||
use id_alloc::IdAlloc;
|
||||
use spin::{Mutex, Once};
|
||||
|
||||
pub struct PseudoFSDeviceIdAllocator {
|
||||
minor_allocator: Mutex<IdAlloc>,
|
||||
}
|
||||
|
||||
/// An allocator for pseudo filesystems (no backing block device) device ID.
|
||||
///
|
||||
/// This follows the Linux convention where pseudo filesystems use major=0
|
||||
/// and dynamically allocate minor numbers (starting from 1) to distinguish different
|
||||
/// pseudo filesystem instances.
|
||||
///
|
||||
/// Reference: <https://elixir.bootlin.com/linux/v6.18/source/fs/super.c#L1242-L1271>
|
||||
impl PseudoFSDeviceIdAllocator {
|
||||
fn new() -> Self {
|
||||
let mut minor_allocator = IdAlloc::with_capacity(MinorId::MAX.get() as usize + 1);
|
||||
// Mark 0 as allocated to ensure minor numbers start from 1.
|
||||
let _ = minor_allocator.alloc_specific(0);
|
||||
|
||||
Self {
|
||||
minor_allocator: Mutex::new(minor_allocator),
|
||||
}
|
||||
}
|
||||
|
||||
/// Allocate a device ID for pseudo filesystems.
|
||||
/// Returns `None` if minor number allocation fails (exhausted).
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the allocator was not initialized.
|
||||
pub fn allocate(&self) -> DeviceId {
|
||||
let major = MajorId::new(0);
|
||||
let minor = self.minor_allocator.lock().alloc().unwrap() as u32;
|
||||
|
||||
DeviceId::new(major, MinorId::new(minor))
|
||||
}
|
||||
|
||||
/// Free a dynamically allocated pseudo filesystem device ID.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the device ID's major is not 0.
|
||||
pub fn release(&mut self, id: DeviceId) {
|
||||
debug_assert!(id.major().get() == 0);
|
||||
|
||||
self.minor_allocator.lock().free(id.minor().get() as usize);
|
||||
}
|
||||
}
|
||||
|
||||
pub static PSEUDO_FS_DEVICE_ID_ALLOCATOR: Once<PseudoFSDeviceIdAllocator> = Once::new();
|
||||
|
||||
pub fn init() {
|
||||
PSEUDO_FS_DEVICE_ID_ALLOCATOR.call_once(PseudoFSDeviceIdAllocator::new);
|
||||
}
|
||||
|
||||
/// A device ID, embedding the major ID and minor ID.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
|
|
@ -24,6 +79,11 @@ impl DeviceId {
|
|||
Self(((major.get() as u32) << 20) | minor.get())
|
||||
}
|
||||
|
||||
/// FIXME: just a placeholder for now.
|
||||
pub const fn none() -> Self {
|
||||
Self(0)
|
||||
}
|
||||
|
||||
/// Returns the encoded `u32` value.
|
||||
pub fn to_raw(&self) -> u32 {
|
||||
self.0
|
||||
|
|
@ -38,6 +98,11 @@ impl DeviceId {
|
|||
pub fn minor(&self) -> MinorId {
|
||||
MinorId::new(self.0 & 0xf_ffff)
|
||||
}
|
||||
|
||||
/// Checks if the container device is valid (major != 0).
|
||||
pub fn has_valid_container(&self) -> bool {
|
||||
self.major().get() != 0
|
||||
}
|
||||
}
|
||||
|
||||
impl DeviceId {
|
||||
|
|
@ -92,10 +157,13 @@ const MAX_MINOR_ID: u32 = 0x000f_ffff;
|
|||
|
||||
/// The major component of a device ID.
|
||||
///
|
||||
/// A major ID is a non-zero, 12-bit integer, thus falling in the range of `1..(1u16 << 12)`.
|
||||
/// A major ID is a 12-bit integer, thus falling in the range of `0..(1u16 << 12)`.
|
||||
///
|
||||
/// - **0**: Represents an invalid or absent device (used for pseudo filesystems)
|
||||
/// - **1-4095**: Valid major device numbers
|
||||
///
|
||||
/// Reference: <https://elixir.bootlin.com/linux/v6.13/source/include/linux/kdev_t.h#L10>.
|
||||
pub type MajorId = RangedU16<1, MAX_MAJOR_ID>;
|
||||
pub type MajorId = RangedU16<0, MAX_MAJOR_ID>;
|
||||
|
||||
/// The minor component of a device ID.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -239,27 +239,27 @@ impl Inode for RootInode {
|
|||
}
|
||||
|
||||
fn atime(&self) -> Duration {
|
||||
self.metadata.read().atime
|
||||
self.metadata.read().last_access_at
|
||||
}
|
||||
|
||||
fn set_atime(&self, time: Duration) {
|
||||
self.metadata.write().atime = time;
|
||||
self.metadata.write().last_access_at = time;
|
||||
}
|
||||
|
||||
fn mtime(&self) -> Duration {
|
||||
self.metadata.read().mtime
|
||||
self.metadata.read().last_modify_at
|
||||
}
|
||||
|
||||
fn set_mtime(&self, time: Duration) {
|
||||
self.metadata.write().mtime = time;
|
||||
self.metadata.write().last_modify_at = time;
|
||||
}
|
||||
|
||||
fn ctime(&self) -> Duration {
|
||||
self.metadata.read().ctime
|
||||
self.metadata.read().last_meta_change_at
|
||||
}
|
||||
|
||||
fn set_ctime(&self, time: Duration) {
|
||||
self.metadata.write().ctime = time;
|
||||
self.metadata.write().last_meta_change_at = time;
|
||||
}
|
||||
|
||||
fn create(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result<Arc<dyn Inode>> {
|
||||
|
|
|
|||
|
|
@ -121,27 +121,27 @@ impl Inode for Ptmx {
|
|||
}
|
||||
|
||||
fn atime(&self) -> Duration {
|
||||
self.metadata.read().atime
|
||||
self.metadata.read().last_access_at
|
||||
}
|
||||
|
||||
fn set_atime(&self, time: Duration) {
|
||||
self.metadata.write().atime = time;
|
||||
self.metadata.write().last_access_at = time;
|
||||
}
|
||||
|
||||
fn mtime(&self) -> Duration {
|
||||
self.metadata.read().mtime
|
||||
self.metadata.read().last_modify_at
|
||||
}
|
||||
|
||||
fn set_mtime(&self, time: Duration) {
|
||||
self.metadata.write().mtime = time;
|
||||
self.metadata.write().last_modify_at = time;
|
||||
}
|
||||
|
||||
fn ctime(&self) -> Duration {
|
||||
self.metadata.read().ctime
|
||||
self.metadata.read().last_meta_change_at
|
||||
}
|
||||
|
||||
fn set_ctime(&self, time: Duration) {
|
||||
self.metadata.write().ctime = time;
|
||||
self.metadata.write().last_meta_change_at = time;
|
||||
}
|
||||
|
||||
fn fs(&self) -> Arc<dyn FileSystem> {
|
||||
|
|
|
|||
|
|
@ -120,27 +120,27 @@ impl Inode for PtySlaveInode {
|
|||
}
|
||||
|
||||
fn atime(&self) -> Duration {
|
||||
self.metadata.read().atime
|
||||
self.metadata.read().last_access_at
|
||||
}
|
||||
|
||||
fn set_atime(&self, time: Duration) {
|
||||
self.metadata.write().atime = time;
|
||||
self.metadata.write().last_access_at = time;
|
||||
}
|
||||
|
||||
fn mtime(&self) -> Duration {
|
||||
self.metadata.read().mtime
|
||||
self.metadata.read().last_modify_at
|
||||
}
|
||||
|
||||
fn set_mtime(&self, time: Duration) {
|
||||
self.metadata.write().mtime = time;
|
||||
self.metadata.write().last_modify_at = time;
|
||||
}
|
||||
|
||||
fn ctime(&self) -> Duration {
|
||||
self.metadata.read().ctime
|
||||
self.metadata.read().last_meta_change_at
|
||||
}
|
||||
|
||||
fn set_ctime(&self, time: Duration) {
|
||||
self.metadata.write().ctime = time;
|
||||
self.metadata.write().last_meta_change_at = time;
|
||||
}
|
||||
|
||||
fn fs(&self) -> Arc<dyn FileSystem> {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ use aster_block::{
|
|||
bio::{BioDirection, BioSegment, BioWaiter},
|
||||
id::{Bid, BlockId},
|
||||
};
|
||||
use device_id::DeviceId;
|
||||
use ostd::mm::{Segment, VmIo, io_util::HasVmReaderWriter};
|
||||
|
||||
use super::{
|
||||
|
|
@ -1358,21 +1359,20 @@ impl Inode for ExfatInode {
|
|||
};
|
||||
|
||||
Metadata {
|
||||
dev: 0,
|
||||
ino: inner.ino,
|
||||
size: inner.size,
|
||||
blk_size,
|
||||
blocks: inner.size.div_ceil(blk_size),
|
||||
atime: inner.atime.as_duration().unwrap_or_default(),
|
||||
mtime: inner.mtime.as_duration().unwrap_or_default(),
|
||||
ctime: inner.ctime.as_duration().unwrap_or_default(),
|
||||
optimal_block_size: blk_size,
|
||||
nr_sectors_allocated: inner.size.div_ceil(blk_size),
|
||||
last_access_at: inner.atime.as_duration().unwrap_or_default(),
|
||||
last_modify_at: inner.mtime.as_duration().unwrap_or_default(),
|
||||
last_meta_change_at: inner.ctime.as_duration().unwrap_or_default(),
|
||||
type_: inner.inode_type,
|
||||
mode: inner.make_mode(),
|
||||
nlinks,
|
||||
nr_hard_links: nlinks,
|
||||
uid: Uid::new(inner.fs().mount_option().fs_uid as u32),
|
||||
gid: Gid::new(inner.fs().mount_option().fs_gid as u32),
|
||||
//real device
|
||||
rdev: 0,
|
||||
container_dev_id: DeviceId::none(), // FIXME: placeholder
|
||||
self_dev_id: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
use alloc::{borrow::ToOwned, rc::Rc};
|
||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
use device_id::DeviceId;
|
||||
use inherit_methods_macro::inherit_methods;
|
||||
use ostd::{const_assert, mm::io_util::HasVmReaderWriter};
|
||||
|
||||
|
|
@ -106,20 +107,24 @@ impl Inode {
|
|||
let inner = self.inner.read();
|
||||
let id = self.fs.upgrade().unwrap().block_device().id();
|
||||
Metadata {
|
||||
dev: id.as_encoded_u64(),
|
||||
ino: self.ino() as _,
|
||||
size: inner.file_size() as _,
|
||||
blk_size: BLOCK_SIZE,
|
||||
blocks: inner.blocks_count() as _,
|
||||
atime: inner.atime(),
|
||||
mtime: inner.mtime(),
|
||||
ctime: inner.ctime(),
|
||||
optimal_block_size: BLOCK_SIZE,
|
||||
nr_sectors_allocated: inner.blocks_count() as _,
|
||||
last_access_at: inner.atime(),
|
||||
last_modify_at: inner.mtime(),
|
||||
last_meta_change_at: inner.ctime(),
|
||||
type_: self.type_,
|
||||
mode: InodeMode::from(inner.file_perm()),
|
||||
nlinks: inner.hard_links() as _,
|
||||
nr_hard_links: inner.hard_links() as _,
|
||||
uid: Uid::new(inner.uid()),
|
||||
gid: Gid::new(inner.gid()),
|
||||
rdev: self.device_id(),
|
||||
container_dev_id: id,
|
||||
self_dev_id: if self.device_id() != 0 {
|
||||
DeviceId::from_encoded_u64(self.device_id())
|
||||
} else {
|
||||
None
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ use crate::{
|
|||
};
|
||||
|
||||
pub fn init() {
|
||||
device_id::init();
|
||||
registry::init();
|
||||
|
||||
sysfs::init();
|
||||
|
|
|
|||
|
|
@ -371,7 +371,7 @@ impl DirDentry<'_> {
|
|||
|
||||
dir_inode.unlink(name)?;
|
||||
|
||||
let nlinks = child_inode.metadata().nlinks;
|
||||
let nlinks = child_inode.metadata().nr_hard_links;
|
||||
fs::notify::on_link_count(&child_inode);
|
||||
if nlinks == 0 {
|
||||
// FIXME: `DELETE_SELF` should be generated after closing the last FD.
|
||||
|
|
@ -422,7 +422,7 @@ impl DirDentry<'_> {
|
|||
|
||||
dir_inode.rmdir(name)?;
|
||||
|
||||
let nlinks = child_inode.metadata().nlinks;
|
||||
let nlinks = child_inode.metadata().nr_hard_links;
|
||||
if nlinks == 0 {
|
||||
// FIXME: `DELETE_SELF` should be generated after closing the last FD.
|
||||
fs::notify::on_inode_removed(&child_inode);
|
||||
|
|
|
|||
|
|
@ -58,27 +58,27 @@ impl Common {
|
|||
}
|
||||
|
||||
pub fn atime(&self) -> Duration {
|
||||
self.metadata.read().atime
|
||||
self.metadata.read().last_access_at
|
||||
}
|
||||
|
||||
pub fn set_atime(&self, time: Duration) {
|
||||
self.metadata.write().atime = time;
|
||||
self.metadata.write().last_access_at = time;
|
||||
}
|
||||
|
||||
pub fn mtime(&self) -> Duration {
|
||||
self.metadata.read().mtime
|
||||
self.metadata.read().last_modify_at
|
||||
}
|
||||
|
||||
pub fn set_mtime(&self, time: Duration) {
|
||||
self.metadata.write().mtime = time;
|
||||
self.metadata.write().last_modify_at = time;
|
||||
}
|
||||
|
||||
pub fn ctime(&self) -> Duration {
|
||||
self.metadata.read().ctime
|
||||
self.metadata.read().last_meta_change_at
|
||||
}
|
||||
|
||||
pub fn set_ctime(&self, time: Duration) {
|
||||
self.metadata.write().ctime = time;
|
||||
self.metadata.write().last_meta_change_at = time;
|
||||
}
|
||||
|
||||
pub fn mode(&self) -> Result<InodeMode> {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ use core::{
|
|||
time::Duration,
|
||||
};
|
||||
|
||||
use device_id::DeviceId;
|
||||
use spin::Once;
|
||||
|
||||
use super::utils::{Extension, InodeIo, StatusFlags};
|
||||
|
|
@ -372,20 +373,20 @@ impl PseudoInode {
|
|||
let type_ = InodeType::from(type_);
|
||||
|
||||
let metadata = Metadata {
|
||||
dev: 0,
|
||||
ino,
|
||||
size: 0,
|
||||
blk_size: aster_block::BLOCK_SIZE,
|
||||
blocks: 0,
|
||||
atime: now,
|
||||
mtime: now,
|
||||
ctime: now,
|
||||
optimal_block_size: aster_block::BLOCK_SIZE,
|
||||
nr_sectors_allocated: 0,
|
||||
last_access_at: now,
|
||||
last_modify_at: now,
|
||||
last_meta_change_at: now,
|
||||
type_,
|
||||
mode,
|
||||
nlinks: 1,
|
||||
nr_hard_links: 1,
|
||||
uid,
|
||||
gid,
|
||||
rdev: 0,
|
||||
container_dev_id: DeviceId::none(), // FIXME: placeholder
|
||||
self_dev_id: None,
|
||||
};
|
||||
|
||||
PseudoInode {
|
||||
|
|
@ -462,7 +463,7 @@ impl Inode for PseudoInode {
|
|||
|
||||
let mut meta = self.metadata.lock();
|
||||
meta.mode = mode;
|
||||
meta.ctime = now();
|
||||
meta.last_meta_change_at = now();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -473,7 +474,7 @@ impl Inode for PseudoInode {
|
|||
fn set_owner(&self, uid: Uid) -> Result<()> {
|
||||
let mut meta = self.metadata.lock();
|
||||
meta.uid = uid;
|
||||
meta.ctime = now();
|
||||
meta.last_meta_change_at = now();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -484,32 +485,32 @@ impl Inode for PseudoInode {
|
|||
fn set_group(&self, gid: Gid) -> Result<()> {
|
||||
let mut meta = self.metadata.lock();
|
||||
meta.gid = gid;
|
||||
meta.ctime = now();
|
||||
meta.last_meta_change_at = now();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn atime(&self) -> Duration {
|
||||
self.metadata.lock().atime
|
||||
self.metadata.lock().last_access_at
|
||||
}
|
||||
|
||||
fn set_atime(&self, time: Duration) {
|
||||
self.metadata.lock().atime = time;
|
||||
self.metadata.lock().last_access_at = time;
|
||||
}
|
||||
|
||||
fn mtime(&self) -> Duration {
|
||||
self.metadata.lock().mtime
|
||||
self.metadata.lock().last_modify_at
|
||||
}
|
||||
|
||||
fn set_mtime(&self, time: Duration) {
|
||||
self.metadata.lock().mtime = time;
|
||||
self.metadata.lock().last_modify_at = time;
|
||||
}
|
||||
|
||||
fn ctime(&self) -> Duration {
|
||||
self.metadata.lock().ctime
|
||||
self.metadata.lock().last_meta_change_at
|
||||
}
|
||||
|
||||
fn set_ctime(&self, time: Duration) {
|
||||
self.metadata.lock().ctime = time;
|
||||
self.metadata.lock().last_meta_change_at = time;
|
||||
}
|
||||
|
||||
fn open(
|
||||
|
|
|
|||
|
|
@ -1170,20 +1170,24 @@ impl Inode for RamInode {
|
|||
let rdev = self.inner.device_id().unwrap_or(0);
|
||||
let inode_metadata = self.metadata.lock();
|
||||
Metadata {
|
||||
dev: 0,
|
||||
ino: self.ino as _,
|
||||
size: inode_metadata.size,
|
||||
blk_size: BLOCK_SIZE,
|
||||
blocks: inode_metadata.blocks,
|
||||
atime: inode_metadata.atime,
|
||||
mtime: inode_metadata.mtime,
|
||||
ctime: inode_metadata.ctime,
|
||||
optimal_block_size: BLOCK_SIZE,
|
||||
nr_sectors_allocated: inode_metadata.blocks,
|
||||
last_access_at: inode_metadata.atime,
|
||||
last_modify_at: inode_metadata.mtime,
|
||||
last_meta_change_at: inode_metadata.ctime,
|
||||
type_: self.typ,
|
||||
mode: inode_metadata.mode,
|
||||
nlinks: inode_metadata.nlinks,
|
||||
nr_hard_links: inode_metadata.nlinks,
|
||||
uid: inode_metadata.uid,
|
||||
gid: inode_metadata.gid,
|
||||
rdev,
|
||||
container_dev_id: DeviceId::none(), // FIXME: placeholder
|
||||
self_dev_id: if rdev == 0 {
|
||||
None
|
||||
} else {
|
||||
DeviceId::from_encoded_u64(rdev)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ use alloc::boxed::ThinBox;
|
|||
use core::time::Duration;
|
||||
|
||||
use core2::io::{Error as IoError, ErrorKind as IoErrorKind, Result as IoResult, Write};
|
||||
use device_id::DeviceId;
|
||||
use ostd::task::Task;
|
||||
use spin::Once;
|
||||
|
||||
|
|
@ -124,101 +125,177 @@ impl From<AccessMode> for Permission {
|
|||
}
|
||||
}
|
||||
|
||||
/// File metadata, providing detailed information about an inode.
|
||||
///
|
||||
/// Asterinas's type-safe counterparts for Linux's `struct stat`.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Metadata {
|
||||
pub dev: u64,
|
||||
/// The inode number, which uniquely identifies the file within the filesystem.
|
||||
///
|
||||
/// Corresponds to `st_ino`.
|
||||
pub ino: u64,
|
||||
|
||||
/// The size of the inode.
|
||||
///
|
||||
/// The interpretation depends on `inode_type`:
|
||||
/// - **Regular File**: The total length of the file content.
|
||||
/// - **Directory**: The size of the directory's internal table (usually a multiple of block size).
|
||||
/// - **Symbolic Link**: The length of the target pathname.
|
||||
/// - **Device/Socket/FIFO**: Usually zero.
|
||||
///
|
||||
/// Corresponds to `st_size`.
|
||||
pub size: usize,
|
||||
pub blk_size: usize,
|
||||
pub blocks: usize,
|
||||
pub atime: Duration,
|
||||
pub mtime: Duration,
|
||||
pub ctime: Duration,
|
||||
|
||||
/// The optimal block size for filesystem I/O operations.
|
||||
///
|
||||
/// Corresponds to `st_blksize`.
|
||||
pub optimal_block_size: usize,
|
||||
|
||||
/// Number of 512-byte sectors allocated for the inode on disk.
|
||||
///
|
||||
/// Corresponds to `st_blocks`.
|
||||
///
|
||||
/// This represents physical usage.
|
||||
/// For sparse files (those having holes), `size` is greater than this field.
|
||||
/// For files with preallocated blocks (`FALLOC_FL_KEEP_SIZE`),
|
||||
/// `size` is smaller than this field.
|
||||
pub nr_sectors_allocated: usize,
|
||||
|
||||
/// The timestamp of the last access to the inode's data.
|
||||
///
|
||||
/// Corresponds to `st_atime`.
|
||||
pub last_access_at: Duration,
|
||||
|
||||
/// The timestamp of the last modification to the inode's content.
|
||||
///
|
||||
/// Corresponds to `st_mtime`.
|
||||
pub last_modify_at: Duration,
|
||||
|
||||
/// The timestamp of the last change to the inode's metadata.
|
||||
///
|
||||
/// This is updated when permissions, ownership, or link count change,
|
||||
/// not just when the inode content is modified.
|
||||
///
|
||||
/// Corresponds to `st_ctime`.
|
||||
pub last_meta_change_at: Duration,
|
||||
|
||||
/// The type of the inode (e.g., regular file, directory, symlink).
|
||||
///
|
||||
/// Derived from the file type bits of `st_mode` (using the `S_IFMT` mask).
|
||||
pub type_: InodeType,
|
||||
|
||||
/// The inode mode, representing access permissions.
|
||||
///
|
||||
/// Derived from the permission bits of `st_mode`.
|
||||
pub mode: InodeMode,
|
||||
pub nlinks: usize,
|
||||
|
||||
/// The number of hard links pointing to this inode.
|
||||
///
|
||||
/// Corresponds to `st_nlink`.
|
||||
pub nr_hard_links: usize,
|
||||
|
||||
/// The User ID (UID) of the inode's owner.
|
||||
///
|
||||
/// Corresponds to `st_uid`.
|
||||
pub uid: Uid,
|
||||
|
||||
/// The Group ID (GID) of the inode's owner.
|
||||
///
|
||||
/// Corresponds to `st_gid`.
|
||||
pub gid: Gid,
|
||||
pub rdev: u64,
|
||||
|
||||
/// The ID of the device containing the inode.
|
||||
///
|
||||
/// For persisted files, this device could be a on-disk partition or a logical volume (with RAID).
|
||||
/// For pseudo files (e.g., those on sockfs), this device is also "pseudo".
|
||||
///
|
||||
/// Corresponds to `st_dev`.
|
||||
pub container_dev_id: DeviceId,
|
||||
|
||||
/// The device ID of the inode itself, if this inode represents a special device file (character or block).
|
||||
///
|
||||
/// Corresponds to `st_rdev`.
|
||||
pub self_dev_id: Option<DeviceId>,
|
||||
}
|
||||
|
||||
impl Metadata {
|
||||
pub fn new_dir(ino: u64, mode: InodeMode, blk_size: usize) -> Self {
|
||||
let now = RealTimeCoarseClock::get().read_time();
|
||||
Self {
|
||||
dev: 0,
|
||||
ino,
|
||||
size: 2,
|
||||
blk_size,
|
||||
blocks: 1,
|
||||
atime: now,
|
||||
mtime: now,
|
||||
ctime: now,
|
||||
optimal_block_size: blk_size,
|
||||
nr_sectors_allocated: 1,
|
||||
last_access_at: now,
|
||||
last_modify_at: now,
|
||||
last_meta_change_at: now,
|
||||
type_: InodeType::Dir,
|
||||
mode,
|
||||
nlinks: 2,
|
||||
nr_hard_links: 2,
|
||||
uid: Uid::new_root(),
|
||||
gid: Gid::new_root(),
|
||||
rdev: 0,
|
||||
container_dev_id: DeviceId::none(), // FIXME: placeholder
|
||||
self_dev_id: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_file(ino: u64, mode: InodeMode, blk_size: usize) -> Self {
|
||||
let now = RealTimeCoarseClock::get().read_time();
|
||||
Self {
|
||||
dev: 0,
|
||||
ino,
|
||||
size: 0,
|
||||
blk_size,
|
||||
blocks: 0,
|
||||
atime: now,
|
||||
mtime: now,
|
||||
ctime: now,
|
||||
optimal_block_size: blk_size,
|
||||
nr_sectors_allocated: 0,
|
||||
last_access_at: now,
|
||||
last_modify_at: now,
|
||||
last_meta_change_at: now,
|
||||
type_: InodeType::File,
|
||||
mode,
|
||||
nlinks: 1,
|
||||
nr_hard_links: 1,
|
||||
uid: Uid::new_root(),
|
||||
gid: Gid::new_root(),
|
||||
rdev: 0,
|
||||
container_dev_id: DeviceId::none(), // FIXME: placeholder
|
||||
self_dev_id: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_symlink(ino: u64, mode: InodeMode, blk_size: usize) -> Self {
|
||||
let now = RealTimeCoarseClock::get().read_time();
|
||||
Self {
|
||||
dev: 0,
|
||||
ino,
|
||||
size: 0,
|
||||
blk_size,
|
||||
blocks: 0,
|
||||
atime: now,
|
||||
mtime: now,
|
||||
ctime: now,
|
||||
optimal_block_size: blk_size,
|
||||
nr_sectors_allocated: 0,
|
||||
last_access_at: now,
|
||||
last_modify_at: now,
|
||||
last_meta_change_at: now,
|
||||
type_: InodeType::SymLink,
|
||||
mode,
|
||||
nlinks: 1,
|
||||
nr_hard_links: 1,
|
||||
uid: Uid::new_root(),
|
||||
gid: Gid::new_root(),
|
||||
rdev: 0,
|
||||
container_dev_id: DeviceId::none(), // FIXME: placeholder
|
||||
self_dev_id: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_device(ino: u64, mode: InodeMode, blk_size: usize, device: &dyn Device) -> Self {
|
||||
let now = RealTimeCoarseClock::get().read_time();
|
||||
Self {
|
||||
dev: 0,
|
||||
ino,
|
||||
size: 0,
|
||||
blk_size,
|
||||
blocks: 0,
|
||||
atime: now,
|
||||
mtime: now,
|
||||
ctime: now,
|
||||
optimal_block_size: blk_size,
|
||||
nr_sectors_allocated: 0,
|
||||
last_access_at: now,
|
||||
last_modify_at: now,
|
||||
last_meta_change_at: now,
|
||||
type_: InodeType::from(device.type_()),
|
||||
mode,
|
||||
nlinks: 1,
|
||||
nr_hard_links: 1,
|
||||
uid: Uid::new_root(),
|
||||
gid: Gid::new_root(),
|
||||
rdev: device.id().as_encoded_u64(),
|
||||
container_dev_id: DeviceId::none(), // FIXME: placeholder
|
||||
self_dev_id: Some(device.id()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ use core::time::Duration;
|
|||
use aster_systree::{
|
||||
SysAttr, SysBranchNode, SysNode, SysNodeId, SysNodeType, SysObj, SysStr, SysSymlink,
|
||||
};
|
||||
use device_id::DeviceId;
|
||||
|
||||
use super::Extension;
|
||||
use crate::{
|
||||
|
|
@ -74,21 +75,21 @@ pub(in crate::fs) trait SysTreeInodeTy: Send + Sync + 'static {
|
|||
fn new_metadata(ino: u64, type_: InodeType) -> Metadata {
|
||||
let now = RealTimeCoarseClock::get().read_time();
|
||||
Metadata {
|
||||
dev: 0,
|
||||
ino,
|
||||
size: 0,
|
||||
blk_size: 1024,
|
||||
blocks: 0,
|
||||
atime: now,
|
||||
mtime: now,
|
||||
ctime: now,
|
||||
optimal_block_size: 1024,
|
||||
nr_sectors_allocated: 0,
|
||||
last_access_at: now,
|
||||
last_modify_at: now,
|
||||
last_meta_change_at: now,
|
||||
type_,
|
||||
// The mode field in metadata will not be used
|
||||
mode: mkmod!(a=),
|
||||
nlinks: 1,
|
||||
nr_hard_links: 1,
|
||||
uid: Uid::new_root(),
|
||||
gid: Gid::new_root(),
|
||||
rdev: 0,
|
||||
container_dev_id: DeviceId::none(), // FIXME: placeholder
|
||||
self_dev_id: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -361,19 +362,19 @@ impl<KInode: SysTreeInodeTy + Send + Sync + 'static> Inode for KInode {
|
|||
}
|
||||
|
||||
default fn atime(&self) -> Duration {
|
||||
self.metadata().atime
|
||||
self.metadata().last_access_at
|
||||
}
|
||||
|
||||
default fn set_atime(&self, _time: Duration) {}
|
||||
|
||||
default fn mtime(&self) -> Duration {
|
||||
self.metadata().mtime
|
||||
self.metadata().last_modify_at
|
||||
}
|
||||
|
||||
default fn set_mtime(&self, _time: Duration) {}
|
||||
|
||||
default fn ctime(&self) -> Duration {
|
||||
self.metadata().ctime
|
||||
self.metadata().last_meta_change_at
|
||||
}
|
||||
|
||||
default fn set_ctime(&self, _time: Duration) {}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use device_id::DeviceId;
|
||||
|
||||
use super::SyscallReturn;
|
||||
use crate::{
|
||||
fs::{
|
||||
|
|
@ -240,7 +238,7 @@ fn get_fs(
|
|||
return_errno_with_message!(Errno::ENODEV, "the path is not a device file");
|
||||
}
|
||||
|
||||
let id = DeviceId::from_encoded_u64(path.metadata().rdev);
|
||||
let id = path.metadata().self_dev_id;
|
||||
let device = id.and_then(aster_block::lookup);
|
||||
if device.is_none() {
|
||||
return_errno_with_message!(Errno::ENODEV, "the device is not found");
|
||||
|
|
|
|||
|
|
@ -175,19 +175,19 @@ struct Stat {
|
|||
impl From<Metadata> for Stat {
|
||||
fn from(info: Metadata) -> Self {
|
||||
Self {
|
||||
st_dev: info.dev,
|
||||
st_dev: info.container_dev_id.as_encoded_u64(),
|
||||
st_ino: info.ino,
|
||||
st_nlink: info.nlinks as _,
|
||||
st_nlink: info.nr_hard_links as _,
|
||||
st_mode: info.type_ as u32 | info.mode.bits() as u32,
|
||||
st_uid: info.uid.into(),
|
||||
st_gid: info.gid.into(),
|
||||
st_rdev: info.rdev,
|
||||
st_rdev: info.self_dev_id.map_or(0, |id| id.as_encoded_u64()),
|
||||
st_size: info.size as i64,
|
||||
st_blksize: info.blk_size as _,
|
||||
st_blocks: (info.blocks * (info.blk_size / 512)) as i64,
|
||||
st_atime: info.atime.into(),
|
||||
st_mtime: info.mtime.into(),
|
||||
st_ctime: info.ctime.into(),
|
||||
st_blksize: info.optimal_block_size as _,
|
||||
st_blocks: info.nr_sectors_allocated as _,
|
||||
st_atime: info.last_access_at.into(),
|
||||
st_mtime: info.last_modify_at.into(),
|
||||
st_ctime: info.last_meta_change_at.into(),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,8 +128,10 @@ impl Statx {
|
|||
fn new(path: &Path) -> Self {
|
||||
let info = path.metadata();
|
||||
|
||||
let (stx_dev_major, stx_dev_minor) = device_id::decode_device_numbers(info.dev);
|
||||
let (stx_rdev_major, stx_rdev_minor) = device_id::decode_device_numbers(info.rdev);
|
||||
let (stx_dev_major, stx_dev_minor) =
|
||||
device_id::decode_device_numbers(info.container_dev_id.as_encoded_u64());
|
||||
let (stx_rdev_major, stx_rdev_minor) =
|
||||
device_id::decode_device_numbers(info.self_dev_id.map_or(0, |id| id.as_encoded_u64()));
|
||||
|
||||
// TODO: Support more `stx_attributes` flags.
|
||||
let stx_attributes_mask = STATX_ATTR_MOUNT_ROOT;
|
||||
|
|
@ -146,21 +148,21 @@ impl Statx {
|
|||
Self {
|
||||
// FIXME: All zero fields below are dummy implementations that need to be improved in the future.
|
||||
stx_mask,
|
||||
stx_blksize: info.blk_size as u32,
|
||||
stx_blksize: info.optimal_block_size as u32,
|
||||
stx_attributes,
|
||||
stx_nlink: info.nlinks as u32,
|
||||
stx_nlink: info.nr_hard_links as u32,
|
||||
stx_uid: info.uid.into(),
|
||||
stx_gid: info.gid.into(),
|
||||
stx_mode: info.type_ as u16 | info.mode.bits(),
|
||||
__spare0: [0; 1],
|
||||
stx_ino: info.ino,
|
||||
stx_size: info.size as u64,
|
||||
stx_blocks: (info.blocks * (info.blk_size / 512)) as u64,
|
||||
stx_blocks: (info.nr_sectors_allocated * (info.optimal_block_size / 512)) as u64,
|
||||
stx_attributes_mask,
|
||||
stx_atime: StatxTimestamp::from(info.atime),
|
||||
stx_btime: StatxTimestamp::from(info.atime),
|
||||
stx_ctime: StatxTimestamp::from(info.ctime),
|
||||
stx_mtime: StatxTimestamp::from(info.ctime),
|
||||
stx_atime: StatxTimestamp::from(info.last_access_at),
|
||||
stx_btime: StatxTimestamp::from(info.last_access_at),
|
||||
stx_ctime: StatxTimestamp::from(info.last_meta_change_at),
|
||||
stx_mtime: StatxTimestamp::from(info.last_meta_change_at),
|
||||
stx_rdev_major,
|
||||
stx_rdev_minor,
|
||||
stx_dev_major,
|
||||
|
|
|
|||
|
|
@ -242,7 +242,9 @@ impl VmMapping {
|
|||
let offset = self.vmo().map(|vmo| vmo.offset).unwrap_or(0);
|
||||
let (dev_major, dev_minor) = self
|
||||
.inode()
|
||||
.map(|inode| device_id::decode_device_numbers(inode.metadata().dev))
|
||||
.map(|inode| {
|
||||
device_id::decode_device_numbers(inode.metadata().container_dev_id.as_encoded_u64())
|
||||
})
|
||||
.unwrap_or((0, 0));
|
||||
let ino = self.inode().map(|inode| inode.ino()).unwrap_or(0);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue