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:
197
src/vfs.h
Normal file
197
src/vfs.h
Normal file
@@ -0,0 +1,197 @@
|
||||
/**
|
||||
* @file vfs.h
|
||||
* @brief Virtual Filesystem (VFS) subsystem.
|
||||
*
|
||||
* Provides a unified interface for file and directory operations across
|
||||
* different filesystem implementations. Filesystem drivers register
|
||||
* themselves and can be mounted at specific paths.
|
||||
*/
|
||||
|
||||
#ifndef VFS_H
|
||||
#define VFS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/** Maximum number of open files across all processes. */
|
||||
#define VFS_MAX_OPEN_FILES 256
|
||||
|
||||
/** Maximum number of mounted filesystems. */
|
||||
#define VFS_MAX_MOUNTS 16
|
||||
|
||||
/** Maximum path length. */
|
||||
#define VFS_MAX_PATH 256
|
||||
|
||||
/** Maximum filename length. */
|
||||
#define VFS_MAX_NAME 128
|
||||
|
||||
/** File types. */
|
||||
#define VFS_FILE 0x01
|
||||
#define VFS_DIRECTORY 0x02
|
||||
#define VFS_CHARDEV 0x03
|
||||
#define VFS_BLOCKDEV 0x04
|
||||
#define VFS_SYMLINK 0x06
|
||||
|
||||
/** Seek origins. */
|
||||
#define VFS_SEEK_SET 0
|
||||
#define VFS_SEEK_CUR 1
|
||||
#define VFS_SEEK_END 2
|
||||
|
||||
/** Forward declarations. */
|
||||
struct vfs_node;
|
||||
struct vfs_dirent;
|
||||
struct vfs_fs_ops;
|
||||
|
||||
/**
|
||||
* Directory entry, returned by readdir.
|
||||
*/
|
||||
typedef struct vfs_dirent {
|
||||
char name[VFS_MAX_NAME]; /**< Entry name. */
|
||||
uint32_t inode; /**< Inode number (fs-specific). */
|
||||
uint8_t type; /**< VFS_FILE, VFS_DIRECTORY, etc. */
|
||||
} vfs_dirent_t;
|
||||
|
||||
/**
|
||||
* VFS node representing a file or directory.
|
||||
*/
|
||||
typedef struct vfs_node {
|
||||
char name[VFS_MAX_NAME]; /**< Node name. */
|
||||
uint8_t type; /**< VFS_FILE, VFS_DIRECTORY, etc. */
|
||||
uint32_t size; /**< File size in bytes. */
|
||||
uint32_t inode; /**< Inode number (fs-specific). */
|
||||
uint32_t mode; /**< Permissions/mode. */
|
||||
|
||||
/** Filesystem-specific operations. */
|
||||
struct vfs_fs_ops *ops;
|
||||
|
||||
/** Opaque pointer for the filesystem driver. */
|
||||
void *fs_data;
|
||||
|
||||
/** Mount index (which mount this node belongs to). */
|
||||
int mount_idx;
|
||||
} vfs_node_t;
|
||||
|
||||
/**
|
||||
* Filesystem operations provided by each filesystem driver.
|
||||
*/
|
||||
typedef struct vfs_fs_ops {
|
||||
/** Open a file. Returns 0 on success. */
|
||||
int (*open)(vfs_node_t *node, uint32_t flags);
|
||||
|
||||
/** Close a file. */
|
||||
void (*close)(vfs_node_t *node);
|
||||
|
||||
/** Read up to `size` bytes at `offset`. Returns bytes read, or -1. */
|
||||
int32_t (*read)(vfs_node_t *node, uint32_t offset, uint32_t size, void *buf);
|
||||
|
||||
/** Write up to `size` bytes at `offset`. Returns bytes written, or -1. */
|
||||
int32_t (*write)(vfs_node_t *node, uint32_t offset, uint32_t size, const void *buf);
|
||||
|
||||
/** Read directory entry at index `idx`. Returns 0 on success, -1 at end. */
|
||||
int (*readdir)(vfs_node_t *dir, uint32_t idx, vfs_dirent_t *out);
|
||||
|
||||
/** Look up a child by name within a directory. Returns 0 on success. */
|
||||
int (*finddir)(vfs_node_t *dir, const char *name, vfs_node_t *out);
|
||||
} vfs_fs_ops_t;
|
||||
|
||||
/**
|
||||
* Mount point entry.
|
||||
*/
|
||||
typedef struct vfs_mount {
|
||||
char path[VFS_MAX_PATH]; /**< Mount path (e.g., "/initrd"). */
|
||||
vfs_fs_ops_t *ops; /**< Filesystem operations. */
|
||||
void *fs_data; /**< Filesystem-specific data. */
|
||||
int active; /**< 1 if mounted, 0 if free. */
|
||||
} vfs_mount_t;
|
||||
|
||||
/**
|
||||
* Open file descriptor.
|
||||
*/
|
||||
typedef struct vfs_fd {
|
||||
vfs_node_t node; /**< The file node. */
|
||||
uint32_t offset; /**< Current read/write offset. */
|
||||
uint32_t flags; /**< Open flags. */
|
||||
int active; /**< 1 if in use, 0 if free. */
|
||||
} vfs_fd_t;
|
||||
|
||||
/**
|
||||
* Initialize the VFS subsystem.
|
||||
*/
|
||||
void init_vfs(void);
|
||||
|
||||
/**
|
||||
* Mount a filesystem at the given path.
|
||||
*
|
||||
* @param path Mount point path (e.g., "/initrd").
|
||||
* @param ops Filesystem operations.
|
||||
* @param fs_data Filesystem-specific data pointer.
|
||||
* @return 0 on success, -1 on failure.
|
||||
*/
|
||||
int vfs_mount(const char *path, vfs_fs_ops_t *ops, void *fs_data);
|
||||
|
||||
/**
|
||||
* Open a file by path.
|
||||
*
|
||||
* @param path Absolute path to the file.
|
||||
* @param flags Open flags (currently unused).
|
||||
* @return File descriptor (>= 0), or -1 on failure.
|
||||
*/
|
||||
int vfs_open(const char *path, uint32_t flags);
|
||||
|
||||
/**
|
||||
* Close an open file descriptor.
|
||||
*
|
||||
* @param fd File descriptor.
|
||||
*/
|
||||
void vfs_close(int fd);
|
||||
|
||||
/**
|
||||
* Read from an open file.
|
||||
*
|
||||
* @param fd File descriptor.
|
||||
* @param buf Buffer to read into.
|
||||
* @param size Maximum bytes to read.
|
||||
* @return Bytes read, or -1 on error.
|
||||
*/
|
||||
int32_t vfs_read(int fd, void *buf, uint32_t size);
|
||||
|
||||
/**
|
||||
* Write to an open file.
|
||||
*
|
||||
* @param fd File descriptor.
|
||||
* @param buf Buffer to write from.
|
||||
* @param size Bytes to write.
|
||||
* @return Bytes written, or -1 on error.
|
||||
*/
|
||||
int32_t vfs_write(int fd, const void *buf, uint32_t size);
|
||||
|
||||
/**
|
||||
* Seek within an open file.
|
||||
*
|
||||
* @param fd File descriptor.
|
||||
* @param offset Offset to seek to.
|
||||
* @param whence VFS_SEEK_SET, VFS_SEEK_CUR, or VFS_SEEK_END.
|
||||
* @return New offset, or -1 on error.
|
||||
*/
|
||||
int32_t vfs_seek(int fd, int32_t offset, int whence);
|
||||
|
||||
/**
|
||||
* Read a directory entry.
|
||||
*
|
||||
* @param path Path to the directory.
|
||||
* @param idx Entry index (0-based).
|
||||
* @param out Output directory entry.
|
||||
* @return 0 on success, -1 at end or on error.
|
||||
*/
|
||||
int vfs_readdir(const char *path, uint32_t idx, vfs_dirent_t *out);
|
||||
|
||||
/**
|
||||
* Stat a file (get its node info).
|
||||
*
|
||||
* @param path Path to the file.
|
||||
* @param out Output node.
|
||||
* @return 0 on success, -1 on failure.
|
||||
*/
|
||||
int vfs_stat(const char *path, vfs_node_t *out);
|
||||
|
||||
#endif /* VFS_H */
|
||||
Reference in New Issue
Block a user