From c04646b0d084e642cb053f4c33d9cac761d05439 Mon Sep 17 00:00:00 2001 From: Tulio A M Mendes Date: Mon, 25 May 2026 17:58:12 -0300 Subject: [PATCH] vfs: change mount API to return vfs_mount_result_t {root, sb} (P2.1) - Add vfs_mount_result_t structure with root and superblock - Update vfs_fs_type_t.mount() to return vfs_mount_result_t - Update fat_mount() and ext2_mount() to build and return superblock - Update init_mount_fs() to handle vfs_mount_result_t and set fstype in sb - Update vfs_mount_full() to accept sb parameter - Update all vfs_mount_full() callers to pass sb (NULL for virtual FS) --- include/ext2.h | 4 ++-- include/fat.h | 4 ++-- include/fs.h | 26 +++++++++++++++++--------- src/kernel/ext2.c | 42 +++++++++++++++++++++++++++++++----------- src/kernel/fat.c | 32 +++++++++++++++++++++++++------- src/kernel/fs.c | 7 ++++--- src/kernel/init.c | 19 ++++++++++++------- src/kernel/syscall.c | 8 ++++---- 8 files changed, 97 insertions(+), 45 deletions(-) diff --git a/include/ext2.h b/include/ext2.h index bda798c0..c878fac7 100644 --- a/include/ext2.h +++ b/include/ext2.h @@ -35,8 +35,8 @@ struct ext2_mount { }; /* Mount an ext2 filesystem on the given block device starting at the given - * LBA offset. Returns a VFS root node or NULL on failure. */ -fs_node_t* ext2_mount(const block_device_t* bdev, uint32_t partition_lba); + * LBA offset. Returns a mount result with root node and superblock, or {NULL, NULL} on failure. */ +vfs_mount_result_t ext2_mount(const block_device_t* bdev, uint32_t partition_lba); /* Unmount an ext2 filesystem and free its resources */ void ext2_umount(struct ext2_mount* em); diff --git a/include/fat.h b/include/fat.h index a580e75c..eb5f886e 100644 --- a/include/fat.h +++ b/include/fat.h @@ -42,8 +42,8 @@ struct fat_mount { /* Mount a FAT12/16/32 filesystem on the given block device starting at * the given LBA offset. Auto-detects FAT type from BPB. - * Returns a VFS root node or NULL on failure. */ -fs_node_t* fat_mount(const block_device_t* bdev, uint32_t partition_lba); + * Returns a mount result with root node and superblock, or {NULL, NULL} on failure. */ +vfs_mount_result_t fat_mount(const block_device_t* bdev, uint32_t partition_lba); /* Unmount a FAT filesystem and free its resources */ void fat_umount(struct fat_mount* fm); diff --git a/include/fs.h b/include/fs.h index deb17b65..f299339c 100644 --- a/include/fs.h +++ b/include/fs.h @@ -34,22 +34,29 @@ #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; +struct vfs_fs_type; /* forward declaration */ /* VFS superblock — per-mount filesystem metadata */ typedef struct vfs_superblock { - const vfs_fs_type_t* fstype; /* Filesystem type */ + const struct vfs_fs_type* 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; +/* Mount result structure - returned by filesystem mount functions */ +typedef struct vfs_mount_result { + struct fs_node* root; /* VFS root node */ + vfs_superblock_t* sb; /* Superblock (NULL for virtual FS) */ +} vfs_mount_result_t; + +/* Filesystem type structure */ +typedef struct vfs_fs_type { + const char* name; /* e.g. "fat", "ext2" */ + uint32_t flags; /* FS_NEEDS_BDEV, etc. */ + vfs_mount_result_t (*mount)(const block_device_t* bdev, uint32_t lba); /* Mount function */ +} vfs_fs_type_t; + /* poll() event flags — shared between kernel VFS and syscall layer */ #define VFS_POLL_IN 0x0001 #define VFS_POLL_OUT 0x0004 @@ -136,7 +143,8 @@ int vfs_link(const char* old_path, const char* new_path); int vfs_mount(const char* mountpoint, fs_node_t* root); 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); + unsigned long flags, const block_device_t* bdev, + vfs_superblock_t* sb); int vfs_umount(const char* mountpoint); /* _nolock variants — caller must already hold g_vfs_lock. diff --git a/src/kernel/ext2.c b/src/kernel/ext2.c index 644810ba..02f60c43 100644 --- a/src/kernel/ext2.c +++ b/src/kernel/ext2.c @@ -8,6 +8,7 @@ */ #include "ext2.h" +#include "fs.h" #include "blockdev.h" #include "heap.h" #include "utils.h" @@ -1426,17 +1427,19 @@ static int ext2_link_impl(struct fs_node* dir, const char* name, struct fs_node* /* ---- Mount ---- */ -fs_node_t* ext2_mount(const block_device_t* bdev, uint32_t partition_lba) { +vfs_mount_result_t ext2_mount(const block_device_t* bdev, uint32_t partition_lba) { + vfs_mount_result_t result = {NULL, NULL}; + if (!bdev) { kprintf("[EXT2] No block device provided\n"); - return NULL; + return result; } /* Allocate mount structure */ struct ext2_mount* em = (struct ext2_mount*)kmalloc(sizeof(struct ext2_mount)); if (!em) { kprintf("[EXT2] Failed to allocate mount structure\n"); - return NULL; + return result; } memset(em, 0, sizeof(*em)); @@ -1448,20 +1451,20 @@ fs_node_t* ext2_mount(const block_device_t* bdev, uint32_t partition_lba) { if (ext2_read_superblock(em, &sb) < 0) { kprintf("[EXT2] Failed to read superblock\n"); kfree(em); - return NULL; + return result; } if (sb.s_magic != EXT2_SUPER_MAGIC) { kprintf("[EXT2] Invalid magic: 0x%x\n", sb.s_magic); kfree(em); - return NULL; + return result; } em->block_size = 1024U << sb.s_log_block_size; if (em->block_size > 4096) { kprintf("[EXT2] Unsupported block size %u\n", em->block_size); kfree(em); - return NULL; + return result; } em->sectors_per_block = em->block_size / EXT2_SECTOR_SIZE; em->inodes_per_group = sb.s_inodes_per_group; @@ -1486,7 +1489,7 @@ fs_node_t* ext2_mount(const block_device_t* bdev, uint32_t partition_lba) { if (!em->gdt) { kprintf("[EXT2] Failed to allocate GDT (%u bytes)\n", gdt_bytes); kfree(em); - return NULL; + return result; } memset(em->gdt, 0, gdt_bytes); @@ -1498,7 +1501,7 @@ fs_node_t* ext2_mount(const block_device_t* bdev, uint32_t partition_lba) { kprintf("[EXT2] Failed to read GDT block %u\n", gdt_block + b); kfree(em->gdt); kfree(em); - return NULL; + return result; } uint32_t to_copy = em->block_size; if (to_copy > gdt_bytes - b * em->block_size) @@ -1512,7 +1515,7 @@ fs_node_t* ext2_mount(const block_device_t* bdev, uint32_t partition_lba) { kprintf("[EXT2] Failed to read root inode\n"); kfree(em->gdt); kfree(em); - return NULL; + return result; } /* Build root node */ @@ -1521,7 +1524,7 @@ fs_node_t* ext2_mount(const block_device_t* bdev, uint32_t partition_lba) { kprintf("[EXT2] Failed to allocate root node\n"); kfree(em->gdt); kfree(em); - return NULL; + return result; } memset(root, 0, sizeof(*root)); root->mount = em; @@ -1536,11 +1539,28 @@ fs_node_t* ext2_mount(const block_device_t* bdev, uint32_t partition_lba) { root->vfs.f_ops = &ext2_dir_fops; root->vfs.i_ops = &ext2_dir_iops; + /* Build superblock */ + vfs_superblock_t* vfs_sb = (vfs_superblock_t*)kmalloc(sizeof(vfs_superblock_t)); + if (!vfs_sb) { + kprintf("[EXT2] Failed to allocate superblock\n"); + kfree(root); + kfree(em->gdt); + kfree(em); + return result; + } + memset(vfs_sb, 0, sizeof(*vfs_sb)); + vfs_sb->bdev = bdev; + vfs_sb->lba = partition_lba; + vfs_sb->private_data = em; + /* fstype will be set by caller */ + kprintf("[EXT2] Mounted at LBA %u (%u blocks, %u inodes, %u groups, %uB/block)\n", partition_lba, em->total_blocks, em->total_inodes, em->num_groups, em->block_size); - return &root->vfs; + result.root = &root->vfs; + result.sb = vfs_sb; + return result; } void ext2_umount(struct ext2_mount* em) { diff --git a/src/kernel/fat.c b/src/kernel/fat.c index 60875654..6e3839bd 100644 --- a/src/kernel/fat.c +++ b/src/kernel/fat.c @@ -8,6 +8,7 @@ */ #include "fat.h" +#include "fs.h" #include "blockdev.h" #include "heap.h" #include "utils.h" @@ -1134,17 +1135,19 @@ static int fat_truncate_impl(struct fs_node* node, uint32_t length) { /* ---- Mount ---- */ -fs_node_t* fat_mount(const block_device_t* bdev, uint32_t partition_lba) { +vfs_mount_result_t fat_mount(const block_device_t* bdev, uint32_t partition_lba) { + vfs_mount_result_t result = {NULL, NULL}; + if (!bdev) { kprintf("[FAT] No block device provided\n"); - return NULL; + return result; } /* Allocate mount structure */ struct fat_mount* fm = (struct fat_mount*)kmalloc(sizeof(struct fat_mount)); if (!fm) { kprintf("[FAT] Failed to allocate mount structure\n"); - return NULL; + return result; } memset(fm, 0, sizeof(*fm)); @@ -1155,7 +1158,7 @@ fs_node_t* fat_mount(const block_device_t* bdev, uint32_t partition_lba) { if (fat_read_sector(fm, partition_lba, boot_sec) < 0) { kprintf("[FAT] Failed to read BPB at LBA %u\n", partition_lba); kfree(fm); - return NULL; + return result; } struct fat_bpb* bpb = (struct fat_bpb*)boot_sec; @@ -1163,12 +1166,12 @@ fs_node_t* fat_mount(const block_device_t* bdev, uint32_t partition_lba) { if (bpb->bytes_per_sector != 512) { kprintf("[FAT] Unsupported sector size %u\n", bpb->bytes_per_sector); kfree(fm); - return NULL; + return result; } if (bpb->num_fats == 0 || bpb->sectors_per_cluster == 0) { kprintf("[FAT] Invalid BPB\n"); kfree(fm); - return NULL; + return result; } fm->part_lba = partition_lba; @@ -1218,10 +1221,25 @@ fs_node_t* fat_mount(const block_device_t* bdev, uint32_t partition_lba) { g_fat_root.vfs.f_ops = &fat_dir_fops; g_fat_root.vfs.i_ops = &fat_dir_iops; + /* Build superblock */ + vfs_superblock_t* sb = (vfs_superblock_t*)kmalloc(sizeof(vfs_superblock_t)); + if (!sb) { + kprintf("[FAT] Failed to allocate superblock\n"); + kfree(fm); + return result; + } + memset(sb, 0, sizeof(*sb)); + sb->bdev = bdev; + sb->lba = partition_lba; + sb->private_data = fm; + /* fstype will be set by caller */ + kprintf("[FAT] Mounted FAT%u at LBA %u (%u clusters)\n", (unsigned)fm->type, partition_lba, fm->total_clusters); - return &g_fat_root.vfs; + result.root = &g_fat_root.vfs; + result.sb = sb; + return result; } void fat_umount(struct fat_mount* fm) { diff --git a/src/kernel/fs.c b/src/kernel/fs.c index 59ab9b0f..b16b9876 100644 --- a/src/kernel/fs.c +++ b/src/kernel/fs.c @@ -153,15 +153,16 @@ int vfs_mount_nolock(const char* mountpoint, fs_node_t* root) { 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) { + unsigned long flags, const block_device_t* bdev, + vfs_superblock_t* sb) { uintptr_t fl = spin_lock_irqsave(&g_vfs_lock); - int ret = vfs_mount_nolock_full(mountpoint, root, fstype, source, flags, bdev, NULL); + int ret = vfs_mount_nolock_full(mountpoint, root, fstype, source, flags, bdev, sb); spin_unlock_irqrestore(&g_vfs_lock, fl); return ret; } int vfs_mount(const char* mountpoint, fs_node_t* root) { - return vfs_mount_full(mountpoint, root, NULL, NULL, 0, NULL); + return vfs_mount_full(mountpoint, root, NULL, NULL, 0, NULL, NULL); } int vfs_umount_nolock(const char* mountpoint) { diff --git a/src/kernel/init.c b/src/kernel/init.c index e7ac8230..e2953d25 100644 --- a/src/kernel/init.c +++ b/src/kernel/init.c @@ -51,14 +51,19 @@ int init_mount_fs(const char* fstype, const block_device_t* bdev, uint32_t lba, return -EINVAL; } - fs_node_t* root = fst->mount(bdev, lba); - if (!root) { + vfs_mount_result_t mres = fst->mount(bdev, lba); + if (!mres.root) { kprintf("[MOUNT] Failed to mount %s on %s at %s\n", fstype, bdev ? bdev->name : "?", mountpoint); return -ENODEV; } + /* Set fstype pointer in superblock */ + if (mres.sb) { + mres.sb->fstype = fst; + } + /* Claim the block device */ if (bdev) { blockdev_claim(bdev); @@ -76,7 +81,7 @@ int init_mount_fs(const char* fstype, const block_device_t* bdev, uint32_t lba, *dp = '\0'; } - int rc = vfs_mount_full(mountpoint, root, fstype, devname, flags, bdev); + int rc = vfs_mount_full(mountpoint, mres.root, fstype, devname, flags, bdev, mres.sb); if (rc < 0) { kprintf("[MOUNT] Failed to register mount at %s (err=%d)\n", mountpoint, rc); if (bdev) { @@ -142,7 +147,7 @@ int init_start(const struct boot_info* bi) { if (upper) { fs_node_t* ovl = overlayfs_create_root(fs_root, upper); if (ovl) { - (void)vfs_mount_full("/", ovl, "overlayfs", "initrd", 0, NULL); + (void)vfs_mount_full("/", ovl, "overlayfs", "initrd", 0, NULL, NULL); vfs_set_initrd_root(ovl); } } @@ -164,7 +169,7 @@ int init_start(const struct boot_info* bi) { fs_node_t* tmp = tmpfs_create_root(); if (tmp) { - (void)vfs_mount_full("/tmp", tmp, "tmpfs", "none", 0, NULL); + (void)vfs_mount_full("/tmp", tmp, "tmpfs", "none", 0, NULL, NULL); } /* Register hardware drivers with HAL and init in priority order */ @@ -191,7 +196,7 @@ int init_start(const struct boot_info* bi) { * existing entry so this is a harmless overlap. */ fs_node_t* dev = devfs_create_root(); if (dev) { - (void)vfs_mount_full("/dev", dev, "devfs", "none", 0, NULL); + (void)vfs_mount_full("/dev", dev, "devfs", "none", 0, NULL, NULL); } vbe_register_devfs(); @@ -199,7 +204,7 @@ int init_start(const struct boot_info* bi) { fs_node_t* proc = procfs_create_root(); if (proc) { - (void)vfs_mount_full("/proc", proc, "procfs", "none", 0, NULL); + (void)vfs_mount_full("/proc", proc, "procfs", "none", 0, NULL, NULL); } /* Initialize ATA subsystem — probe all 4 drives diff --git a/src/kernel/syscall.c b/src/kernel/syscall.c index 2a228a42..5d37e9ca 100644 --- a/src/kernel/syscall.c +++ b/src/kernel/syscall.c @@ -5170,7 +5170,7 @@ static void extended_syscall_dispatch(struct registers* regs, uint32_t syscall_n /* MS_REMOUNT: update flags on existing mount */ if (mount_flags & MS_REMOUNT) { - sc_ret(regs) = (uint32_t)vfs_mount_full(kmp, NULL, NULL, NULL, mount_flags & ~MS_REMOUNT, NULL); + sc_ret(regs) = (uint32_t)vfs_mount_full(kmp, NULL, NULL, NULL, mount_flags & ~MS_REMOUNT, NULL, NULL); return; } @@ -5183,21 +5183,21 @@ static void extended_syscall_dispatch(struct registers* regs, uint32_t syscall_n if (strcmp(ktype, "tmpfs") == 0) { fs_node_t* tmp = tmpfs_create_root(); if (!tmp) { sc_ret(regs) = (uint32_t)-ENOMEM; return; } - sc_ret(regs) = (uint32_t)vfs_mount_full(kmp, tmp, "tmpfs", kdev, mount_flags, NULL); + sc_ret(regs) = (uint32_t)vfs_mount_full(kmp, tmp, "tmpfs", kdev, mount_flags, NULL, NULL); return; } if (strcmp(ktype, "devfs") == 0) { extern fs_node_t* devfs_create_root(void); fs_node_t* dev = devfs_create_root(); if (!dev) { sc_ret(regs) = (uint32_t)-ENOMEM; return; } - sc_ret(regs) = (uint32_t)vfs_mount_full(kmp, dev, "devfs", kdev, mount_flags, NULL); + sc_ret(regs) = (uint32_t)vfs_mount_full(kmp, dev, "devfs", kdev, mount_flags, NULL, NULL); return; } if (strcmp(ktype, "procfs") == 0) { extern fs_node_t* procfs_create_root(void); fs_node_t* proc = procfs_create_root(); if (!proc) { sc_ret(regs) = (uint32_t)-ENOMEM; return; } - sc_ret(regs) = (uint32_t)vfs_mount_full(kmp, proc, "procfs", kdev, mount_flags, NULL); + sc_ret(regs) = (uint32_t)vfs_mount_full(kmp, proc, "procfs", kdev, mount_flags, NULL, NULL); return; } -- 2.43.0