Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions etc/syscalls_linux_aarch64.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
Expand Down
5 changes: 5 additions & 0 deletions libkernel/src/fs/filesystems/ext4/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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?;
Expand Down
4 changes: 4 additions & 0 deletions libkernel/src/fs/filesystems/fat32/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
4 changes: 4 additions & 0 deletions libkernel/src/fs/filesystems/tmpfs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -821,6 +821,10 @@ where
fn id(&self) -> u64 {
self.id
}

fn magic(&self) -> u64 {
0x01021994 // Tmpfs magic number
}
}

#[cfg(test)]
Expand Down
3 changes: 3 additions & 0 deletions libkernel/src/fs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 3 additions & 1 deletion src/arch/arm64/exceptions/syscall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
},
Expand Down Expand Up @@ -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,
Expand Down
4 changes: 4 additions & 0 deletions src/drivers/fs/cgroup/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
5 changes: 5 additions & 0 deletions src/drivers/fs/dev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
4 changes: 4 additions & 0 deletions src/drivers/fs/proc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
4 changes: 4 additions & 0 deletions src/drivers/fs/sys/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
7 changes: 7 additions & 0 deletions src/fs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
1 change: 1 addition & 0 deletions src/fs/syscalls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 88 additions & 0 deletions src/fs/syscalls/statfs.rs
Original file line number Diff line number Diff line change
@@ -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(), &current_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)
}