mirror of
https://github.com/hexagonal-sun/moss-kernel.git
synced 2026-04-18 14:19:01 -04:00
Merge pull request #203 from arihant2math/statfs
Implement `sys_statfs` and `sys_fstatfs`
This commit is contained in:
@@ -43,8 +43,8 @@
|
||||
| 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 |
|
||||
| 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 |
|
||||
| 0x2b (43) | statfs | (const char *pathname, struct statfs *buf) | __arm64_sys_statfs | partial |
|
||||
| 0x2c (44) | fstatfs | (unsigned int fd, struct statfs *buf) | __arm64_sys_fstatfs | partial |
|
||||
| 0x2d (45) | truncate | (const char *path, long length) | __arm64_sys_truncate | true |
|
||||
| 0x2e (46) | ftruncate | (unsigned int fd, off_t length) | __arm64_sys_ftruncate | true |
|
||||
| 0x2f (47) | fallocate | (int fd, int mode, loff_t offset, loff_t len) | __arm64_sys_fallocate | false |
|
||||
|
||||
@@ -362,6 +362,11 @@ where
|
||||
self.id
|
||||
}
|
||||
|
||||
fn magic(&self) -> u64 {
|
||||
// TODO: retrieve magic from superblock instead of hardcoding
|
||||
0xef53 // EXT4 magic number
|
||||
}
|
||||
|
||||
/// Returns the root inode of the mounted EXT4 filesystem.
|
||||
async fn root_inode(&self) -> Result<Arc<dyn Inode>> {
|
||||
let root = self.inner.read_root_inode().await?;
|
||||
|
||||
@@ -168,6 +168,10 @@ impl Filesystem for Fat32Filesystem {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn magic(&self) -> u64 {
|
||||
0x4D44 // MSDOS magic number
|
||||
}
|
||||
|
||||
/// Get the root inode of this filesystem.
|
||||
async fn root_inode(&self) -> Result<Arc<dyn Inode>> {
|
||||
Ok(Arc::new(Fat32DirNode::new(
|
||||
|
||||
@@ -821,6 +821,10 @@ where
|
||||
fn id(&self) -> u64 {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn magic(&self) -> u64 {
|
||||
0x01021994 // Tmpfs magic number
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -65,6 +65,9 @@ pub trait Filesystem: Send + Sync {
|
||||
/// Returns the instance ID for this FS.
|
||||
fn id(&self) -> u64;
|
||||
|
||||
/// Get magic
|
||||
fn magic(&self) -> u64;
|
||||
|
||||
/// Flushes all pending data to the underlying storage device(s).
|
||||
///
|
||||
/// The default implementation is a no-op so that read-only filesystems do
|
||||
|
||||
@@ -38,6 +38,7 @@ use crate::{
|
||||
setxattr::{sys_fsetxattr, sys_lsetxattr, sys_setxattr},
|
||||
splice::sys_sendfile,
|
||||
stat::sys_fstat,
|
||||
statfs::{sys_fstatfs, sys_statfs},
|
||||
sync::{sys_fdatasync, sys_fsync, sys_sync, sys_syncfs},
|
||||
trunc::{sys_ftruncate, sys_truncate},
|
||||
},
|
||||
@@ -227,7 +228,8 @@ pub async fn handle_syscall() {
|
||||
)
|
||||
.await
|
||||
}
|
||||
0x2b | 0x2c => Err(KernelError::NotSupported),
|
||||
0x2b => sys_statfs(TUA::from_value(arg1 as _), TUA::from_value(arg2 as _)).await,
|
||||
0x2c => sys_fstatfs(arg1.into(), TUA::from_value(arg2 as _)).await,
|
||||
0x2d => sys_truncate(TUA::from_value(arg1 as _), arg2 as _).await,
|
||||
0x2e => sys_ftruncate(arg1.into(), arg2 as _).await,
|
||||
0x30 => sys_faccessat(arg1.into(), TUA::from_value(arg2 as _), arg3 as _).await,
|
||||
|
||||
@@ -127,6 +127,10 @@ impl Filesystem for CgroupFs {
|
||||
fn id(&self) -> u64 {
|
||||
CGROUPFS_ID
|
||||
}
|
||||
|
||||
fn magic(&self) -> u64 {
|
||||
0x63677270 // v2 magic number
|
||||
}
|
||||
}
|
||||
|
||||
static SYSFS_INSTANCE: OnceLock<Arc<CgroupFs>> = OnceLock::new();
|
||||
|
||||
@@ -88,6 +88,11 @@ impl Filesystem for DevFs {
|
||||
fn id(&self) -> u64 {
|
||||
DEVFS_ID
|
||||
}
|
||||
|
||||
fn magic(&self) -> u64 {
|
||||
// TODO: Is this the right value
|
||||
0x01021994 // TMPFS_MAGIC
|
||||
}
|
||||
}
|
||||
|
||||
enum InodeKind {
|
||||
|
||||
@@ -51,6 +51,10 @@ impl Filesystem for ProcFs {
|
||||
fn id(&self) -> u64 {
|
||||
PROCFS_ID
|
||||
}
|
||||
|
||||
fn magic(&self) -> u64 {
|
||||
0x9fa0 // procfs magic number
|
||||
}
|
||||
}
|
||||
|
||||
static PROCFS_INSTANCE: OnceLock<Arc<ProcFs>> = OnceLock::new();
|
||||
|
||||
@@ -176,6 +176,10 @@ impl Filesystem for SysFs {
|
||||
fn id(&self) -> u64 {
|
||||
SYSFS_ID
|
||||
}
|
||||
|
||||
fn magic(&self) -> u64 {
|
||||
0x62656572 // sysfs magic number
|
||||
}
|
||||
}
|
||||
|
||||
static SYSFS_INSTANCE: OnceLock<Arc<SysFs>> = OnceLock::new();
|
||||
|
||||
@@ -177,6 +177,13 @@ impl VFS {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn get_fs(&self, inode: Arc<dyn Inode>) -> Result<Arc<dyn Filesystem>> {
|
||||
self.state
|
||||
.lock_save_irq()
|
||||
.get_fs(inode.id())
|
||||
.ok_or(KernelError::from(FsError::NoDevice))
|
||||
}
|
||||
|
||||
/// Resolves a path string to an Inode, starting from a given root for
|
||||
/// relative paths.
|
||||
pub async fn resolve_path(
|
||||
|
||||
@@ -14,5 +14,6 @@ pub mod seek;
|
||||
pub mod setxattr;
|
||||
pub mod splice;
|
||||
pub mod stat;
|
||||
pub mod statfs;
|
||||
pub mod sync;
|
||||
pub mod trunc;
|
||||
|
||||
88
src/fs/syscalls/statfs.rs
Normal file
88
src/fs/syscalls/statfs.rs
Normal file
@@ -0,0 +1,88 @@
|
||||
use crate::fs::VFS;
|
||||
use crate::memory::uaccess::cstr::UserCStr;
|
||||
use crate::memory::uaccess::{UserCopyable, copy_to_user};
|
||||
use crate::process::fd_table::Fd;
|
||||
use crate::sched::current::{current_task, current_task_shared};
|
||||
use alloc::sync::Arc;
|
||||
use core::ffi::c_char;
|
||||
use libkernel::error::KernelError;
|
||||
use libkernel::fs::Inode;
|
||||
use libkernel::fs::path::Path;
|
||||
use libkernel::memory::address::TUA;
|
||||
use libkernel::pod::Pod;
|
||||
|
||||
type FswordT = u32;
|
||||
type FsBlockCntT = u64;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct StatFs {
|
||||
/// Type of filesystem
|
||||
f_type: FswordT,
|
||||
/// Optimal transfer block size
|
||||
f_bsize: FswordT,
|
||||
/// Total data blocks in filesystem
|
||||
f_blocks: FsBlockCntT,
|
||||
/// Free blocks in filesystem
|
||||
f_bfree: FsBlockCntT,
|
||||
/// Free blocks available to unprivileged user
|
||||
f_bavail: FsBlockCntT,
|
||||
/// Total inodes in filesystem
|
||||
f_files: FsBlockCntT,
|
||||
/// Free inodes in filesystem
|
||||
f_ffree: FsBlockCntT,
|
||||
/// Filesystem ID
|
||||
f_fsid: u64,
|
||||
/// Maximum length of filenames
|
||||
f_namelen: FswordT,
|
||||
/// Fragment size (since Linux 2.6)
|
||||
f_frsize: FswordT,
|
||||
/// Mount flags of filesystem (since Linux 2.6.36)
|
||||
f_flags: FswordT,
|
||||
/// Padding bytes reserved for future use
|
||||
f_spare: [FswordT; 6],
|
||||
}
|
||||
|
||||
unsafe impl Pod for StatFs {}
|
||||
|
||||
unsafe impl UserCopyable for StatFs {}
|
||||
|
||||
async fn statfs_impl(inode: Arc<dyn Inode>) -> libkernel::error::Result<StatFs> {
|
||||
let fs = VFS.get_fs(inode).await?;
|
||||
Ok(StatFs {
|
||||
f_type: fs.magic() as _,
|
||||
f_bsize: 0,
|
||||
f_blocks: 0,
|
||||
f_bfree: 0,
|
||||
f_bavail: 0,
|
||||
f_files: 0,
|
||||
f_ffree: 0,
|
||||
f_fsid: fs.id(),
|
||||
f_namelen: 0,
|
||||
f_frsize: 0,
|
||||
f_flags: 0,
|
||||
f_spare: [0; 6],
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn sys_statfs(path: TUA<c_char>, stat: TUA<StatFs>) -> libkernel::error::Result<usize> {
|
||||
let mut buf = [0; 1024];
|
||||
let path = Path::new(UserCStr::from_ptr(path).copy_from_user(&mut buf).await?);
|
||||
let inode = VFS
|
||||
.resolve_path(path, VFS.root_inode(), ¤t_task_shared())
|
||||
.await?;
|
||||
let statfs = statfs_impl(inode).await?;
|
||||
copy_to_user(stat, statfs).await?;
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
pub async fn sys_fstatfs(fd: Fd, stat: TUA<StatFs>) -> libkernel::error::Result<usize> {
|
||||
let fd = current_task()
|
||||
.fd_table
|
||||
.lock_save_irq()
|
||||
.get(fd)
|
||||
.ok_or(KernelError::BadFd)?;
|
||||
let statfs = statfs_impl(fd.inode().ok_or(KernelError::InvalidValue)?).await?;
|
||||
copy_to_user(stat, statfs).await?;
|
||||
Ok(0)
|
||||
}
|
||||
Reference in New Issue
Block a user