]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commitdiff
vfs: change mount API to return vfs_mount_result_t {root, sb} (P2.1)
authorTulio A M Mendes <[email protected]>
Mon, 25 May 2026 20:58:12 +0000 (17:58 -0300)
committerTulio A M Mendes <[email protected]>
Wed, 3 Jun 2026 04:02:35 +0000 (01:02 -0300)
- 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
include/fat.h
include/fs.h
src/kernel/ext2.c
src/kernel/fat.c
src/kernel/fs.c
src/kernel/init.c
src/kernel/syscall.c

index bda798c07afec773acacb69b6fac404755464f0d..c878fac75c7d0256fd90ca152cbabb9927ba809b 100644 (file)
@@ -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);
index a580e75ce2af7807899ec5c531c8239c3821e765..eb5f886ed122a2955f8dec2ebc9c9439eac5f863 100644 (file)
@@ -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);
index deb17b65b97d7d6dee564164dab810dc0e2fae14..f299339c9473c63ae8f819d53b119b4e66367a75 100644 (file)
 #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.
index 644810ba59bc13d45aa22db69f5888617b809f8f..02f60c439ae3a536731ba0cfa71d35540ad28263 100644 (file)
@@ -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) {
index 60875654e093d586216c66b1e4484fa70e7bba62..6e3839bd8fa036c75fe7fbbc381181d2397cd408 100644 (file)
@@ -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) {
index 59ab9b0f1fecde069d5976332188591868cf3d53..b16b9876cf50c439adbf7029c2d0963e516b7187 100644 (file)
@@ -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) {
index e7ac8230de46625d38f5b41743f92c682f959ba7..e2953d25eb85e81ff66fb49c52f4686dc99681bc 100644 (file)
@@ -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
index 2a228a4269f656cf84b849ece68e62d0fc05cfd5..5d37e9caed8696fb66ef0ba737ccaaf4afe28c5e 100644 (file)
@@ -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;
         }