-
Notifications
You must be signed in to change notification settings - Fork 1
Open
Labels
enhancementNew feature or requestNew feature or requestkernelKernel-level implementationKernel-level implementation
Description
Goal
Implement VFS mount point infrastructure to support mounting multiple filesystems at different paths in the directory tree (e.g., FAT32 at /boot, ext2 at /).
Context
Currently, meniOS VFS supports only a single root filesystem. To support the dual-partition layout (#228) and future multi-filesystem scenarios, we need:
- Mount point data structures
- Path lookup across mount boundaries
- Mount/unmount operations
- /proc/mounts support
This is a prerequisite for #228 (dual partition mount).
Dependencies
Required (Blocking)
- Implement VFS (Virtual File System) layer #65 - VFS layer ✅ COMPLETE
Blocks (Downstream)
- Mount FAT32 boot drive as /boot and ext2 as root / #228 - Dual partition mount (needs mount point support)
- Future: NFS, devfs, tmpfs, procfs mounting
Priority
Medium - Required for dual-partition boot, enables proper Linux-style mounts
Justification
- Foundation for multi-filesystem support
- Required for Mount FAT32 boot drive as /boot and ext2 as root / #228 (dual partition mount)
- Not blocking Doom or GCC milestones immediately
- Single filesystem works for current needs
- Standard Linux VFS feature
Implementation Scope
Phase 1: Mount Point Data Structures (2-3 days)
// Mount point structure
struct mount {
char *path; // Mount path (e.g., "/boot")
struct superblock *sb; // Mounted filesystem superblock
struct dentry *mount_point; // Dentry where mounted
struct dentry *root; // Root dentry of mounted fs
struct mount *parent; // Parent mount (for umount ordering)
struct list_head children; // Child mounts
struct list_head list; // Global mount list
uint32_t flags; // Mount flags (ro, noexec, etc.)
};
// Global mount table
struct list_head mount_table;
struct spinlock mount_lock;
struct mount *root_mount; // Root filesystem mountPhase 2: Mount Operations (3-4 days)
// Mount API
int vfs_mount(struct superblock *sb, const char *path, uint32_t flags);
int vfs_umount(const char *path);
struct mount *vfs_find_mount(const char *path);
bool vfs_is_mount_point(struct dentry *dentry);
// Mount flags
#define MS_RDONLY 0x0001 // Read-only
#define MS_NOSUID 0x0002 // Ignore suid/sgid
#define MS_NODEV 0x0004 // Disallow device access
#define MS_NOEXEC 0x0008 // Disallow program execution
#define MS_SYNCHRONOUS 0x0010 // Sync writes
#define MS_REMOUNT 0x0020 // Remount existing mount
#define MS_BIND 0x1000 // Bind mountPhase 3: Path Lookup with Mounts (4-5 days)
// Enhanced path lookup
struct dentry *vfs_path_lookup_with_mounts(const char *path) {
struct dentry *current = root_dentry;
struct mount *current_mount = root_mount;
// Parse path components
const char *next = path;
while (*next) {
// Skip leading slashes
while (*next == '/') next++;
// Get next component
const char *component = next;
while (*next && *next != '/') next++;
size_t len = next - component;
if (len == 0) break;
// Lookup component in current directory
struct dentry *child = dentry_lookup(current, component, len);
if (!child) {
return ERR_PTR(-ENOENT);
}
// Check if child is a mount point
struct mount *mount = vfs_find_mount_at_dentry(child);
if (mount) {
// Cross mount boundary
current = mount->root;
current_mount = mount;
} else {
current = child;
}
}
return current;
}Phase 4: Mount Syscalls (2-3 days)
// System calls
long sys_mount(const char *source, const char *target,
const char *filesystemtype, unsigned long mountflags,
const void *data);
long sys_umount(const char *target);
long sys_umount2(const char *target, int flags);
// umount2 flags
#define MNT_FORCE 0x0001 // Force unmount even if busy
#define MNT_DETACH 0x0002 // Lazy unmount
#define MNT_EXPIRE 0x0004 // Mark for expirationPhase 5: /proc/mounts (1-2 days)
// Expose mount table via /proc/mounts
// Format: device mountpoint fstype options
// Example:
// /dev/sda1 /boot fat32 rw 0 0
// /dev/sda2 / ext2 rw 0 0
int proc_mounts_show(struct seq_file *m, void *v) {
struct mount *mount;
list_for_each_entry(mount, &mount_table, list) {
seq_printf(m, "%s %s %s %s 0 0\n",
mount->sb->s_dev_name,
mount->path,
mount->sb->s_type->name,
mount_flags_to_string(mount->flags));
}
return 0;
}Definition of Done
- Mount point data structures implemented
- Mount/umount operations working
- Path lookup crosses mount boundaries correctly
- Multiple filesystems can be mounted simultaneously
- Mount syscalls implemented
- /proc/mounts shows mounted filesystems
- Proper locking and synchronization
- Unit tests for mount operations
- Integration tests with FAT32 and ext2
- Documentation
Implementation Details
Mount Point Detection
// Check if dentry is a mount point
bool vfs_is_mount_point(struct dentry *dentry) {
struct mount *mount;
spin_lock(&mount_lock);
list_for_each_entry(mount, &mount_table, list) {
if (mount->mount_point == dentry) {
spin_unlock(&mount_lock);
return true;
}
}
spin_unlock(&mount_lock);
return false;
}Mount Operation
int vfs_mount(struct superblock *sb, const char *path, uint32_t flags) {
// Lookup mount point
struct dentry *mount_point = vfs_path_lookup(path);
if (IS_ERR(mount_point)) {
return PTR_ERR(mount_point);
}
// Verify mount point is a directory
if (!S_ISDIR(mount_point->d_inode->i_mode)) {
return -ENOTDIR;
}
// Check if already mounted
if (vfs_is_mount_point(mount_point)) {
return -EBUSY;
}
// Create mount structure
struct mount *mount = kmalloc(sizeof(struct mount));
mount->path = kstrdup(path);
mount->sb = sb;
mount->mount_point = mount_point;
mount->root = sb->s_root;
mount->flags = flags;
// Add to mount table
spin_lock(&mount_lock);
list_add(&mount->list, &mount_table);
mount_point->d_flags |= DCACHE_MOUNTED;
spin_unlock(&mount_lock);
kprintf("Mounted %s at %s\n", sb->s_type->name, path);
return 0;
}Unmount Operation
int vfs_umount(const char *path) {
struct mount *mount;
// Find mount by path
spin_lock(&mount_lock);
list_for_each_entry(mount, &mount_table, list) {
if (strcmp(mount->path, path) == 0) {
// Found it
goto found;
}
}
spin_unlock(&mount_lock);
return -EINVAL;
found:
// Check if busy (has children mounted)
if (!list_empty(&mount->children)) {
spin_unlock(&mount_lock);
return -EBUSY;
}
// Remove from mount table
list_del(&mount->list);
mount->mount_point->d_flags &= ~DCACHE_MOUNTED;
spin_unlock(&mount_lock);
// Sync and release filesystem
sb_sync(mount->sb);
sb_put(mount->sb);
kfree(mount->path);
kfree(mount);
kprintf("Unmounted %s\n", path);
return 0;
}Testing Strategy
Unit Tests
- Mount filesystem at /mnt
- Mount filesystem at /boot
- Mount multiple filesystems
- Unmount filesystem
- Verify mount point detection
- Test mount over existing mount (should fail)
- Test umount of busy mount (should fail)
Integration Tests
// Test dual mount
void test_dual_mount(void) {
// Mount FAT32 at /boot
struct superblock *fat32_sb = fat32_mount(boot_device);
assert(vfs_mount(fat32_sb, "/boot", MS_RDONLY) == 0);
// Mount ext2 at /
struct superblock *ext2_sb = ext2_mount(root_device);
assert(vfs_mount(ext2_sb, "/", 0) == 0);
// Verify path lookup crosses mounts
struct dentry *boot_file = vfs_path_lookup("/boot/kernel.elf");
assert(boot_file != NULL);
assert(boot_file->d_sb == fat32_sb);
struct dentry *root_file = vfs_path_lookup("/bin/mosh");
assert(root_file != NULL);
assert(root_file->d_sb == ext2_sb);
// Unmount
assert(vfs_umount("/boot") == 0);
assert(vfs_umount("/") == 0);
}Use Cases
Dual Partition Boot
void init_filesystems(void) {
// Mount boot partition (FAT32)
struct superblock *boot_sb = fat32_mount(boot_partition);
vfs_mount(boot_sb, "/boot", MS_RDONLY);
// Mount root partition (ext2)
struct superblock *root_sb = ext2_mount(root_partition);
vfs_mount(root_sb, "/", 0);
// Mount special filesystems
vfs_mount(devfs_mount(), "/dev", 0);
vfs_mount(tmpfs_mount(), "/tmp", 0);
vfs_mount(procfs_mount(), "/proc", MS_RDONLY);
}Checking Mounts
$ cat /proc/mounts
/dev/sda1 /boot fat32 ro 0 0
/dev/sda2 / ext2 rw 0 0
devfs /dev devfs rw 0 0
tmpfs /tmp tmpfs rw 0 0
procfs /proc procfs ro 0 0Files to Create/Modify
- src/kernel/fs/mount.c - Mount point management
- src/kernel/fs/vfs.c - Update path lookup for mounts
- src/kernel/syscalls/mount.c - Mount/umount syscalls
- src/kernel/proc/mounts.c - /proc/mounts implementation
- include/kernel/fs/mount.h - Mount API
- test/test_mount.c - Mount tests
Deliverables
- Mount point infrastructure
- Mount/umount operations
- Enhanced path lookup
- Mount syscalls
- /proc/mounts support
- Test suite
- Documentation
Performance Goals
- Mount/umount operations < 1ms
- Path lookup overhead minimal (1-2 extra checks)
- Minimal memory per mount point (~100 bytes)
Error Handling
- Prevent mount over non-directory
- Prevent mount over existing mount
- Prevent umount of busy filesystem
- Proper cleanup on mount failure
- Handle umount during active access
Security Considerations
- Check permissions on mount point
- Validate mount flags
- Prevent privilege escalation via mount
- Proper ownership of mounted files
Related Issues
- Mount FAT32 boot drive as /boot and ext2 as root / #228 - Dual partition mount (blocked by this)
- Implement VFS (Virtual File System) layer #65 - VFS layer ✅ COMPLETE
- Future: devfs, tmpfs, procfs mounting
Current Status
Ready to Start - VFS layer complete, can begin implementation
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or requestkernelKernel-level implementationKernel-level implementation