Support generating the mount infomation
This commit is contained in:
parent
79d737c268
commit
7b68571290
|
|
@ -351,6 +351,16 @@ impl From<aster_systree::Error> for Error {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<aster_util::printer::VmPrinterError> for Error {
|
||||
fn from(value: aster_util::printer::VmPrinterError) -> Self {
|
||||
match value {
|
||||
aster_util::printer::VmPrinterError::PageFault => {
|
||||
Error::with_message(Errno::EFAULT, "Page fault occurred during VmPrinter write")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! return_errno {
|
||||
($errno: expr) => {
|
||||
|
|
|
|||
|
|
@ -48,6 +48,10 @@ impl CgroupFs {
|
|||
}
|
||||
|
||||
impl FileSystem for CgroupFs {
|
||||
fn name(&self) -> &'static str {
|
||||
"cgroup2"
|
||||
}
|
||||
|
||||
fn sync(&self) -> Result<()> {
|
||||
// CgroupFs is volatile, sync is a no-op
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -53,6 +53,10 @@ impl ConfigFs {
|
|||
}
|
||||
|
||||
impl FileSystem for ConfigFs {
|
||||
fn name(&self) -> &'static str {
|
||||
"configfs"
|
||||
}
|
||||
|
||||
fn sync(&self) -> Result<()> {
|
||||
// `ConfigFs` is volatile, sync is a no-op
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -88,6 +88,10 @@ impl DevPts {
|
|||
}
|
||||
|
||||
impl FileSystem for DevPts {
|
||||
fn name(&self) -> &'static str {
|
||||
"devpts"
|
||||
}
|
||||
|
||||
fn sync(&self) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -403,6 +403,10 @@ impl PageCacheBackend for ExfatFs {
|
|||
}
|
||||
|
||||
impl FileSystem for ExfatFs {
|
||||
fn name(&self) -> &'static str {
|
||||
"exfat"
|
||||
}
|
||||
|
||||
fn sync(&self) -> Result<()> {
|
||||
for inode in self.inodes.read().values() {
|
||||
inode.sync_all()?;
|
||||
|
|
|
|||
|
|
@ -11,6 +11,10 @@ use crate::{
|
|||
};
|
||||
|
||||
impl FileSystem for Ext2 {
|
||||
fn name(&self) -> &'static str {
|
||||
"ext2"
|
||||
}
|
||||
|
||||
fn sync(&self) -> Result<()> {
|
||||
self.sync_all_inodes()?;
|
||||
self.sync_metadata()?;
|
||||
|
|
|
|||
|
|
@ -69,6 +69,8 @@ pub fn init() {
|
|||
ext2::init();
|
||||
exfat::init();
|
||||
overlayfs::init();
|
||||
|
||||
path::init();
|
||||
}
|
||||
|
||||
pub fn init_on_each_cpu() {
|
||||
|
|
|
|||
|
|
@ -154,6 +154,10 @@ impl OverlayFs {
|
|||
}
|
||||
|
||||
impl FileSystem for OverlayFs {
|
||||
fn name(&self) -> &'static str {
|
||||
"overlay"
|
||||
}
|
||||
|
||||
/// Utilizes the layered directory entries to build the root inode.
|
||||
fn root_inode(&self) -> Arc<dyn Inode> {
|
||||
let fs = self.fs();
|
||||
|
|
@ -1193,6 +1197,7 @@ mod tests {
|
|||
|
||||
fn create_overlay_fs() -> Arc<dyn FileSystem> {
|
||||
crate::time::clocks::init_for_ktest();
|
||||
crate::fs::path::init();
|
||||
|
||||
let mode = InodeMode::all();
|
||||
let upper = {
|
||||
|
|
@ -1238,6 +1243,7 @@ mod tests {
|
|||
#[ktest]
|
||||
fn work_and_upper_should_be_in_same_mount() {
|
||||
crate::time::clocks::init_for_ktest();
|
||||
crate::fs::path::init();
|
||||
|
||||
let upper = Path::new_fs_root(new_dummy_mount());
|
||||
let lower = vec![Path::new_fs_root(new_dummy_mount())];
|
||||
|
|
@ -1252,6 +1258,7 @@ mod tests {
|
|||
#[ktest]
|
||||
fn work_should_be_empty() {
|
||||
crate::time::clocks::init_for_ktest();
|
||||
crate::fs::path::init();
|
||||
|
||||
let mode = InodeMode::all();
|
||||
let upper = {
|
||||
|
|
@ -1271,6 +1278,7 @@ mod tests {
|
|||
#[ktest]
|
||||
fn obscured_multi_layers() {
|
||||
crate::time::clocks::init_for_ktest();
|
||||
crate::fs::path::init();
|
||||
|
||||
let mode = InodeMode::all();
|
||||
let root = Path::new_fs_root(new_dummy_mount());
|
||||
|
|
|
|||
|
|
@ -477,3 +477,7 @@ pub const fn is_dot_or_dotdot(filename: &str) -> bool {
|
|||
}
|
||||
|
||||
const DOT_BYTE: u8 = b'.';
|
||||
|
||||
pub(super) fn init() {
|
||||
mount::init();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use aster_util::printer::VmPrinter;
|
||||
use hashbrown::HashMap;
|
||||
use id_alloc::IdAlloc;
|
||||
use spin::Once;
|
||||
|
||||
use crate::{
|
||||
fs::{
|
||||
|
|
@ -32,11 +35,22 @@ impl Default for MountPropType {
|
|||
}
|
||||
}
|
||||
|
||||
static ID_ALLOCATOR: Once<SpinLock<IdAlloc>> = Once::new();
|
||||
|
||||
pub(super) fn init() {
|
||||
// TODO: Make it configurable.
|
||||
const MAX_MOUNT_NUM: usize = 10000;
|
||||
|
||||
ID_ALLOCATOR.call_once(|| SpinLock::new(IdAlloc::with_capacity(MAX_MOUNT_NUM)));
|
||||
}
|
||||
|
||||
/// A `Mount` represents a mounted filesystem instance in the VFS.
|
||||
///
|
||||
/// Each `Mount` can be viewed as a node in the mount tree, maintaining
|
||||
/// mount-related information and the structure of the mount tree.
|
||||
pub struct Mount {
|
||||
/// Global unique identifier for the mount node.
|
||||
id: usize,
|
||||
/// Root dentry.
|
||||
root_dentry: Arc<Dentry>,
|
||||
/// Mountpoint dentry. A mount node can be mounted on one dentry of another mount node,
|
||||
|
|
@ -84,7 +98,9 @@ impl Mount {
|
|||
parent_mount: Option<Weak<Mount>>,
|
||||
mnt_ns: Weak<MountNamespace>,
|
||||
) -> Arc<Self> {
|
||||
let id = ID_ALLOCATOR.get().unwrap().lock().alloc().unwrap();
|
||||
Arc::new_cyclic(|weak_self| Self {
|
||||
id,
|
||||
root_dentry: Dentry::new_root(fs.root_inode()),
|
||||
mountpoint: RwLock::new(None),
|
||||
parent: RwLock::new(parent_mount),
|
||||
|
|
@ -96,6 +112,11 @@ impl Mount {
|
|||
})
|
||||
}
|
||||
|
||||
/// Gets the mount ID.
|
||||
pub fn id(&self) -> usize {
|
||||
self.id
|
||||
}
|
||||
|
||||
/// Mounts a fs on the mountpoint, it will create a new child mount node.
|
||||
///
|
||||
/// If the given mountpoint has already been mounted, then its mounted child mount
|
||||
|
|
@ -152,6 +173,7 @@ impl Mount {
|
|||
new_ns: Option<&Weak<MountNamespace>>,
|
||||
) -> Arc<Self> {
|
||||
Arc::new_cyclic(|weak_self| Self {
|
||||
id: ID_ALLOCATOR.get().unwrap().lock().alloc().unwrap(),
|
||||
root_dentry: root_dentry.clone(),
|
||||
mountpoint: RwLock::new(None),
|
||||
parent: RwLock::new(None),
|
||||
|
|
@ -362,6 +384,59 @@ impl Mount {
|
|||
Some(target_mount)
|
||||
}
|
||||
|
||||
/// Reads the mount information starting from this mount as the root,
|
||||
pub fn read_mount_info(&self, offset: usize, writer: &mut VmWriter) -> Result<usize> {
|
||||
let mut printer = VmPrinter::new_skip(writer, offset);
|
||||
|
||||
let mut stack = vec![self.this()];
|
||||
while let Some(mount) = stack.pop() {
|
||||
let mount_id = mount.id();
|
||||
let parent = mount.parent().and_then(|parent| parent.upgrade());
|
||||
let parent_id = parent.as_ref().map_or(mount_id, |p| p.id());
|
||||
let root = Path::new_fs_root(mount.clone()).abs_path();
|
||||
let mount_point = if let Some(parent) = parent {
|
||||
if let Some(mount_point_dentry) = mount.mountpoint() {
|
||||
Path::new(parent, mount_point_dentry).abs_path()
|
||||
} else {
|
||||
"".to_string()
|
||||
}
|
||||
} else {
|
||||
// No parent means it's the root of the namespace.
|
||||
"/".to_string()
|
||||
};
|
||||
let fs_type = mount.fs().name();
|
||||
|
||||
// The following fields are dummy for now.
|
||||
let major = 0;
|
||||
let minor = 0;
|
||||
let mount_options = "rw,relatime";
|
||||
let source = "none";
|
||||
let super_options = "rw";
|
||||
|
||||
let entry = MountInfoEntry {
|
||||
mount_id,
|
||||
parent_id,
|
||||
major,
|
||||
minor,
|
||||
root: &root,
|
||||
mount_point: &mount_point,
|
||||
mount_options,
|
||||
fs_type,
|
||||
source,
|
||||
super_options,
|
||||
};
|
||||
|
||||
writeln!(printer, "{}", entry)?;
|
||||
|
||||
let children = mount.children.read();
|
||||
for child_mount in children.values() {
|
||||
stack.push(child_mount.clone());
|
||||
}
|
||||
}
|
||||
|
||||
Ok(printer.bytes_written())
|
||||
}
|
||||
|
||||
fn this(&self) -> Arc<Self> {
|
||||
self.this.upgrade().unwrap()
|
||||
}
|
||||
|
|
@ -376,3 +451,52 @@ impl Debug for Mount {
|
|||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Mount {
|
||||
fn drop(&mut self) {
|
||||
ID_ALLOCATOR.get().unwrap().lock().free(self.id);
|
||||
}
|
||||
}
|
||||
|
||||
/// A single entry in the mountinfo file.
|
||||
struct MountInfoEntry<'a> {
|
||||
/// A unique ID for the mount (but not guaranteed to be unique across reboots).
|
||||
mount_id: usize,
|
||||
/// The ID of the parent mount (or self if it has no parent).
|
||||
parent_id: usize,
|
||||
/// The major device ID of the filesystem.
|
||||
major: u32,
|
||||
/// The minor device ID of the filesystem.
|
||||
minor: u32,
|
||||
/// The root of the mount within the filesystem.
|
||||
root: &'a str,
|
||||
/// The mount point relative to the process's root directory.
|
||||
mount_point: &'a str,
|
||||
/// Per-mount options.
|
||||
mount_options: &'a str,
|
||||
/// The type of the filesystem in the form "type[.subtype]".
|
||||
fs_type: &'a str,
|
||||
/// Filesystem-specific information or "none".
|
||||
source: &'a str,
|
||||
/// Per-superblock options.
|
||||
super_options: &'a str,
|
||||
}
|
||||
|
||||
impl core::fmt::Display for MountInfoEntry<'_> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{} {} {}:{} {} {} {} - {} {} {}",
|
||||
self.mount_id,
|
||||
self.parent_id,
|
||||
self.major,
|
||||
self.minor,
|
||||
&self.root,
|
||||
&self.mount_point,
|
||||
&self.mount_options,
|
||||
&self.fs_type,
|
||||
&self.source,
|
||||
&self.super_options
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,6 +77,10 @@ impl ProcFs {
|
|||
}
|
||||
|
||||
impl FileSystem for ProcFs {
|
||||
fn name(&self) -> &'static str {
|
||||
"proc"
|
||||
}
|
||||
|
||||
fn sync(&self) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,6 +74,10 @@ impl RamFs {
|
|||
}
|
||||
|
||||
impl FileSystem for RamFs {
|
||||
fn name(&self) -> &'static str {
|
||||
"ramfs"
|
||||
}
|
||||
|
||||
fn sync(&self) -> Result<()> {
|
||||
// do nothing
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -49,6 +49,10 @@ impl SysFs {
|
|||
}
|
||||
|
||||
impl FileSystem for SysFs {
|
||||
fn name(&self) -> &'static str {
|
||||
"sysfs"
|
||||
}
|
||||
|
||||
fn sync(&self) -> Result<()> {
|
||||
// Sysfs is volatile, sync is a no-op
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@ pub struct TmpFs {
|
|||
}
|
||||
|
||||
impl FileSystem for TmpFs {
|
||||
fn name(&self) -> &'static str {
|
||||
"tmpfs"
|
||||
}
|
||||
|
||||
fn sync(&self) -> Result<()> {
|
||||
// do nothing
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -44,12 +44,19 @@ bitflags! {
|
|||
}
|
||||
|
||||
pub trait FileSystem: Any + Sync + Send {
|
||||
/// Gets the name of this FS type such as `"ext4"` or `"sysfs"`.
|
||||
fn name(&self) -> &'static str;
|
||||
|
||||
/// Syncs the file system.
|
||||
fn sync(&self) -> Result<()>;
|
||||
|
||||
/// Returns the root inode of this file system.
|
||||
fn root_inode(&self) -> Arc<dyn Inode>;
|
||||
|
||||
/// Returns the super block of this file system.
|
||||
fn sb(&self) -> SuperBlock;
|
||||
|
||||
/// Returns the flags of this file system.
|
||||
fn flags(&self) -> FsFlags;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ impl ContextUnshareAdminApi for Context<'_> {
|
|||
let mut fs_ref = self.thread_local.borrow_fs_mut();
|
||||
let new_fs = fs_ref.as_ref().clone();
|
||||
*fs_ref = Arc::new(new_fs);
|
||||
self.posix_thread.update_fs(fs_ref.clone());
|
||||
}
|
||||
|
||||
fn unshare_sysvsem(&self) {
|
||||
|
|
|
|||
|
|
@ -172,6 +172,7 @@ impl PosixThreadBuilder {
|
|||
tid,
|
||||
name: Mutex::new(thread_name),
|
||||
credentials,
|
||||
fs: RwMutex::new(fs.clone()),
|
||||
file_table: Mutex::new(Some(file_table.clone_ro())),
|
||||
sig_mask,
|
||||
sig_queues,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
use core::sync::atomic::{AtomicU32, Ordering};
|
||||
|
||||
use aster_rights::{ReadDupOp, ReadOp, WriteOp};
|
||||
use ostd::sync::{RoArc, Waker};
|
||||
use ostd::sync::{RoArc, RwMutexReadGuard, Waker};
|
||||
|
||||
use super::{
|
||||
kill::SignalSenderIds,
|
||||
|
|
@ -19,7 +19,7 @@ use super::{
|
|||
};
|
||||
use crate::{
|
||||
events::Observer,
|
||||
fs::file_table::FileTable,
|
||||
fs::{file_table::FileTable, thread_info::ThreadFsInfo},
|
||||
prelude::*,
|
||||
process::{namespace::nsproxy::NsProxy, signal::constants::SIGCONT},
|
||||
thread::{Thread, Tid},
|
||||
|
|
@ -53,6 +53,9 @@ pub struct PosixThread {
|
|||
/// Process credentials. At the kernel level, credentials are a per-thread attribute.
|
||||
credentials: Credentials,
|
||||
|
||||
/// The file system information of the thread.
|
||||
fs: RwMutex<Arc<ThreadFsInfo>>,
|
||||
|
||||
// Files
|
||||
/// File table
|
||||
file_table: Mutex<Option<RoArc<FileTable>>>,
|
||||
|
|
@ -100,6 +103,17 @@ impl PosixThread {
|
|||
&self.name
|
||||
}
|
||||
|
||||
/// Returns a read guard to the filesystem information of the thread.
|
||||
pub fn fs(&self) -> RwMutexReadGuard<Arc<ThreadFsInfo>> {
|
||||
self.fs.read()
|
||||
}
|
||||
|
||||
/// Updates the filesystem information of the thread.
|
||||
pub fn update_fs(&self, new_fs: Arc<ThreadFsInfo>) {
|
||||
let mut fs_lock = self.fs.write();
|
||||
*fs_lock = new_fs;
|
||||
}
|
||||
|
||||
pub fn file_table(&self) -> &Mutex<Option<RoArc<FileTable>>> {
|
||||
&self.file_table
|
||||
}
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ impl ThreadLocal {
|
|||
}
|
||||
|
||||
pub fn is_fs_shared(&self) -> bool {
|
||||
Arc::strong_count(&self.fs.borrow()) > 1
|
||||
Arc::strong_count(&self.fs.borrow()) > 2
|
||||
}
|
||||
|
||||
pub fn sig_context(&self) -> &Cell<Option<Vaddr>> {
|
||||
|
|
|
|||
Loading…
Reference in New Issue