Skip to main content

Overview

Aurora OS implements a Unix-like Virtual File System (VFS) that provides a unified interface for multiple filesystem types. The VFS supports mounting filesystems, path resolution, and standard file operations.
VFS is mounted at boot with tmpfs for / and /tmp. ELF binaries are loaded through VFS.

Architecture

Source: kernel/src/fs/vfs.c
  • Mount Points: Up to 8 simultaneous mounts
  • Filesystem Types: tmpfs, ext2 (stub), FAT (stub)
  • Path Resolution: Recursive component-by-component lookup
  • Operations: read, write, create, unlink, mkdir, readdir, stat

Data Structures

vfs_node

Represents a file, directory, or symlink in the VFS.
struct vfs_node {
    char name[256];           // Filename (VFS_NAME_MAX + 1)
    vfs_type_t type;          // VFS_FILE, VFS_DIR, VFS_SYMLINK
    uint64_t size;            // File size in bytes
    uint64_t inode;           // Filesystem-specific inode number
    void *fs_priv;            // Filesystem private data
    struct vfs_ops *ops;      // Function pointer table
};
Source: kernel/src/fs/vfs.h:27-34

vfs_type_t

Node type enumeration.
VFS_FILE
enum
Regular file.
VFS_DIR
enum
Directory.
Symbolic link (not yet implemented).
Source: kernel/src/fs/vfs.h:17

vfs_ops

Filesystem operation function pointers.
struct vfs_ops {
    int (*read)(struct vfs_node *node, uint64_t offset, 
                void *buf, size_t count);
    int (*write)(struct vfs_node *node, uint64_t offset, 
                 const void *buf, size_t count);
    int (*open)(struct vfs_node *node);
    int (*close)(struct vfs_node *node);
    struct vfs_node *(*readdir)(struct vfs_node *dir, uint32_t index);
    struct vfs_node *(*lookup)(struct vfs_node *dir, const char *name);
    int (*create)(struct vfs_node *dir, const char *name, vfs_type_t type);
    int (*unlink)(struct vfs_node *dir, const char *name);
    int (*mkdir)(struct vfs_node *dir, const char *name);
    int (*stat)(struct vfs_node *node, struct vfs_stat *st);
};
Source: kernel/src/fs/vfs.h:36-47

vfs_stat

File metadata (similar to POSIX stat).
struct vfs_stat {
    uint64_t inode;
    uint64_t size;
    vfs_type_t type;
    uint32_t mode;      // Permission bits (e.g., 0755)
    uint32_t nlink;     // Hard link count
};
Source: kernel/src/fs/vfs.h:19-25

vfs_mount

Mount table entry.
struct vfs_mount {
    const char *mountpoint;     // Path (e.g., "/", "/tmp")
    struct vfs_node *root;      // Root node of filesystem
    const char *fs_type;        // Filesystem type ("tmpfs", "ext2")
};
Limit: VFS_MAX_MOUNTS = 8 Source: kernel/src/fs/vfs.h:49-53

Core Functions

vfs_mount

Mount a filesystem at a specified path.
int vfs_mount(const char *mountpoint, struct vfs_node *root, 
              const char *fs_type);
mountpoint
const char*
Mount path (e.g., /, /mnt/usb).
root
struct vfs_node*
Root directory node of the filesystem.
fs_type
const char*
Filesystem type string (“tmpfs”, “ext2”, “fat32”).
return
int
Returns 0 on success, -1 if mount table is full.
Example:
struct vfs_node *tmpfs_root = tmpfs_create_root();
vfs_mount("/", tmpfs_root, "tmpfs");
vfs_mount("/tmp", tmpfs_create_root(), "tmpfs");
Source: kernel/src/fs/vfs.c:20-27

vfs_resolve

Resolve an absolute path to a VFS node.
struct vfs_node *vfs_resolve(const char *path);
path
const char*
Absolute path (must start with /).
return
struct vfs_node*
Pointer to resolved node, or NULL if path not found.
Algorithm:
  1. Find longest matching mount point
  2. Start at mount’s root node
  3. Split remaining path into components (separated by /)
  4. Call ops->lookup() for each component
  5. Return final node or NULL
Example:
struct vfs_node *node = vfs_resolve("/home/user/file.txt");
if (node && node->type == VFS_FILE) {
    // File found
}
Source: kernel/src/fs/vfs.c:29-58

vfs_read

Read data from a file.
int vfs_read(struct vfs_node *node, uint64_t offset, 
             void *buf, size_t count);
node
struct vfs_node*
File node to read from.
offset
uint64_t
Byte offset in file.
buf
void*
Destination buffer.
count
size_t
Number of bytes to read.
return
int
Number of bytes read, or -1 on error.
Behavior:
  • Delegates to node->ops->read()
  • Returns -1 if node is NULL or read operation not supported
Source: kernel/src/fs/vfs.c:60-64

vfs_write

Write data to a file.
int vfs_write(struct vfs_node *node, uint64_t offset, 
              const void *buf, size_t count);
