Skip to content
Merged
29 changes: 27 additions & 2 deletions kernel/inc/fs/vfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,12 @@ int vfs_unregister_filesystem(file_system_type_t *fs);

/// @brief Register a superblock for the filesystem.
/// @param name The name of the superblock.
/// @param path The path associated with the superblock.
/// @param path The mount point path associated with the superblock.
/// @param source The mount source (device/file) used for this filesystem.
/// @param type A pointer to the filesystem type.
/// @param root A pointer to the root file of the filesystem.
/// @return 1 on success, 0 on failure.
int vfs_register_superblock(const char *name, const char *path, file_system_type_t *type, vfs_file_t *root);
int vfs_register_superblock(const char *name, const char *path, const char *source, file_system_type_t *type, vfs_file_t *root);

/// @brief Unregister a superblock.
/// @param sb A pointer to the superblock to unregister.
Expand All @@ -73,6 +74,18 @@ super_block_t *vfs_get_superblock(const char *absolute_path);
/// @param log_level Logging level to use for the output.
void vfs_dump_superblocks(int log_level);

/// @brief Callback used for iterating all mounted superblocks.
/// @param sb Pointer to the current superblock.
/// @param ctx User-provided context pointer.
/// @return 0 to continue iteration, non-zero to stop early.
typedef int (*vfs_superblock_iter_fn)(super_block_t *sb, void *ctx);

/// @brief Iterate over all mounted superblocks.
/// @param fn Callback to execute for each superblock.
/// @param ctx User-provided context passed to the callback.
/// @return 0 if iteration completed, otherwise the non-zero return value from the callback.
int vfs_superblock_for_each(vfs_superblock_iter_fn fn, void *ctx);

/// @brief Open a file given its absolute path.
/// @param absolute_path An absolute path to the file.
/// @param flags Used to set the file status flags and access modes.
Expand Down Expand Up @@ -187,12 +200,24 @@ int vfs_symlink(const char *linkname, const char *path);
/// @return 0 on success, -errno on failure.
int vfs_stat(const char *path, stat_t *buf);

/// @brief Retrieve filesystem statistics for the mounted filesystem containing path.
/// @param path Path used to resolve the target mounted filesystem.
/// @param buf Buffer where filesystem statistics are stored.
/// @return 0 on success, -errno on failure.
int vfs_statfs(const char *path, statfs_t *buf);

/// @brief Stat the given file.
/// @param file Pointer to the file for which we are retrieving the statistics.
/// @param buf Buffer where we are storing the statistics.
/// @return 0 on success, -errno on failure.
int vfs_fstat(vfs_file_t *file, stat_t *buf);

/// @brief Retrieve filesystem statistics for the mounted filesystem containing file.
/// @param file Pointer to an open file on the target mounted filesystem.
/// @param buf Buffer where filesystem statistics are stored.
/// @return 0 on success, -errno on failure.
int vfs_fstatfs(vfs_file_t *file, statfs_t *buf);

/// @brief Mount the path as a filesystem of the given type.
/// @param type The type of filesystem
/// @param path The path to where it should be mounter.
Expand Down
18 changes: 15 additions & 3 deletions kernel/inc/fs/vfs_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
#pragma once

#include "bits/stat.h"
#include "bits/statfs.h"
#include "dirent.h"
#include "limits.h"
#include "list_head.h"
#include "stdint.h"

