#define MS_SYNCHRONOUS 16
#define MS_REMOUNT 32 /* Alter flags of existing mount */
+/* Filesystem type flags */
+#define FS_NEEDS_BDEV 0x01 /* Requires block device */
+
+struct fs_node; /* forward declaration */
+
+/* Filesystem type structure */
+typedef struct vfs_fs_type {
+ const char* name; /* e.g. "fat", "ext2" */
+ uint32_t flags; /* FS_NEEDS_BDEV, etc. */
+ struct fs_node* (*mount)(const block_device_t* bdev, uint32_t lba); /* Mount function */
+} vfs_fs_type_t;
+
+/* VFS superblock — per-mount filesystem metadata */
+typedef struct vfs_superblock {
+ const vfs_fs_type_t* fstype; /* Filesystem type */
+ const block_device_t* bdev; /* Block device (NULL for virtual FS) */
+ uint32_t lba; /* Partition start LBA (0 for whole disk) */
+ void* private_data; /* Filesystem-specific data (e.g. fat_mount, ext2_mount) */
+} vfs_superblock_t;
+
/* poll() event flags — shared between kernel VFS and syscall layer */
#define VFS_POLL_IN 0x0001
#define VFS_POLL_OUT 0x0004
#define VFS_POLL_ERR 0x0008
#define VFS_POLL_HUP 0x0010
-struct fs_node; /* forward declaration for file_operations */
-
/* File operations — per-open-fd I/O (requires an open file descriptor) */
struct file_operations {
uint32_t (*read)(struct fs_node* node, uint32_t offset, uint32_t size, uint8_t* buffer);
int vfs_mount_nolock(const char* mountpoint, fs_node_t* root);
int vfs_mount_nolock_full(const char* mountpoint, fs_node_t* root,
const char* fstype, const char* source,
- unsigned long flags, const block_device_t* bdev);
+ unsigned long flags, const block_device_t* bdev,
+ vfs_superblock_t* sb);
int vfs_umount_nolock(const char* mountpoint);
/* Read mount table for /proc/mounts. Returns bytes written. */
/* Look up mount flags by mount root node pointer. */
unsigned long vfs_node_mount_flags(const fs_node_t* root);
+/* Filesystem type registry */
+int vfs_fs_type_register(const vfs_fs_type_t* fst);
+const vfs_fs_type_t* vfs_fs_type_find(const char* name);
+
/* Find the mount root fs_node for a given path. */
fs_node_t* vfs_find_mount_root(const char* path);
unsigned long flags; /* MS_RDONLY, MS_NOSUID, etc. */
int refcount; /* number of open files on this mount */
const block_device_t* bdev; /* block device (NULL for virtual FS) */
+ vfs_superblock_t* sb; /* superblock (NULL for virtual FS) */
fs_node_t* root;
};
static struct vfs_mount g_mounts[32];
static int g_mount_count = 0;
+/* Filesystem type registry */
+#define FS_TYPE_MAX 8
+static vfs_fs_type_t g_fs_types[FS_TYPE_MAX];
+static int g_fs_type_count = 0;
+
static int path_is_mountpoint_prefix(const char* mp, const char* path) {
size_t mpl = strlen(mp);
if (mpl == 0) return 0;
int vfs_mount_nolock_full(const char* mountpoint, fs_node_t* root,
const char* fstype, const char* source,
- unsigned long flags, const block_device_t* bdev) {
+ unsigned long flags, const block_device_t* bdev,
+ vfs_superblock_t* sb) {
char mp[128];
normalize_mountpoint(mountpoint, mp, sizeof(mp));
/* Always update flags on remount (even if 0, caller explicitly set them) */
g_mounts[i].flags = flags;
g_mounts[i].bdev = bdev;
+ g_mounts[i].sb = sb;
return 0;
}
}
}
g_mounts[g_mount_count].flags = flags;
g_mounts[g_mount_count].bdev = bdev;
+ g_mounts[g_mount_count].sb = sb;
g_mount_count++;
return 0;
}
int vfs_mount_nolock(const char* mountpoint, fs_node_t* root) {
- return vfs_mount_nolock_full(mountpoint, root, NULL, NULL, 0, NULL);
+ return vfs_mount_nolock_full(mountpoint, root, NULL, NULL, 0, NULL, NULL);
}
int vfs_mount_full(const char* mountpoint, fs_node_t* root,
const char* fstype, const char* source,
unsigned long flags, const block_device_t* bdev) {
uintptr_t fl = spin_lock_irqsave(&g_vfs_lock);
- int ret = vfs_mount_nolock_full(mountpoint, root, fstype, source, flags, bdev);
+ int ret = vfs_mount_nolock_full(mountpoint, root, fstype, source, flags, bdev, NULL);
spin_unlock_irqrestore(&g_vfs_lock, fl);
return ret;
}
if (mflags & MS_RDONLY) return -EROFS;
return 0;
}
+
+/* ---- Filesystem type registry ---- */
+
+int vfs_fs_type_register(const vfs_fs_type_t* fst) {
+ if (!fst || !fst->name) return -EINVAL;
+ if (g_fs_type_count >= FS_TYPE_MAX) return -ENOSPC;
+
+ /* Check for duplicate name */
+ for (int i = 0; i < g_fs_type_count; i++) {
+ if (strcmp(g_fs_types[i].name, fst->name) == 0) {
+ /* Update existing entry */
+ g_fs_types[i] = *fst;
+ return 0;
+ }
+ }
+
+ g_fs_types[g_fs_type_count++] = *fst;
+ kprintf("[VFS] Registered filesystem type: %s\n", fst->name);
+ return 0;
+}
+
+const vfs_fs_type_t* vfs_fs_type_find(const char* name) {
+ if (!name) return NULL;
+ for (int i = 0; i < g_fs_type_count; i++) {
+ if (strcmp(g_fs_types[i].name, name) == 0)
+ return &g_fs_types[i];
+ }
+ return NULL;
+}
#include "hal/driver.h"
#include "fs.h"
+#include "fat.h"
+#include "ext2.h"
#include "initrd.h"
#include "overlayfs.h"
#include "tmpfs.h"
#include "pty.h"
/* diskfs and persistfs removed — use fat/ext2 for disk storage */
#include "procfs.h"
-#include "fat.h"
-#include "ext2.h"
#include "pci.h"
#include "e1000.h"
#include "net.h"
/* ---- Mount helper: used by fstab parser and kconsole 'mount' command ---- */
int init_mount_fs(const char* fstype, const block_device_t* bdev, uint32_t lba, const char* mountpoint, unsigned long flags) {
- fs_node_t* root = NULL;
-
- if (strcmp(fstype, "fat") == 0) {
- root = fat_mount(bdev, lba);
- } else if (strcmp(fstype, "ext2") == 0) {
- root = ext2_mount(bdev, lba);
- } else {
+ const vfs_fs_type_t* fst = vfs_fs_type_find(fstype);
+ if (!fst) {
kprintf("[MOUNT] Unknown filesystem type: %s\n", fstype);
return -EINVAL;
}
+ fs_node_t* root = fst->mount(bdev, lba);
if (!root) {
kprintf("[MOUNT] Failed to mount %s on %s at %s\n",
fstype, bdev ? bdev->name : "?",
}
int init_start(const struct boot_info* bi) {
+ /* Register filesystem types */
+ static vfs_fs_type_t fat_fs_type = {
+ .name = "fat",
+ .flags = FS_NEEDS_BDEV,
+ .mount = fat_mount
+ };
+ vfs_fs_type_register(&fat_fs_type);
+
+ static vfs_fs_type_t ext2_fs_type = {
+ .name = "ext2",
+ .flags = FS_NEEDS_BDEV,
+ .mount = ext2_mount
+ };
+ vfs_fs_type_register(&ext2_fs_type);
+
/* Parse kernel command line (Linux-like triaging) */
cmdline_parse(bi ? bi->cmdline : NULL);
uintptr_t vfs_fl = spin_lock_irqsave(&g_vfs_lock);
fs_node_t* old_root = fs_root;
fs_root = new_root;
- (void)vfs_mount_nolock_full("/", new_root, NULL, NULL, 0, NULL);
+ (void)vfs_mount_nolock_full("/", new_root, NULL, NULL, 0, NULL, NULL);
if (old_root) {
- (void)vfs_mount_nolock_full(kput, old_root, NULL, NULL, 0, NULL);
+ (void)vfs_mount_nolock_full(kput, old_root, NULL, NULL, 0, NULL, NULL);
}
spin_unlock_irqrestore(&g_vfs_lock, vfs_fl);
sc_ret(regs) = 0;