Add VFS subsystem and initrd filesystem driver (AI)
VFS subsystem (vfs.c/h): - Mount table with up to 16 mount points, longest-prefix path matching. - File descriptor table (256 entries, fds 0-2 reserved for std streams). - Path resolution walks mount table then delegates to filesystem's finddir() for each path component. - Operations: open, close, read, write, seek, readdir, stat. - Each filesystem driver provides a vfs_fs_ops_t with callbacks. Initrd filesystem driver (initrd_fs.c/h): - Read-only VFS driver backed by the CPIO ramdisk. - Mounted at '/initrd' during boot. - Zero-copy reads: file data points directly into the CPIO archive memory, no allocation or copying needed. - Supports readdir (flat iteration) and finddir (name lookup). Bug fix: resolve_path was overwriting file-specific fs_data (set by finddir, e.g. pointer to CPIO file data) with the mount's fs_data (NULL). Fixed to preserve fs_data from finddir. Verified in QEMU: kernel reads /initrd/README via VFS and prints its contents. Ring 3 user process continues to work.
This commit is contained in:
78
docs/vfs.md
Normal file
78
docs/vfs.md
Normal file
@@ -0,0 +1,78 @@
|
||||
# Virtual Filesystem (VFS)
|
||||
|
||||
## Overview
|
||||
|
||||
The VFS provides a unified interface for file and directory operations across
|
||||
different filesystem implementations. Filesystem drivers register ops structs
|
||||
and are mounted at specific paths. Path resolution finds the longest-matching
|
||||
mount point and delegates to that filesystem.
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
User/Kernel Code
|
||||
│
|
||||
▼
|
||||
vfs_open("/initrd/hello-world", 0)
|
||||
│
|
||||
▼
|
||||
VFS: find_mount("/initrd/hello-world")
|
||||
│ → mount "/initrd", rel_path = "hello-world"
|
||||
▼
|
||||
resolve_path → initrd_finddir("hello-world")
|
||||
│
|
||||
▼
|
||||
vfs_read(fd, buf, size)
|
||||
│ → initrd_read(node, offset, size, buf)
|
||||
▼
|
||||
Returns file data from CPIO archive
|
||||
```
|
||||
|
||||
## Mount Points
|
||||
|
||||
Filesystems are mounted at absolute paths. The VFS supports up to 16
|
||||
simultaneous mounts. Path resolution uses longest-prefix matching:
|
||||
|
||||
```
|
||||
Mount: "/initrd" → handles /initrd/*
|
||||
Mount: "/sys" → handles /sys/*
|
||||
Mount: "/dev" → handles /dev/*
|
||||
```
|
||||
|
||||
## File Operations
|
||||
|
||||
| Function | Description |
|
||||
|----------|-------------|
|
||||
| `vfs_open(path, flags)` | Open a file, returns fd |
|
||||
| `vfs_close(fd)` | Close a file descriptor |
|
||||
| `vfs_read(fd, buf, size)` | Read bytes, advances offset |
|
||||
| `vfs_write(fd, buf, size)` | Write bytes, advances offset |
|
||||
| `vfs_seek(fd, offset, whence)` | Seek within file |
|
||||
| `vfs_readdir(path, idx, out)` | Read directory entry |
|
||||
| `vfs_stat(path, out)` | Get file info |
|
||||
|
||||
## Filesystem Driver Interface
|
||||
|
||||
Each filesystem provides a `vfs_fs_ops_t` struct:
|
||||
|
||||
```c
|
||||
typedef struct vfs_fs_ops {
|
||||
int (*open)(vfs_node_t *node, uint32_t flags);
|
||||
void (*close)(vfs_node_t *node);
|
||||
int32_t (*read)(vfs_node_t *node, uint32_t offset, uint32_t size, void *buf);
|
||||
int32_t (*write)(vfs_node_t *node, uint32_t offset, uint32_t size, const void *buf);
|
||||
int (*readdir)(vfs_node_t *dir, uint32_t idx, vfs_dirent_t *out);
|
||||
int (*finddir)(vfs_node_t *dir, const char *name, vfs_node_t *out);
|
||||
} vfs_fs_ops_t;
|
||||
```
|
||||
|
||||
## Initrd Filesystem Driver
|
||||
|
||||
The initrd filesystem (`initrd_fs.c`) provides read-only access to the CPIO
|
||||
ramdisk. It is automatically mounted at `/initrd` during boot. Files are
|
||||
accessed via zero-copy reads directly from the CPIO archive in memory.
|
||||
|
||||
## Files
|
||||
|
||||
- `src/vfs.h` / `src/vfs.c` — VFS core: mount table, fd table, path resolution
|
||||
- `src/initrd_fs.h` / `src/initrd_fs.c` — CPIO ramdisk VFS driver
|
||||
Reference in New Issue
Block a user