Fix the issue that all pseudofs's `container_dev_id` is zero

This commit is contained in:
Chaoqun Zheng 2026-01-31 18:16:23 +08:00
parent aa33845967
commit e2fe0cb8c8
24 changed files with 156 additions and 53 deletions

View File

@ -79,11 +79,6 @@ 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

View File

@ -41,7 +41,11 @@ impl CgroupFs {
}
fn new(root_node: Arc<CgroupSystem>) -> Arc<Self> {
let sb = SuperBlock::new(MAGIC_NUMBER, BLOCK_SIZE, NAME_MAX);
let dev_id = device_id::PSEUDO_FS_DEVICE_ID_ALLOCATOR
.get()
.expect("PSEUDO_FS_DEVICE_ID_ALLOCATOR not initialized")
.allocate();
let sb = SuperBlock::new(MAGIC_NUMBER, BLOCK_SIZE, NAME_MAX, dev_id);
let root_inode = CgroupInode::new_root(root_node);
Arc::new(Self {

View File

@ -46,7 +46,11 @@ impl ConfigFs {
}
fn new(root_node: Arc<ConfigRootNode>) -> Arc<Self> {
let sb = SuperBlock::new(MAGIC_NUMBER, BLOCK_SIZE, NAME_MAX);
let dev_id = device_id::PSEUDO_FS_DEVICE_ID_ALLOCATOR
.get()
.expect("PSEUDO_FS_DEVICE_ID_ALLOCATOR not initialized")
.allocate();
let sb = SuperBlock::new(MAGIC_NUMBER, BLOCK_SIZE, NAME_MAX, dev_id);
let root_inode = ConfigInode::new_root(root_node);
Arc::new(Self {

View File

@ -53,8 +53,12 @@ pub struct DevPts {
impl DevPts {
pub fn new() -> Arc<Self> {
let dev_id = device_id::PSEUDO_FS_DEVICE_ID_ALLOCATOR
.get()
.expect("PSEUDO_FS_DEVICE_ID_ALLOCATOR not initialized")
.allocate();
Arc::new_cyclic(|weak_self| Self {
sb: SuperBlock::new(DEVPTS_MAGIC, BLOCK_SIZE, NAME_MAX),
sb: SuperBlock::new(DEVPTS_MAGIC, BLOCK_SIZE, NAME_MAX, dev_id),
root: RootInode::new(weak_self.clone()),
index_alloc: Mutex::new(IdAlloc::with_capacity(MAX_PTY_NUM)),
fs_event_subscriber_stats: FsEventSubscriberStats::new(),
@ -196,7 +200,16 @@ impl Inode for RootInode {
}
fn metadata(&self) -> Metadata {
*self.metadata.read()
let metadata = *self.metadata.read();
if metadata.container_dev_id.is_none()
&& let Some(devpts) = self.fs.upgrade()
{
let dev_id = devpts.sb().dev_id;
let mut metadata_lock = self.metadata.write();
metadata_lock.container_dev_id = Some(dev_id);
return *metadata_lock;
}
metadata
}
fn extension(&self) -> &Extension {

View File

@ -28,7 +28,7 @@ struct Inner(Weak<DevPts>);
impl Ptmx {
pub fn new(fs: Weak<DevPts>) -> Arc<Self> {
let inner = Inner(fs);
let inner = Inner(fs.clone());
Arc::new(Self {
metadata: RwLock::new(Metadata::new_device(
PTMX_INO,
@ -78,7 +78,16 @@ impl Inode for Ptmx {
}
fn metadata(&self) -> Metadata {
*self.metadata.read()
let metadata = *self.metadata.read();
if metadata.container_dev_id.is_none()
&& let Some(devpts) = self.inner.0.upgrade()
{
let dev_id = devpts.sb().dev_id;
let mut metadata_lock = self.metadata.write();
metadata_lock.container_dev_id = Some(dev_id);
return *metadata_lock;
}
metadata
}
fn extension(&self) -> &Extension {

View File

@ -77,7 +77,16 @@ impl Inode for PtySlaveInode {
}
fn metadata(&self) -> Metadata {
*self.metadata.read()
let metadata = *self.metadata.read();
if metadata.container_dev_id.is_none()
&& let Some(devpts) = self.fs.upgrade()
{
let dev_id = devpts.sb().dev_id;
let mut metadata_lock = self.metadata.write();
metadata_lock.container_dev_id = Some(dev_id);
return *metadata_lock;
}
metadata
}
fn extension(&self) -> &Extension {

View File

@ -10,6 +10,7 @@ use aster_block::{
bio::{BioDirection, BioSegment, BioWaiter},
id::BlockId,
};
use device_id::DeviceId;
use hashbrown::HashMap;
use lru::LruCache;
use ostd::mm::Segment;
@ -38,6 +39,7 @@ use crate::{
pub struct ExfatFs {
block_device: Arc<dyn BlockDevice>,
super_block: ExfatSuperBlock,
dev_id: DeviceId,
bitmap: Arc<Mutex<ExfatBitmap>>,
@ -71,10 +73,12 @@ impl ExfatFs {
) -> Result<Arc<Self>> {
// Load the super_block
let super_block = Self::read_super_block(block_device.as_ref())?;
let dev_id = block_device.id();
let fs_size = super_block.num_clusters as usize * super_block.cluster_size as usize;
let exfat_fs = Arc::new_cyclic(|weak_self| ExfatFs {
block_device,
super_block,
dev_id,
bitmap: Arc::new(Mutex::new(ExfatBitmap::default())),
upcase_table: Arc::new(SpinLock::new(ExfatUpcaseTable::empty())),
mount_option,
@ -310,6 +314,10 @@ impl ExfatFs {
self.block_device.as_ref()
}
pub(super) fn dev_id(&self) -> DeviceId {
self.dev_id
}
pub(super) fn super_block(&self) -> ExfatSuperBlock {
self.super_block
}
@ -421,7 +429,12 @@ impl FileSystem for ExfatFs {
}
fn sb(&self) -> SuperBlock {
SuperBlock::new(BOOT_SIGNATURE as u64, self.sector_size(), MAX_NAME_LENGTH)
SuperBlock::new(
BOOT_SIGNATURE as u64,
self.sector_size(),
MAX_NAME_LENGTH,
self.dev_id,
)
}
fn fs_event_subscriber_stats(&self) -> &FsEventSubscriberStats {

View File

@ -12,7 +12,6 @@ use aster_block::{
bio::{BioDirection, BioSegment, BioWaiter},
id::{Bid, BlockId},
};
use device_id::DeviceId;
use ostd::mm::{Segment, VmIo, io_util::HasVmReaderWriter};
use super::{
@ -1371,7 +1370,7 @@ impl Inode for ExfatInode {
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),
container_dev_id: DeviceId::none(), // FIXME: placeholder
container_dev_id: Some(inner.fs().dev_id()),
self_dev_id: None,
}
}

View File

@ -2,6 +2,8 @@
#![expect(dead_code)]
use device_id::DeviceId;
use super::{
block_group::{BlockGroup, RawGroupDescriptor},
block_ptr::Ext2Bid,
@ -22,6 +24,7 @@ const ROOT_INO: u32 = 2;
pub struct Ext2 {
block_device: Arc<dyn BlockDevice>,
super_block: RwMutex<Dirty<SuperBlock>>,
dev_id: DeviceId,
block_groups: Vec<BlockGroup>,
inodes_per_group: u32,
blocks_per_group: Ext2Bid,
@ -90,6 +93,7 @@ impl Ext2 {
blocks_per_group: super_block.blocks_per_group(),
inode_size: super_block.inode_size(),
block_size: super_block.block_size(),
dev_id: block_device.id(),
block_groups: load_block_groups(
weak_ref.clone(),
block_device.as_ref(),
@ -110,6 +114,11 @@ impl Ext2 {
self.block_device.as_ref()
}
/// Returns the device ID containing this filesystem.
pub fn dev_id(&self) -> DeviceId {
self.dev_id
}
/// Returns the size of block.
pub fn block_size(&self) -> usize {
self.block_size

View File

@ -1,10 +1,8 @@
// SPDX-License-Identifier: MPL-2.0
use ostd::sync::RwMutexReadGuard;
use crate::{
fs::{
ext2::{Ext2, MAGIC_NUM as EXT2_MAGIC, SuperBlock as Ext2SuperBlock, utils::Dirty},
ext2::{Ext2, MAGIC_NUM as EXT2_MAGIC},
utils::{FileSystem, FsEventSubscriberStats, Inode, NAME_MAX, SuperBlock},
},
prelude::*,
@ -28,17 +26,8 @@ impl FileSystem for Ext2 {
}
fn sb(&self) -> SuperBlock {
SuperBlock::from(self.super_block())
}
fn fs_event_subscriber_stats(&self) -> &FsEventSubscriberStats {
self.fs_event_subscriber_stats()
}
}
impl From<RwMutexReadGuard<'_, Dirty<Ext2SuperBlock>>> for SuperBlock {
fn from(ext2_sb: RwMutexReadGuard<Dirty<Ext2SuperBlock>>) -> Self {
Self {
let ext2_sb = self.super_block();
SuperBlock {
magic: EXT2_MAGIC as _,
bsize: ext2_sb.block_size(),
blocks: ext2_sb.total_blocks() as _,
@ -50,6 +39,11 @@ impl From<RwMutexReadGuard<'_, Dirty<Ext2SuperBlock>>> for SuperBlock {
namelen: NAME_MAX,
frsize: ext2_sb.fragment_size(),
flags: 0, // TODO
dev_id: self.dev_id(),
}
}
fn fs_event_subscriber_stats(&self) -> &FsEventSubscriberStats {
self.fs_event_subscriber_stats()
}
}

View File

@ -105,7 +105,7 @@ impl Inode {
pub fn metadata(&self) -> Metadata {
let inner = self.inner.read();
let id = self.fs.upgrade().unwrap().block_device().id();
let dev_id = self.fs.upgrade().unwrap().dev_id();
Metadata {
ino: self.ino() as _,
size: inner.file_size() as _,
@ -119,7 +119,7 @@ impl Inode {
nr_hard_links: inner.hard_links() as _,
uid: Uid::new(inner.uid()),
gid: Gid::new(inner.gid()),
container_dev_id: id,
container_dev_id: Some(dev_id),
self_dev_id: if self.device_id() != 0 {
DeviceId::from_encoded_u64(self.device_id())
} else {

View File

@ -38,7 +38,7 @@
pub use fs::Ext2;
pub use inode::{FilePerm, Inode};
pub use super_block::{MAGIC_NUM, SuperBlock};
pub use super_block::MAGIC_NUM;
use crate::fs::ext2::fs::Ext2Type;

View File

@ -50,6 +50,8 @@ pub struct OverlayFs {
config: OverlayConfig,
/// Super block.
sb: OverlaySB,
/// The device ID containing this filesystem.
dev_id: device_id::DeviceId,
/// Unique inode number generator.
next_ino: AtomicU64,
/// FS event subscriber stats for this file system.
@ -123,12 +125,17 @@ impl OverlayFs {
Self::validate_work_and_upper(&work, &upper)?;
Self::validate_work_empty(&work)?;
let dev_id = device_id::PSEUDO_FS_DEVICE_ID_ALLOCATOR
.get()
.expect("PSEUDO_FS_DEVICE_ID_ALLOCATOR not initialized")
.allocate();
Ok(Arc::new_cyclic(|weak| Self {
upper: OverlayUpper { path: upper },
lower: OverlayLower { paths: lower },
work: OverlayWork { path: work },
config: OverlayConfig::default(),
sb: OverlaySB,
dev_id,
next_ino: AtomicU64::new(0),
fs_event_subscriber_stats: FsEventSubscriberStats::new(),
self_: weak.clone(),
@ -194,7 +201,7 @@ impl FileSystem for OverlayFs {
fn sb(&self) -> SuperBlock {
// TODO: Fill the super block with valid field values.
SuperBlock::new(OVERLAY_FS_MAGIC, BLOCK_SIZE, NAME_MAX)
SuperBlock::new(OVERLAY_FS_MAGIC, BLOCK_SIZE, NAME_MAX, self.dev_id)
}
fn fs_event_subscriber_stats(&self) -> &FsEventSubscriberStats {

View File

@ -74,8 +74,12 @@ struct ProcFs {
impl ProcFs {
pub(self) fn new() -> Arc<Self> {
let dev_id = device_id::PSEUDO_FS_DEVICE_ID_ALLOCATOR
.get()
.expect("PSEUDO_FS_DEVICE_ID_ALLOCATOR not initialized")
.allocate();
Arc::new_cyclic(|weak_fs| Self {
sb: SuperBlock::new(PROC_MAGIC, BLOCK_SIZE, NAME_MAX),
sb: SuperBlock::new(PROC_MAGIC, BLOCK_SIZE, NAME_MAX, dev_id),
root: RootDirOps::new_inode(weak_fs.clone()),
inode_allocator: AtomicU64::new(PROC_ROOT_INO + 1),
fs_event_subscriber_stats: FsEventSubscriberStats::new(),

View File

@ -42,7 +42,16 @@ impl Common {
}
pub fn metadata(&self) -> Metadata {
*self.metadata.read()
let metadata = *self.metadata.read();
if metadata.container_dev_id.is_none()
&& let Some(fs) = self.fs.upgrade()
{
let dev_id = fs.sb().dev_id;
let mut metadata_lock = self.metadata.write();
metadata_lock.container_dev_id = Some(dev_id);
return *metadata_lock;
}
metadata
}
pub fn ino(&self) -> u64 {

View File

@ -67,9 +67,13 @@ impl PseudoFs {
) -> &'static Arc<Self> {
// Reference: <https://elixir.bootlin.com/linux/v6.16.5/source/fs/libfs.c#L659-L689>
fs.call_once(|| {
let dev_id = device_id::PSEUDO_FS_DEVICE_ID_ALLOCATOR
.get()
.expect("PSEUDO_FS_DEVICE_ID_ALLOCATOR not initialized")
.allocate();
Arc::new_cyclic(|weak_fs: &Weak<Self>| Self {
name,
sb: SuperBlock::new(magic, aster_block::BLOCK_SIZE, NAME_MAX),
sb: SuperBlock::new(magic, aster_block::BLOCK_SIZE, NAME_MAX, dev_id),
root: Arc::new(PseudoInode::new(
ROOT_INO,
PseudoInodeType::Root,
@ -77,6 +81,7 @@ impl PseudoFs {
Uid::new_root(),
Gid::new_root(),
weak_fs.clone(),
dev_id,
)),
inode_allocator: AtomicU64::new(ROOT_INO + 1),
fs_event_subscriber_stats: FsEventSubscriberStats::new(),
@ -91,7 +96,15 @@ impl PseudoFs {
uid: Uid,
gid: Gid,
) -> PseudoInode {
PseudoInode::new(self.alloc_id(), type_, mode, uid, gid, Arc::downgrade(self))
PseudoInode::new(
self.alloc_id(),
type_,
mode,
uid,
gid,
Arc::downgrade(self),
self.sb.dev_id,
)
}
fn alloc_id(&self) -> u64 {
@ -368,6 +381,7 @@ impl PseudoInode {
uid: Uid,
gid: Gid,
fs: Weak<PseudoFs>,
dev_id: DeviceId,
) -> Self {
let now = now();
let type_ = InodeType::from(type_);
@ -385,7 +399,7 @@ impl PseudoInode {
nr_hard_links: 1,
uid,
gid,
container_dev_id: DeviceId::none(), // FIXME: placeholder
container_dev_id: Some(dev_id),
self_dev_id: None,
};

View File

@ -51,8 +51,12 @@ pub struct RamFs {
impl RamFs {
pub fn new() -> Arc<Self> {
let dev_id = device_id::PSEUDO_FS_DEVICE_ID_ALLOCATOR
.get()
.expect("PSEUDO_FS_DEVICE_ID_ALLOCATOR not initialized")
.allocate();
Arc::new_cyclic(|weak_fs| Self {
sb: SuperBlock::new(RAMFS_MAGIC, BLOCK_SIZE, NAME_MAX),
sb: SuperBlock::new(RAMFS_MAGIC, BLOCK_SIZE, NAME_MAX, dev_id),
root: Arc::new_cyclic(|weak_root| RamInode {
inner: Inner::new_dir(weak_root.clone(), weak_root.clone()),
metadata: SpinLock::new(InodeMeta::new_dir(
@ -1169,6 +1173,7 @@ impl Inode for RamInode {
fn metadata(&self) -> Metadata {
let rdev = self.inner.device_id().unwrap_or(0);
let inode_metadata = self.metadata.lock();
let container_dev_id = self.fs().sb().dev_id;
Metadata {
ino: self.ino as _,
size: inode_metadata.size,
@ -1182,7 +1187,7 @@ impl Inode for RamInode {
nr_hard_links: inode_metadata.nlinks,
uid: inode_metadata.uid,
gid: inode_metadata.gid,
container_dev_id: DeviceId::none(), // FIXME: placeholder
container_dev_id: Some(container_dev_id),
self_dev_id: if rdev == 0 {
None
} else {

View File

@ -41,7 +41,11 @@ impl SysFs {
}
fn new() -> Arc<Self> {
let sb = SuperBlock::new(MAGIC_NUMBER, BLOCK_SIZE, NAME_MAX);
let dev_id = device_id::PSEUDO_FS_DEVICE_ID_ALLOCATOR
.get()
.expect("PSEUDO_FS_DEVICE_ID_ALLOCATOR not initialized")
.allocate();
let sb = SuperBlock::new(MAGIC_NUMBER, BLOCK_SIZE, NAME_MAX, dev_id);
let systree_ref = sysfs::systree_singleton();
let root_inode = SysFsInode::new_root(systree_ref.root().clone());

View File

@ -3,6 +3,7 @@
use core::sync::atomic::{AtomicI64, AtomicU32, Ordering};
use atomic_integer_wrapper::define_atomic_version_of_integer_like_type;
use device_id::DeviceId;
use super::Inode;
use crate::prelude::*;
@ -20,10 +21,11 @@ pub struct SuperBlock {
pub namelen: usize,
pub frsize: usize,
pub flags: u64,
pub dev_id: DeviceId,
}
impl SuperBlock {
pub fn new(magic: u64, block_size: usize, name_max_len: usize) -> Self {
pub fn new(magic: u64, block_size: usize, name_max_len: usize, dev_id: DeviceId) -> Self {
Self {
magic,
bsize: block_size,
@ -36,6 +38,7 @@ impl SuperBlock {
namelen: name_max_len,
frsize: block_size,
flags: 0,
dev_id,
}
}
}

View File

@ -210,7 +210,7 @@ pub struct Metadata {
/// For pseudo files (e.g., those on sockfs), this device is also "pseudo".
///
/// Corresponds to `st_dev`.
pub container_dev_id: DeviceId,
pub container_dev_id: Option<DeviceId>,
/// The device ID of the inode itself, if this inode represents a special device file (character or block).
///
@ -234,7 +234,7 @@ impl Metadata {
nr_hard_links: 2,
uid: Uid::new_root(),
gid: Gid::new_root(),
container_dev_id: DeviceId::none(), // FIXME: placeholder
container_dev_id: None,
self_dev_id: None,
}
}
@ -254,7 +254,7 @@ impl Metadata {
nr_hard_links: 1,
uid: Uid::new_root(),
gid: Gid::new_root(),
container_dev_id: DeviceId::none(), // FIXME: placeholder
container_dev_id: None,
self_dev_id: None,
}
}
@ -274,7 +274,7 @@ impl Metadata {
nr_hard_links: 1,
uid: Uid::new_root(),
gid: Gid::new_root(),
container_dev_id: DeviceId::none(), // FIXME: placeholder
container_dev_id: None,
self_dev_id: None,
}
}
@ -294,7 +294,7 @@ impl Metadata {
nr_hard_links: 1,
uid: Uid::new_root(),
gid: Gid::new_root(),
container_dev_id: DeviceId::none(), // FIXME: placeholder
container_dev_id: None,
self_dev_id: Some(device.id()),
}
}

View File

@ -12,7 +12,6 @@ use core::time::Duration;
use aster_systree::{
SysAttr, SysBranchNode, SysNode, SysNodeId, SysNodeType, SysObj, SysStr, SysSymlink,
};
use device_id::DeviceId;
use super::Extension;
use crate::{
@ -88,7 +87,7 @@ pub(in crate::fs) trait SysTreeInodeTy: Send + Sync + 'static {
nr_hard_links: 1,
uid: Uid::new_root(),
gid: Gid::new_root(),
container_dev_id: DeviceId::none(), // FIXME: placeholder
container_dev_id: None,
self_dev_id: None,
}
}
@ -336,6 +335,9 @@ impl<KInode: SysTreeInodeTy + Send + Sync + 'static> Inode for KInode {
default fn metadata(&self) -> Metadata {
let mut metadata = *self.metadata();
metadata.mode = self.mode().unwrap();
if metadata.container_dev_id.is_none() {
metadata.container_dev_id = Some(self.fs().sb().dev_id);
}
metadata
}

View File

@ -175,7 +175,7 @@ struct Stat {
impl From<Metadata> for Stat {
fn from(info: Metadata) -> Self {
Self {
st_dev: info.container_dev_id.as_encoded_u64(),
st_dev: info.container_dev_id.map_or(0, |id| id.as_encoded_u64()),
st_ino: info.ino,
st_nlink: info.nr_hard_links as _,
st_mode: info.type_ as u32 | info.mode.bits() as u32,

View File

@ -128,8 +128,9 @@ impl Statx {
fn new(path: &Path) -> Self {
let info = path.metadata();
let (stx_dev_major, stx_dev_minor) =
device_id::decode_device_numbers(info.container_dev_id.as_encoded_u64());
let (stx_dev_major, stx_dev_minor) = device_id::decode_device_numbers(
info.container_dev_id.map_or(0, |id| 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()));

View File

@ -243,7 +243,12 @@ impl VmMapping {
let (dev_major, dev_minor) = self
.inode()
.map(|inode| {
device_id::decode_device_numbers(inode.metadata().container_dev_id.as_encoded_u64())
device_id::decode_device_numbers(
inode
.metadata()
.container_dev_id
.map_or(0, |id| id.as_encoded_u64()),
)
})
.unwrap_or((0, 0));
let ino = self.inode().map(|inode| inode.ino()).unwrap_or(0);