node
struct vfs_node*
File node to write to.
offset
uint64_t
Byte offset in file.
buf
const void*
Source buffer.
count
size_t
Number of bytes to write.
return
int
Number of bytes written, or -1 on error.
Source: kernel/src/fs/vfs.c:66-70

vfs_create

Create a new file or directory entry.
int vfs_create(struct vfs_node *dir, const char *name, vfs_type_t type);
dir
struct vfs_node*
Parent directory.
name
const char*
Filename (no path separators).
type
vfs_type_t
VFS_FILE or VFS_DIR.
return
int
Returns 0 on success, -1 on error.
Source: kernel/src/fs/vfs.c:72-76
Delete a file.
int vfs_unlink(struct vfs_node *dir, const char *name);
dir
struct vfs_node*
Parent directory.
name
const char*
Filename to delete.
return
int
Returns 0 on success, -1 on error.
Source: kernel/src/fs/vfs.c:78-82

vfs_mkdir

Create a directory.
int vfs_mkdir(struct vfs_node *dir, const char *name);
dir
struct vfs_node*
Parent directory.
name
const char*
Directory name.
return
int
Returns 0 on success, -1 on error.
Source: kernel/src/fs/vfs.c:84-88

vfs_stat

Get file metadata.
int vfs_stat(struct vfs_node *node, struct vfs_stat *st);
node
struct vfs_node*
File or directory node.
st
struct vfs_stat*
Pointer to stat structure to fill.
return
int
Returns 0 on success, -1 on error.
Behavior:
  1. Calls node->ops->stat() if available
  2. Falls back to filling stat from vfs_node fields:
    • inode, size, type from node
    • mode = 0755 (default)
    • nlink = 1 (default)
Source: kernel/src/fs/vfs.c:90-102

vfs_readdir

Read directory entry by index.
struct vfs_node *vfs_readdir(struct vfs_node *dir, uint32_t index);
dir
struct vfs_node*
Directory node.
index
uint32_t
Entry index (0-based).
return
struct vfs_node*
Pointer to entry node, or NULL if index out of bounds.
Usage Example:
struct vfs_node *dir = vfs_resolve("/home");
for (uint32_t i = 0; ; i++) {
    struct vfs_node *entry = vfs_readdir(dir, i);
    if (!entry) break;
    printf("%s\n", entry->name);
}
Source: kernel/src/fs/vfs.c:104-108

Filesystem Implementations

tmpfs (In-Memory Filesystem)

Fully functional RAM-based filesystem. Features:
  • Mounted at / and /tmp by default
  • Supports files and directories
  • All operations implemented (create, unlink, mkdir, read, write)
  • Data stored in kernel heap via kmalloc()
Source: kernel/src/fs/tmpfs/

ext2 (Extended Filesystem 2)

Status: Stub implementation. Not functional yet.
Planned Features:
  • Read-only access to ext2 partitions
  • Inode-based structure
  • Block group descriptors
Source: kernel/src/fs/ext2/

FAT32 (File Allocation Table)

Status: Stub implementation. Not functional yet.
Planned Features:
  • Read/write access to FAT32 partitions
  • Long filename support (VFAT)
  • Boot sector parsing
Source: kernel/src/fs/fat/

File Descriptor Integration

Processes use file descriptors to interact with VFS. Each process has an FD table.
struct fd_entry {
    void *vfs_node;       // struct vfs_node *
    void *fs_priv;        // Pipe or socket data
    uint64_t offset;      // Current file position
    int flags;            // O_RDONLY, O_WRONLY, O_RDWR
    int in_use;           // FD slot allocated
};
Limits:
  • FD_MAX = 32 file descriptors per process
  • FD 0 = stdin, 1 = stdout, 2 = stderr (reserved)
Source: kernel/src/proc/process.h:36-43

Syscall Interface

VFS operations are exposed through syscalls:

SYS_OPEN

Open file and return FD

SYS_READ

Read from FD

SYS_WRITE

Write to FD

SYS_CLOSE

Close FD

SYS_STAT

Get file metadata

SYS_MKDIR

Create directory

SYS_UNLINK

Delete file

SYS_READDIR

Read directory entries
Implementation: kernel/src/proc/syscall.c

Path Resolution Examples

/       → tmpfs (root)
/tmp    → tmpfs (separate instance)
/mnt/usb → (not mounted)
Resolution Process:
  1. Path: /etc/passwd
    • Matches mount: /
    • Lookup: etc in root → passwd in etc
  2. Path: /tmp/session.dat
    • Matches mount: /tmp (longest match wins)
    • Lookup: session.dat in tmpfs root
  3. Path: /mnt/usb/data
    • No matching mount → returns NULL

Performance Considerations

Path Resolution: O(n×m) where n = path depth, m = directory entriestmpfs: All operations O(1) or O(n) linear scan (no hash tables yet)Mount Lookup: O(m) where m = number of mounts (max 8)

Limitations

  • No symbolic link support yet (VFS_SYMLINK defined but not implemented)
  • No hard links (nlink always 1)
  • No permissions checking (mode bits stored but not enforced)
  • No timestamps (created, modified, accessed)
  • No ownership (uid/gid)
  • No extended attributes


References

Build docs developers (and LLMs) love