m³OS docs GitHub

Phase 38

Filesystem Enhancements

The filesystem supports symlinks, hard links, `umask`-backed creation defaults, the remaining Unix permission semantics needed for symlink-aware metadata and directory listing, a `/proc` filesystem for process introspection, and basic device nodes (`/dev/null`, `/dev/zero`, `/dev/urandom`, `/dev/full`). These are the filesystem primitives that Unix tools and build systems assume exist.

Complete

Learning goal

Understand the difference between hard links and symbolic links at the inode level.

Category

infrastructure

Components touched

Why this phase matters

The filesystem supports symlinks, hard links, umask-backed creation defaults, the remaining Unix permission semantics needed for symlink-aware metadata and directory listing, a /proc filesystem for process introspection, and basic device nodes (/dev/null, /dev/zero, /dev/urandom, /dev/full). These are the filesystem primitives that Unix tools and build systems assume exist.

How it works in m3OS

The roadmap entry defines the learning scope for this phase; a deeper implementation doc has not been matched yet.

How it builds on earlier phases

This phase builds on I/O Multiplexing and turns that foundation into Filesystem Enhancements.

Implementation outline

  • Implement symlinks in tmpfs (create, readlink, path resolution with follow).
  • Implement symlinks in ext2.
  • Add symlink loop detection (max 40 hops, return ELOOP).
  • Implement hard links in ext2 (link count management).
  • Complete the permission model for directory listing and symlink-aware metadata lookups.
  • Implement umask() syscall with per-process mask.
  • Implement /proc filesystem (start with /proc/<pid>/status and /proc/meminfo).
  • Add /dev/null, /dev/zero, /dev/urandom, /dev/full device nodes.
  • Implement statfs/fstatfs.
  • Write ln utility for creating links.
  • Test: ln -s /bin/sh0 /tmp/mysh && /tmp/mysh works via symlink.
  • Test: permission enforcement blocks unauthorized access.

Task progress snapshot

208 of 208 tracked tasks are complete.

Documentation targets

  • Documentation deliverables have not been listed yet.

Deferred follow-on work

  • Extended attributes (xattr)
  • Access Control Lists (ACLs)
  • inotify / fanotify (filesystem events)
  • sysfs
  • Full /proc (cgroups, net, sys subdirectories)
  • File locking (flock, lockf)
  • Overlay filesystems
  • Page cache for file data
  • mknod syscall for arbitrary device creation

Source materials

Important code

Code spotlight cards

Code spotlight

Add `Symlink` variant to `TmpfsNode`

kernel-core/src/fs/tmpfs.rs L40-L44

require a third variant that stores the target path string instead of file data. Why it matters: tmpfs currently has File and Dir variants only. Symlinks. Focus on `Symlink` and `TmpfsNode` in `kernel-core/src/fs/tmpfs.rs` while you trace the snippet.

enum TmpfsNode {
    File(FileData),
    Dir(DirData),
    Symlink(SymlinkData),
}

Code spotlight

Implement ext2 symlink creation and reading

kernel/src/fs/ext2.rs L15-L26

pointers (up to 60 bytes) and longer targets in a data block. Both paths must work. Why it matters: ext2 stores short symlink targets inline in the inode's block. Focus on `Ext2Volume::create_symlink` and `Ext2Volume::read_symlink` in `kernel/src/fs/ext2.rs` while you trace the snippet.

    EXT2_DIND_BLOCK, EXT2_FT_DIR, EXT2_FT_REG_FILE, EXT2_FT_SYMLINK, EXT2_IND_BLOCK,
    EXT2_NDIR_BLOCKS, EXT2_ROOT_INO, Ext2BlockGroupDescriptor, Ext2DirEntry, Ext2Error, Ext2Inode,
    Ext2Superblock, S_IFDIR, S_IFLNK, S_IFREG,
};
use spin::Mutex;

// ---------------------------------------------------------------------------
// Ext2Volume (P28-T019)
// ---------------------------------------------------------------------------

/// A mounted ext2 volume backed by virtio-blk sectors.
pub struct Ext2Volume {

Code spotlight

Implement `sys_symlink()` and `sys_symlinkat()` syscalls

kernel/src/arch/x86_64/syscall.rs L7003-L7005

They must route through resolve_fs_target() to the correct filesystem backend. Why it matters: These are the userspace entry points for symlink creation. Focus on `sys_symlink` and `sys_symlinkat` in `kernel/src/arch/x86_64/syscall.rs` while you trace the snippet.

fn sys_symlink(target_ptr: u64, linkpath_ptr: u64) -> u64 {
    sys_symlinkat(target_ptr, AT_FDCWD, linkpath_ptr)
}

Key files

  • kernel/src/fs/procfs.rs — A new kernel/src/fs/procfs.rs module synthesizes file content on read from kernel

How real OSes differ

  • **Dentry cache** for fast path lookup with negative caching.
  • **Inode cache** for recently accessed inodes.
  • **Page cache** for file data (unified with VM).
  • **Overlay filesystems** (overlayfs, unionfs).
  • **Extended attributes** (xattr) for SELinux labels, ACLs, capabilities.
  • **Full procfs** with hundreds of entries per process.
  • **sysfs** for device/driver introspection.
  • **devtmpfs** with udev rules for dynamic device creation.
  • **inotify/fanotify** for filesystem event monitoring.

Success criteria

  • `symlink("/bin/sh0", "/tmp/mysh")` creates a working symlink.
  • `readlink("/tmp/mysh")` returns `"/bin/sh0"`.
  • Symlink chain resolution works (A→B→C) with loop detection.
  • Hard links share an inode: modify via one path, see changes via the other.
  • `unlink()` of a hard-linked file only removes it when link count hits 0.
  • `getdents64()` on a directory without read permission returns `EACCES`.
  • `umask(022)` causes `mkdir()` to create directories with mode 0755.
  • `cat /proc/self/status` shows the process's own info.
  • `readlink /proc/self/exe` returns the current process executable path.
  • `cat /proc/meminfo` shows memory statistics.
  • `cat /dev/urandom | hexdump | head` produces random output.
  • `echo test > /dev/null` succeeds silently.
  • `dd if=/dev/zero bs=4096 count=1` produces 4096 zero bytes.
  • All existing tests pass without regression.

Related phases

Keep exploring the roadmap