Expand Down Expand Up @@ -53,6 +55,8 @@ typedef struct vfs_sys_operations {
int (*rmdir_f)(const char *);
/// Retrieves file status information.
int (*stat_f)(const char *, stat_t *);
/// Retrieves filesystem status information.
int (*statfs_f)(const char *, statfs_t *);
/// Creates a new file or directory.
struct vfs_file *(*creat_f)(const char *, mode_t);
/// Creates a symbolic link.
Expand Down Expand Up @@ -137,8 +141,10 @@ typedef struct vfs_file {
typedef struct super_block {
/// Name of the superblock.
char name[NAME_MAX];
/// Path of the superblock.
/// Mount point path of the superblock.
char path[PATH_MAX];
/// Source (device/file) used to mount the filesystem.
char source[PATH_MAX];
/// Pointer to the root file of the given filesystem.
struct vfs_file *root;
/// Pointer to the information regarding the filesystem.
Expand All @@ -163,7 +169,13 @@ typedef struct vfs_file_descriptor {
#define ATTR_CTIME (1 << 5) ///< Flag set to specify the validity of CTIME.

/// Used to initialize an iattr inside the chown function.
#define IATTR_CHOWN(user, group) {.ia_valid = ATTR_UID | ATTR_GID, .ia_uid = (user), .ia_gid = (group)}
#define IATTR_CHOWN(user, group) \
{ \
.ia_valid = ATTR_UID | ATTR_GID, .ia_uid = (user), .ia_gid = (group) \
}

/// Used to initialize an iattr inside the chmod function.
#define IATTR_CHMOD(mode) {.ia_valid = ATTR_MODE, .ia_mode = (mode)}
#define IATTR_CHMOD(mode) \
{ \
.ia_valid = ATTR_MODE, .ia_mode = (mode) \
}
12 changes: 12 additions & 0 deletions kernel/inc/system/syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,18 @@ int sys_stat(const char *path, stat_t *buf);
/// @return Returns a negative value on failure.
int sys_fstat(int fd, stat_t *buf);

/// @brief Retrieve filesystem statistics for the mounted filesystem containing path.
/// @param path A path on the target mounted filesystem.
/// @param buf A structure where filesystem statistics will be stored.
/// @return Returns a negative value on failure.
int sys_statfs(const char *path, statfs_t *buf);

/// @brief Retrieve filesystem statistics for an open file descriptor.
/// @param fd The file descriptor of a file on the target mounted filesystem.
/// @param buf A structure where filesystem statistics will be stored.
/// @return Returns a negative value on failure.
int sys_fstatfs(int fd, statfs_t *buf);

/// @brief Creates a new directory at the given path.
/// @param path The path of the new directory.
/// @param mode The permission of the new directory.
Expand Down
2 changes: 1 addition & 1 deletion kernel/src/drivers/ata.c
Original file line number Diff line number Diff line change
Expand Up @@ -1694,7 +1694,7 @@ static ata_device_type_t ata_device_detect(ata_device_t *dev)
// Update the filesystem entry with the length of the device.
dev->fs_root->length = ata_max_offset(dev);
// Try to mount the drive.
if (!vfs_register_superblock(dev->fs_root->name, dev->path, &ata_file_system_type, dev->fs_root)) {
if (!vfs_register_superblock(dev->fs_root->name, dev->path, dev->path, &ata_file_system_type, dev->fs_root)) {
pr_alert("Failed to mount ata device!\n");
// Free the memory.
vfs_dealloc_file(dev->fs_root);
Expand Down
19 changes: 18 additions & 1 deletion kernel/src/drivers/mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,14 @@ static vfs_file_t *find_device_file(const char *path)
}

static int mem_stat(const char *path, stat_t *stat);
static int mem_statfs(const char *path, statfs_t *statfs);

/// @brief System operations for the memory device.
static vfs_sys_operations_t mem_sys_operations = {
.mkdir_f = NULL,
.rmdir_f = NULL,
.stat_f = mem_stat,
.statfs_f = mem_statfs,
};

static vfs_file_t *null_mount_callback(const char *path, const char *device);
Expand Down Expand Up @@ -143,6 +145,21 @@ static int mem_stat(const char *path, stat_t *stat)
return -ENOENT;
}

static int mem_statfs(const char *path, statfs_t *statfs)
{
(void)path;
if (statfs == NULL) {
return -EINVAL;
}

memset(statfs, 0, sizeof(statfs_t));
statfs->f_type = 0;
statfs->f_bsize = 1;
statfs->f_namelen = NAME_MAX;
statfs->f_frsize = 1;
return 0;
}

/// @brief The mount callback, which prepares everything and calls the actual
/// NULL mount function.
///
Expand Down Expand Up @@ -371,7 +388,7 @@ int mem_devs_initialize(void)
}

// Mount the /dev/null device.
if (!vfs_register_superblock("null", "/dev/null", &null_file_system_type, devnull->file)) {
if (!vfs_register_superblock("null", "/dev/null", "/dev/null", &null_file_system_type, devnull->file)) {
pr_err("mem_devs_initialize: Failed to mount /dev/null\n");
return 1; // Return error if mounting fails.
}
Expand Down
29 changes: 29 additions & 0 deletions kernel/src/fs/ext2.c
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,7 @@ static int ext2_fsetattr(vfs_file_t *file, struct iattr *attr);
static int ext2_mkdir(const char *path, mode_t mode);
static int ext2_rmdir(const char *path);
static int ext2_stat(const char *path, stat_t *stat);
static int ext2_statfs(const char *path, statfs_t *statfs);
static int ext2_setattr(const char *path, struct iattr *attr);
static vfs_file_t *ext2_creat(const char *path, mode_t mode);
static vfs_file_t *ext2_mount(vfs_file_t *block_device, const char *path);
Expand All @@ -397,6 +398,7 @@ static vfs_sys_operations_t ext2_sys_operations = {
.mkdir_f = ext2_mkdir,
.rmdir_f = ext2_rmdir,
.stat_f = ext2_stat,
.statfs_f = ext2_statfs,
.creat_f = ext2_creat,
.symlink_f = NULL,
.setattr_f = ext2_setattr,
Expand Down Expand Up @@ -3522,6 +3524,33 @@ static int ext2_stat(const char *path, stat_t *stat)
return __ext2_stat(fs, &inode, search.direntry.inode, stat);
}

static int ext2_statfs(const char *path, statfs_t *statfs)
{
ext2_filesystem_t *fs = get_ext2_filesystem(path);
if (fs == NULL) {
pr_err("ext2_statfs(path: %s): Failed to get the EXT2 filesystem.\n", path);
return -ENOENT;
}

if (statfs == NULL) {
return -EINVAL;
}

memset(statfs, 0, sizeof(statfs_t));
statfs->f_type = EXT2_SUPERBLOCK_MAGIC;
statfs->f_bsize = fs->block_size;
statfs->f_blocks = fs->superblock.blocks_count;
statfs->f_bfree = fs->superblock.free_blocks_count;
statfs->f_bavail = (fs->superblock.free_blocks_count > fs->superblock.r_blocks_count)
? (fs->superblock.free_blocks_count - fs->superblock.r_blocks_count)
: 0;
statfs->f_files = fs->superblock.inodes_count;
statfs->f_ffree = fs->superblock.free_inodes_count;
statfs->f_namelen = EXT2_NAME_LEN;
statfs->f_frsize = fs->block_size;
return 0;
}

/// @brief Perform the I/O control operation specified by REQUEST on FD. One
/// argument may follow; its presence and type depend on REQUEST.
/// @param file the file on which we perform the operations.
Expand Down
17 changes: 17 additions & 0 deletions kernel/src/fs/procfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ procfs_t fs;
static int procfs_mkdir(const char *path, mode_t mode);
static int procfs_rmdir(const char *path);
static int procfs_stat(const char *path, stat_t *stat);
static int procfs_statfs(const char *path, statfs_t *statfs);

static vfs_file_t *procfs_open(const char *path, int flags, mode_t mode);
static int procfs_unlink(const char *path);
Expand All @@ -102,6 +103,7 @@ static vfs_sys_operations_t procfs_sys_operations = {
.mkdir_f = procfs_mkdir,
.rmdir_f = procfs_rmdir,
.stat_f = procfs_stat,
.statfs_f = procfs_statfs,
.creat_f = NULL,
.symlink_f = NULL,
};
Expand Down Expand Up @@ -843,6 +845,21 @@ static inline ssize_t procfs_getdents(vfs_file_t *file, dirent_t *dirp, off_t do
return written_size;
}

static int procfs_statfs(const char *path, statfs_t *statfs)
{
(void)path;
if (!statfs) {
return -EINVAL;
}

memset(statfs, 0, sizeof(statfs_t));
statfs->f_type = 0x9fa0;
statfs->f_bsize = 1024;
statfs->f_namelen = PROCFS_NAME_MAX;
statfs->f_frsize = 1024;
return 0;
}

/// @brief Mounts the block device as a procfs filesystem.
/// @param block_device the block device formatted as procfs.
/// @param path location where we mount the filesystem.
Expand Down
23 changes: 23 additions & 0 deletions kernel/src/fs/stat.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,26 @@ int sys_fstat(int fd, stat_t *buf)

return vfs_fstat(vfd->file_struct, buf);
}

int sys_statfs(const char *path, statfs_t *buf) { return vfs_statfs(path, buf); }

int sys_fstatfs(int fd, statfs_t *buf)
{
// Get the current task.
task_struct *task = scheduler_get_current_process();

// Check the current FD.
if (fd < 0 || fd >= task->max_fd) {
return -EMFILE;
}

// Get the file descriptor.
vfs_file_descriptor_t *vfd = &task->fd_list[fd];

// Check the file.
if (vfd->file_struct == NULL) {
return -ENOSYS;
}

return vfs_fstatfs(vfd->file_struct, buf);
}
Loading
Loading