syscalls: statvfs

This commit is contained in:
Matheus
2026-03-20 21:28:59 -03:00
parent d0bb48c162
commit f8694029ab
6 changed files with 212 additions and 5 deletions
+5 -1
View File
@@ -99,6 +99,8 @@ extern syscall_sysinfo
extern syscall_writev
extern syscall_readv
extern syscall_yield
extern syscall_fstatvfs
extern syscall_fstatvfsat
syscalltab:
dq syscall_print
dq syscall_mmap
@@ -200,7 +202,9 @@ dq syscall_sysinfo
dq syscall_writev
dq syscall_readv
dq syscall_yield
syscallcount equ 100
dq syscall_fstatvfs
dq syscall_fstatvfsat
syscallcount equ 102
section .text
global arch_syscall_entry
; on entry:
+8 -2
View File
@@ -8,7 +8,7 @@
void arch_interrupt_disable();
void arch_interrupt_enable();
#define SYSCALL_COUNT 99
#define SYSCALL_COUNT 102
#define LOGSTR(x) arch_e9_puts(x)
static char *name[] = {
@@ -110,7 +110,10 @@ static char *name[] = {
"getcpu",
"sysinfo",
"writev",
"readv"
"readv",
"yield",
"fstatvfs",
"fstatvfsat",
};
static char *args[] = {
@@ -213,6 +216,9 @@ static char *args[] = {
"ptr %p", // sysinfo
"fd %d iov %p iovcnt %d", // writev
"fd %d iov %p iovcnt %d", // readv
"N/A", // yield
"fd %d ustat %p", // fstatvfs
"dirfd %d path %s ustat %p flags %d", // fstatvfsat
};
#endif
+26 -1
View File
@@ -1969,6 +1969,30 @@ static int ext2_inactive(vnode_t *vnode) {
return 0;
}
static int ext2_statfs(vfs_t *vfs, fsattr_t *fsattr) {
ext2fs_t *ext2fs = (ext2fs_t *)vfs;
fsattr->io_size = ext2fs->blocksize;
fsattr->block_size = ext2fs->blocksize;
fsattr->block_count = ext2fs->superblock.blockcount;
fsattr->inode_count = ext2fs->superblock.inodecount;
MUTEX_ACQUIRE(&ext2fs->superblocklock);
fsattr->free_blocks = ext2fs->superblock.unallocatedblocks;
fsattr->free_blocks_unprivileged = ext2fs->superblock.unallocatedblocks;
fsattr->free_inode_count = ext2fs->superblock.unallocatedinodes;
fsattr->free_inode_count_unprivileged = ext2fs->superblock.unallocatedinodes;
MUTEX_RELEASE(&ext2fs->superblocklock);
fsattr->fsid = 0; // TODO
fsattr->flags = 0;
fsattr->max_name_size = 255;
return 0;
}
// TODO move root variable to vfs
static int ext2_root(vfs_t *vfs, vnode_t **vnodep) {
ext2fs_t *fs = (ext2fs_t *)vfs;
@@ -2102,7 +2126,8 @@ static int ext2_mount(vfs_t **vfs, vnode_t *mountpoint, vnode_t *backing, void *
static vfsops_t vfsops = {
.mount = ext2_mount,
.root = ext2_root
.root = ext2_root,
.statfs = ext2_statfs
};
static vops_t vnops = {
+24 -1
View File
@@ -560,9 +560,32 @@ static int tmpfs_unlock(vnode_t *node) {
return 0;
}
static int tmpfs_statfs(vfs_t *vfs, fsattr_t *fsattr) {
tmpfs_t *tmpfs = (tmpfs_t *)vfs;
size_t total_pages, free_pages;
pmm_getinfo(&total_pages, &free_pages);
fsattr->io_size = PAGE_SIZE;
fsattr->block_size = PAGE_SIZE;
fsattr->block_count = total_pages;
fsattr->free_blocks = free_pages;
fsattr->free_blocks_unprivileged = free_pages;
fsattr->inode_count = INT64_MAX;
fsattr->free_inode_count = INT64_MAX;
fsattr->free_inode_count_unprivileged = INT64_MAX;
fsattr->fsid = tmpfs->id;
fsattr->flags = 0;
fsattr->max_name_size = 255;
return 0;
}
static vfsops_t vfsops = {
.mount = tmpfs_mount,
.root = tmpfs_root
.root = tmpfs_root,
.statfs = tmpfs_statfs
};
static vops_t vnops = {
+16
View File
@@ -65,6 +65,20 @@ typedef struct {
size_t blocksused;
} vattr_t;
typedef struct {
size_t io_size;
size_t block_size;
size_t block_count;
size_t free_blocks;
size_t free_blocks_unprivileged;
size_t inode_count;
size_t free_inode_count;
size_t free_inode_count_unprivileged;
unsigned long fsid;
unsigned long flags;
size_t max_name_size;
} fsattr_t;
typedef struct vfs_t {
struct vfs_t *next;
struct vfsops_t *ops;
@@ -131,6 +145,7 @@ typedef struct vfsops_t {
int (*unmount)(vfs_t *vfs);
int (*sync)(vfs_t *vfs);
int (*root)(vfs_t *vfs, vnode_t **root);
int (*statfs)(vfs_t *vfs, fsattr_t *fsattr);
} vfsops_t;
struct polldata;
@@ -178,6 +193,7 @@ typedef struct vops_t {
#define VFS_UNMOUNT(vfs) (vfs)->ops->unmount(vfs)
#define VFS_ROOT(vfs, r) (vfs)->ops->root(vfs, r)
#define VFS_SYNC(vfs) (vfs)->ops->sync(vfs)
#define VFS_STATFS(vfs, f) ((vfs)->ops->statfs ? (vfs)->ops->statfs(vfs, f) : ENOSYS)
#define VOP_INIT(vn, o, f, t, v) \
(vn)->ops = o; \
+133
View File
@@ -0,0 +1,133 @@
#include <kernel/syscalls.h>
#include <kernel/abi.h>
#include <kernel/vfs.h>
#include <arch/cpu.h>
#include <errno.h>
#include <kernel/file.h>
#include <kernel/alloc.h>
typedef uint64_t fsblkcnt_t;
typedef uint64_t fsfilcnt_t;
typedef struct {
unsigned long f_bsize;
unsigned long f_frsize;
fsblkcnt_t f_blocks;
fsblkcnt_t f_bfree;
fsblkcnt_t f_bavail;
fsfilcnt_t f_files;
fsfilcnt_t f_ffree;
fsfilcnt_t f_favail;
unsigned long f_fsid;
unsigned long f_flag;
unsigned long f_namemax;
} statvfs_t;
syscallret_t syscall_fstatvfs(context_t *ctx, int fd, statvfs_t *ustatvfs) {
syscallret_t ret = {
.ret = -1
};
file_t *file = fd_get(fd);
if (file == NULL) {
ret.errno = EBADF;
return ret;
}
fsattr_t buf;
ret.errno = VFS_STATFS(file->vnode->vfs, &buf);
if (ret.errno)
goto cleanup;
statvfs_t output = {
.f_bsize = buf.io_size,
.f_frsize = buf.block_size,
.f_blocks = buf.block_count,
.f_bfree = buf.free_blocks,
.f_bavail = buf.free_blocks_unprivileged,
.f_files = buf.inode_count,
.f_ffree = buf.free_inode_count,
.f_favail = buf.free_inode_count_unprivileged,
.f_fsid = buf.fsid,
.f_flag = buf.flags,
.f_namemax = buf.max_name_size
};
ret.errno = usercopy_touser(ustatvfs, &output, sizeof(statvfs_t));
ret.ret = ret.errno ? -1 : 0;
cleanup:
fd_release(file);
return ret;
}
syscallret_t syscall_fstatvfsat(context_t *ctx, int dirfd, char *upath, stat_t *ustatvfs, int flags) {
syscallret_t ret = {
.ret = -1
};
size_t pathlen;
ret.errno = usercopy_strlen(upath, &pathlen);
if (ret.errno)
return ret;
char *path = alloc(pathlen + 1);
if (path == NULL) {
ret.errno = ENOMEM;
return ret;
}
ret.errno = usercopy_fromuser(path, upath, pathlen);
if (ret.errno) {
free(path);
return ret;
}
vnode_t *dirnode = NULL;
file_t *file = NULL;
ret.errno = dirfd_enter(path, dirfd, &file, &dirnode);
if (ret.errno)
goto cleanup;
vnode_t *node = NULL;
ret.errno = vfs_lookup(&node, dirnode, path, NULL, flags & AT_SYMLINK_NOFOLLOW ? VFS_LOOKUP_NOLINK : 0);
if (ret.errno)
goto cleanup;
// locked by vfs_lookup
VOP_UNLOCK(node);
fsattr_t buf;
ret.errno = VFS_STATFS(node->vfs, &buf);
if (ret.errno)
goto cleanup;
statvfs_t output = {
.f_bsize = buf.io_size,
.f_frsize = buf.block_size,
.f_blocks = buf.block_count,
.f_bfree = buf.free_blocks,
.f_bavail = buf.free_blocks_unprivileged,
.f_files = buf.inode_count,
.f_ffree = buf.free_inode_count,
.f_favail = buf.free_inode_count_unprivileged,
.f_fsid = buf.fsid,
.f_flag = buf.flags,
.f_namemax = buf.max_name_size
};
ret.errno = usercopy_touser(ustatvfs, &output, sizeof(statvfs_t));
ret.ret = ret.errno ? -1 : 0;
cleanup:
if (node)
VOP_RELEASE(node);
if (dirnode)
dirfd_leave(dirnode, file);
free(path);
return ret;
}