From f1385e7f929538f535ad1040443b03ba16060e65 Mon Sep 17 00:00:00 2001 From: Ashwin Naren Date: Tue, 20 Jan 2026 19:52:27 -0800 Subject: [PATCH 1/2] mount implementation --- etc/syscalls_linux_aarch64.md | 2 +- src/arch/arm64/exceptions/syscall.rs | 11 ++++++++ src/drivers/fs/proc/task/fd.rs | 27 ++++++++++++++++++- src/fs/mod.rs | 20 ++++++++++++++ src/fs/syscalls/mod.rs | 1 + src/fs/syscalls/mount.rs | 40 ++++++++++++++++++++++++++++ 6 files changed, 99 insertions(+), 2 deletions(-) create mode 100644 src/fs/syscalls/mount.rs diff --git a/etc/syscalls_linux_aarch64.md b/etc/syscalls_linux_aarch64.md index f2b94e7a..b097ffc7 100644 --- a/etc/syscalls_linux_aarch64.md +++ b/etc/syscalls_linux_aarch64.md @@ -41,7 +41,7 @@ | 0x25 (37) | linkat | (int olddfd, const char *oldname, int newdfd, const char *newname, int flags) | __arm64_sys_linkat | true | | 0x26 (38) | renameat | (int olddfd, const char *oldname, int newdfd, const char *newname) | __arm64_sys_renameat | true | | 0x27 (39) | umount | (char *name, int flags) | __arm64_sys_umount | false | -| 0x28 (40) | mount | (char *dev_name, char *dir_name, char *type, unsigned long flags, void *data) | __arm64_sys_mount | false | +| 0x28 (40) | mount | (char *dev_name, char *dir_name, char *type, unsigned long flags, void *data) | __arm64_sys_mount | partial | | 0x29 (41) | pivot_root | (const char *new_root, const char *put_old) | __arm64_sys_pivot_root | false | | 0x2b (43) | statfs | (const char *pathname, struct statfs *buf) | __arm64_sys_statfs | dummy | | 0x2c (44) | fstatfs | (unsigned int fd, struct statfs *buf) | __arm64_sys_fstatfs | dummy | diff --git a/src/arch/arm64/exceptions/syscall.rs b/src/arch/arm64/exceptions/syscall.rs index 39eeda18..a2872fb7 100644 --- a/src/arch/arm64/exceptions/syscall.rs +++ b/src/arch/arm64/exceptions/syscall.rs @@ -32,6 +32,7 @@ use crate::{ ioctl::sys_ioctl, iov::{sys_preadv, sys_preadv2, sys_pwritev, sys_pwritev2, sys_readv, sys_writev}, listxattr::{sys_flistxattr, sys_listxattr, sys_llistxattr}, + mount::sys_mount, removexattr::{sys_fremovexattr, sys_lremovexattr, sys_removexattr}, rw::{sys_pread64, sys_pwrite64, sys_read, sys_write}, seek::sys_lseek, @@ -224,6 +225,16 @@ pub async fn handle_syscall() { ) .await } + 0x28 => { + sys_mount( + TUA::from_value(arg1 as _), + TUA::from_value(arg2 as _), + TUA::from_value(arg3 as _), + arg4 as _, + TUA::from_value(arg5 as _), + ) + .await + } 0x2b | 0x2c => Err(KernelError::NotSupported), 0x2d => sys_truncate(TUA::from_value(arg1 as _), arg2 as _).await, 0x2e => sys_ftruncate(arg1.into(), arg2 as _).await, diff --git a/src/drivers/fs/proc/task/fd.rs b/src/drivers/fs/proc/task/fd.rs index 781c713b..1d3edba1 100644 --- a/src/drivers/fs/proc/task/fd.rs +++ b/src/drivers/fs/proc/task/fd.rs @@ -2,6 +2,7 @@ use crate::drivers::fs::proc::{get_inode_id, procfs}; use crate::process::fd_table::Fd; use crate::process::{TaskDescriptor, find_task_by_descriptor}; use crate::sched::current::current_task_shared; +use alloc::borrow::ToOwned; use alloc::boxed::Box; use alloc::format; use alloc::string::ToString; @@ -11,6 +12,7 @@ use async_trait::async_trait; use libkernel::error::Result; use libkernel::error::{FsError, KernelError}; use libkernel::fs::attr::FileAttr; +use libkernel::fs::pathbuf::PathBuf; use libkernel::fs::{ DirStream, Dirent, FileType, Filesystem, Inode, InodeId, SimpleDirStream, SimpleFile, }; @@ -115,7 +117,11 @@ impl ProcFdFile { Self { id: inode_id, attr: FileAttr { - file_type: FileType::File, + file_type: if fd_info { + FileType::File + } else { + FileType::Symlink + }, // Define appropriate file attributes for fdinfo file. ..FileAttr::default() }, @@ -151,4 +157,23 @@ impl SimpleFile for ProcFdFile { Err(KernelError::NotSupported) } } + + async fn readlink(&self) -> Result { + if !self.fd_info { + if let Some(task) = find_task_by_descriptor(&self.desc) { + let Some(file) = task.fd_table.lock_save_irq().get(Fd(self.fd)) else { + return Err(FsError::NotFound.into()); + }; + if let Some(path) = file.path() { + Ok(path.to_owned()) + } else { + todo!(); + } + } else { + Err(FsError::NotFound.into()) + } + } else { + Err(KernelError::NotSupported) + } + } } diff --git a/src/fs/mod.rs b/src/fs/mod.rs index 7b51269b..a9e390c0 100644 --- a/src/fs/mod.rs +++ b/src/fs/mod.rs @@ -79,6 +79,13 @@ impl VfsState { self.mounts.insert(mount_point_id, mount); } + /// Removes a mount point by its inode ID. + fn remove_mount(&mut self, mount_point_id: &InodeId) -> Option<()> { + let mount = self.mounts.remove(mount_point_id)?; + self.filesystems.remove(&mount.fs.id())?; + Some(()) + } + /// Checks if an inode is a mount point and returns the root inode of the /// mounted filesystem if it is. fn get_mount_root(&self, inode_id: &InodeId) -> Option> { @@ -177,6 +184,19 @@ impl VFS { Ok(()) } + #[expect(unused)] + pub async fn unmount(&self, mount_point: Arc) -> Result<()> { + let mount_point_id = mount_point.id(); + + // Lock the state and remove the mount. + self.state + .lock_save_irq() + .remove_mount(&mount_point_id) + .ok_or(FsError::NotFound)?; + + Ok(()) + } + /// Resolves a path string to an Inode, starting from a given root for /// relative paths. pub async fn resolve_path( diff --git a/src/fs/syscalls/mod.rs b/src/fs/syscalls/mod.rs index 0cc93561..8005e343 100644 --- a/src/fs/syscalls/mod.rs +++ b/src/fs/syscalls/mod.rs @@ -7,6 +7,7 @@ pub mod getxattr; pub mod ioctl; pub mod iov; pub mod listxattr; +pub mod mount; pub mod open; pub mod removexattr; pub mod rw; diff --git a/src/fs/syscalls/mount.rs b/src/fs/syscalls/mount.rs new file mode 100644 index 00000000..b7e2dae7 --- /dev/null +++ b/src/fs/syscalls/mount.rs @@ -0,0 +1,40 @@ +use crate::fs::VFS; +use crate::memory::uaccess::cstr::UserCStr; +use crate::sched::current::current_task_shared; +use core::ffi::c_char; +use libkernel::error::Result; +use libkernel::fs::path::Path; +use libkernel::memory::address::{TUA, UA}; + +pub async fn sys_mount( + dev_name: TUA, + dir_name: TUA, + type_: TUA, + _flags: i64, + _data: UA, +) -> Result { + let mut buf = [0u8; 1024]; + let dev_name = UserCStr::from_ptr(dev_name) + .copy_from_user(&mut buf) + .await?; + let mut buf = [0u8; 1024]; + let dir_name = UserCStr::from_ptr(dir_name) + .copy_from_user(&mut buf) + .await?; + let mount_point = VFS + .resolve_path( + Path::new(dir_name), + VFS.root_inode(), + ¤t_task_shared(), + ) + .await?; + let mut buf = [0u8; 1024]; + let _type = UserCStr::from_ptr(type_).copy_from_user(&mut buf).await?; + let dev_name = match dev_name { + "proc" => "procfs", + "devtmpfs" => "devfs", + s => s, + }; + VFS.mount(mount_point, dev_name, None).await?; + Ok(0) +} From 53b5b81b2dd6516423efc6a586a157623f43b4b4 Mon Sep 17 00:00:00 2001 From: Ashwin Naren Date: Sat, 7 Feb 2026 10:35:57 -0800 Subject: [PATCH 2/2] mount fixups --- src/fs/syscalls/mount.rs | 75 ++++++++++++++++++++++++++++++++++------ 1 file changed, 64 insertions(+), 11 deletions(-) diff --git a/src/fs/syscalls/mount.rs b/src/fs/syscalls/mount.rs index b7e2dae7..b89ebabe 100644 --- a/src/fs/syscalls/mount.rs +++ b/src/fs/syscalls/mount.rs @@ -1,22 +1,67 @@ use crate::fs::VFS; use crate::memory::uaccess::cstr::UserCStr; use crate::sched::current::current_task_shared; +use bitflags::bitflags; use core::ffi::c_char; -use libkernel::error::Result; +use libkernel::error::{KernelError, Result}; use libkernel::fs::path::Path; use libkernel::memory::address::{TUA, UA}; +bitflags! { + #[derive(Debug)] + pub struct MountFlags: u64 { + const MS_RDONLY = 1; + const MS_NOSUID = 2; + const MS_NODEV = 4; + const MS_NOEXEC = 8; + const MS_SYNCHRONOUS = 16; + const MS_REMOUNT = 32; + const MS_MANDLOCK = 64; + const MS_DIRSYNC = 128; + const NOSYMFOLLOW = 256; + const MS_NOATIME = 1024; + const MS_NODIRATIME = 2048; + const MS_BIND = 4096; + const MS_MOVE = 8192; + const MS_REC = 16384; + const MS_VERBOSE = 32768; + const MS_SILENT = 65536; + const MS_POSIXACL = 1 << 16; + const MS_UNBINDABLE = 1 << 17; + const MS_PRIVATE = 1 << 18; + const MS_SLAVE = 1 << 19; + const MS_SHARED = 1 << 20; + const MS_RELATIME = 1 << 21; + const MS_KERNMOUNT = 1 << 22; + const MS_I_VERSION = 1 << 23; + const MS_STRICTATIME = 1 << 24; + const MS_LAZYTIME = 1 << 25; + const MS_SUBMOUNT = 1 << 26; + const MS_NOREMOTELOCK = 1 << 27; + const MS_NOSEC = 1 << 28; + const MS_BORN = 1 << 29; + const MS_ACTIVE = 1 << 30; + const MS_NOUSER = 1 << 31; + } +} + pub async fn sys_mount( dev_name: TUA, dir_name: TUA, type_: TUA, - _flags: i64, + flags: i64, _data: UA, ) -> Result { + let flags = MountFlags::from_bits_truncate(flags as u64); + if flags.contains(MountFlags::MS_REC) { + // TODO: Handle later + return Ok(0); + } let mut buf = [0u8; 1024]; let dev_name = UserCStr::from_ptr(dev_name) .copy_from_user(&mut buf) - .await?; + .await + .ok(); let mut buf = [0u8; 1024]; let dir_name = UserCStr::from_ptr(dir_name) .copy_from_user(&mut buf) @@ -29,12 +74,20 @@ pub async fn sys_mount( ) .await?; let mut buf = [0u8; 1024]; - let _type = UserCStr::from_ptr(type_).copy_from_user(&mut buf).await?; - let dev_name = match dev_name { - "proc" => "procfs", - "devtmpfs" => "devfs", - s => s, - }; - VFS.mount(mount_point, dev_name, None).await?; - Ok(0) + let _type = UserCStr::from_ptr(type_) + .copy_from_user(&mut buf) + .await + .ok(); + if let Some(dev_name) = dev_name { + let dev_name = match dev_name { + "proc" => "procfs", + "devtmpfs" => "devfs", + "cgroup2" => "cgroupfs", + s => s, + }; + VFS.mount(mount_point, dev_name, None).await?; + Ok(0) + } else { + Err(KernelError::NotSupported) + } }