|
miniOS
x86_64 hobby kernel with SMP, VFS, and POSIX process model
|


Go to the source code of this file.
Classes | |
| struct | __attribute__ |
Macros | |
| #define | EXT2_MAGIC 0xEF53 |
| #define | EXT2_ROOT_INO 2 |
| #define | EXT2_S_IFREG 0x8000 /* regular file */ |
| #define | EXT2_S_IFDIR 0x4000 /* directory */ |
| #define | EXT2_S_IFLNK 0xA000 /* symbolic link */ |
| #define | EXT2_S_IFCHR 0x2000 /* character device */ |
| #define | EXT2_S_IFBLK 0x6000 /* block device */ |
| #define | EXT2_FT_UNKNOWN 0 |
| #define | EXT2_FT_REG_FILE 1 |
| #define | EXT2_FT_DIR 2 |
| #define | EXT2_FT_CHRDEV 3 |
| #define | EXT2_FT_BLKDEV 4 |
| #define | EXT2_FT_SYMLINK 7 |
Typedefs | |
| typedef struct vfs_inode_info | vfs_inode_info_t |
Functions | |
| int | ext2_mount (uint64_t part_lba_start, uint64_t part_lba_end) |
| int | ext2_lookup (const char *path, vfs_inode_info_t *out) |
| int | ext2_read_file (uint32_t ino, uint64_t off, void *buf, uint32_t len) |
| int | ext2_readdir (uint32_t dir_ino, uint64_t *offset, vfs_dirent_cb_t cb, void *ud) |
| int | ext2_write_file (uint32_t ino, uint64_t off, const void *buf, uint32_t len) |
: Null-terminated filename (no path separators). | |
ext2_create() - Create a new regular file inode and directory entry. @parent_ino: Inode number of the parent directory. @out_ino: Output: inode number of the newly created file. Allocates a new inode via the inode bitmap (first-fit). Initialises the inode with i_mode = EXT2_S_IFREG | (mode & 0777), i_links_count = 1, all block pointers zero, i_size = 0. Appends an ext2_dirent_t to the parent directory. Writes back the new inode, updated bitmaps, superblock, and BGD. @mode: Lower 9 bits used as permission bits; 0 defaults to 0644.
| |
| int | ext2_create (uint32_t parent_ino, const char *name, uint16_t mode, uint32_t *out_ino) |
| int | ext2_flush_inode (uint32_t ino) |
| int | ext2_truncate_inode (uint32_t ino, uint64_t new_size) |
| int | ext2_readlink (uint32_t ino, char *buf, uint32_t len) |
: Symlink filename (no path separators). | |
@target: Target string stored as-is (may be relative or absolute).
| |
| int | ext2_symlink (uint32_t parent_ino, const char *name, const char *target) |
: Null-terminated filename (no '/' allowed). | |
ext2_mknod() - Create a device-file inode (char or block) in a directory. @parent_ino: Inode number of the parent directory. @mode: Inode mode: EXT2_S_IFCHR|perms or EXT2_S_IFBLK|perms. @dev: Device number encoded as (major<<8)|minor stored in i_block[0]. @out_ino: Set to the new inode number on success.
| |
| int | ext2_mknod (uint32_t parent_ino, const char *name, uint16_t mode, uint32_t dev, uint32_t *out_ino) |
: Null-terminated directory name (no '/' allowed). | |
ext2_mkdir() - Create a new directory inode and link it into @parent_ino. @parent_ino: Inode number of the parent directory. @out_ino: Set to the new directory inode number on success. Allocates an inode (i_mode=EXT2_S_IFDIR|0755, i_links_count=2) and a data block containing '.' (→ new_ino) and '..' (→ parent_ino) entries. Inserts a directory entry with file_type=EXT2_FT_DIR in the parent, then increments the parent's i_links_count for the '..' back-reference and bumps bg_used_dirs_count in the block group descriptor.
| |
| int | ext2_mkdir (uint32_t parent_ino, const char *name, uint32_t *out_ino) |
: Directory name to remove. | |
ext2_rmdir() - Remove an empty directory inode and its parent entry. @parent_ino: Inode number of the parent directory. The target must exist, be a directory, and contain only "." and "..". Frees the directory data block and inode, removes the parent directory entry, decrements the parent's link count, and updates bg_used_dirs_count.
| |
| int | ext2_rmdir (uint32_t parent_ino, const char *name) |
| void | ext2_init (void) |
| #define EXT2_FT_BLKDEV 4 |
| #define EXT2_FT_CHRDEV 3 |
| #define EXT2_FT_DIR 2 |
| #define EXT2_FT_REG_FILE 1 |
| #define EXT2_FT_SYMLINK 7 |
| #define EXT2_FT_UNKNOWN 0 |
| #define EXT2_MAGIC 0xEF53 |
| #define EXT2_ROOT_INO 2 |
| #define EXT2_S_IFBLK 0x6000 /* block device */ |
| #define EXT2_S_IFCHR 0x2000 /* character device */ |
| #define EXT2_S_IFDIR 0x4000 /* directory */ |
| #define EXT2_S_IFLNK 0xA000 /* symbolic link */ |
| #define EXT2_S_IFREG 0x8000 /* regular file */ |
| typedef struct vfs_inode_info vfs_inode_info_t |

| int ext2_flush_inode | ( | uint32_t | ino | ) |
ext2_flush_inode() - Write the in-memory inode state back to disk. @ino: Inode number to flush.
Reads the inode table block containing @ino, updates the inode bytes in place with the current on-disk inode data, then writes the block back. Called from vfs_close() via ops->flush to persist i_size and i_block[] after a write sequence.
ext2_flush_inode() - Write the current inode state back to disk. @ino: Inode number to flush.
Reads the inode from disk and immediately writes it back. Used by vfs_close() (via ops->flush) to ensure i_size and i_block[] are durable after writes. The ATA flush command is issued separately by the caller.

| void ext2_init | ( | void | ) |
ext2_init() - Register the ext2 filesystem type with the VFS registry.
After this call, vfs_mount_fstype("ext2", source, target, data) can be used to mount any ext2 partition by passing a vfs_mount_data_t as @data. ext2_init() does NOT mount anything itself; it only registers the type. Call once during kernel startup, before the first ext2 mount.


| int ext2_lookup | ( | const char * | path, |
| vfs_inode_info_t * | out ) |
ext2_lookup() - Resolve an absolute path to typed inode metadata. @path: Absolute path string (e.g., "/hello.txt", "/bin/sh"). Must begin with '/'. Components separated by '/'. @out: Output metadata populated on success.
Starts at root inode (inode 2) and descends through each path component by iterating directory entries via ext2_readdir with a find_entry_cb callback. Directory traversal still handles only direct blocks (i_block[0..11]), which is sufficient for the current single-group test image. Uses static g_block_buf — not reentrant.
Context: Single-threaded; uses static g_block_buf. Not ISR-safe.
ext2_lookup() - Resolve path components starting from root inode 2. @path: Absolute path; must start with '/'.
Tokenises @path on '/' using strtok-like manual scanning. For each component, calls ext2_readdir with find_entry_cb to search the current directory inode for a matching entry. Updates current_ino to the matched child inode and continues to the next component. Returns current_ino after all components.


| int ext2_mknod | ( | uint32_t | parent_ino, |
| const char * | name, | ||
| uint16_t | mode, | ||
| uint32_t | dev, | ||
| uint32_t * | out_ino ) |
ext2_mknod() - Create a char or block device inode in @parent_ino.
Allocates an inode with i_mode = @mode (EXT2_S_IFCHR|perms or EXT2_S_IFBLK|perms), i_links_count = 1, no data blocks, and stores @dev in i_block[0] (traditional Linux ext2 device number encoding). Inserts a directory entry with EXT2_FT_CHRDEV or EXT2_FT_BLKDEV into the parent directory using the same split-and-append logic as ext2_create.

ext2_mount() - Mount an ext2 partition by reading and validating its superblock. @part_lba_start: First sector of the partition (LBA offset from disk start). @part_lba_end: Last sector of the partition (inclusive).
Reads the superblock from byte offset 1024 within the partition (sector part_lba_start + 2 for 512-byte sectors). Validates the ext2 magic number (0xEF53). Initialises global filesystem state: block size, sectors per block, inodes per group, inode size, first data block. Reads block group descriptor table to locate the inode table. Assumes a single block group.
ext2_mount() - Read superblock and initialise filesystem global state. @part_lba_start: LBA of partition start; stored in g_part_start.
Reads 2 sectors at part_lba_start + 2 (superblock at 1024-byte offset). Checks s_magic == 0xEF53. Sets g_block_size = 1024 << s_log_block_size, g_sectors_per_block, g_inodes_per_group, g_inode_size (128 for rev 0, s_inode_size for rev 1), g_first_data_block. Reads block group descriptor table at block g_first_data_block+1 to obtain inode table base. Single block group assumed (8 MiB image has exactly one group).


ext2_read_file() - Read bytes from an open inode. @ino: Inode number of the file (>= 2; must be a regular file). @off: Byte offset within the file to start reading from. @buf: Destination buffer for read data. @len: Maximum number of bytes to read.
Maps byte range [@off, @off+@len) to direct block indices plus the first single-indirect block (i_block[12]). Reads each required block via ata_read_sectors into g_block_buf, then copies the relevant slice to @buf. Clamps to file size (i_size). Handles cross-block reads by iterating over block boundaries.
Context: Single-threaded; uses static g_block_buf. Not reentrant.
ext2_read_file() - Copy file data from inode blocks into caller's buffer. @ino: Inode number of the regular file. @off: Starting byte offset within the file. @buf: Destination buffer. @len: Requested byte count.
Reads the inode to get i_size and i_block[]. Clamps read to i_size. Computes starting block index as off / g_block_size, byte offset within block as off % g_block_size. Resolves each logical block through direct pointers and the first single-indirect block, then copies the relevant slice. Iterates until @len bytes are copied or EOF.

| int ext2_readdir | ( | uint32_t | dir_ino, |
| uint64_t * | offset, | ||
| vfs_dirent_cb_t | cb, | ||
| void * | ud ) |
ext2_readdir() - Iterate directory entries in an inode. @dir_ino: Inode number of the directory to read (must have i_mode dir bit set). @offset: Caller-owned byte cursor. Entries before *@offset are skipped; on return it points just past the last emitted record. @cb: Callback invoked for each directory entry with (name, name_len, inode, file_type, ud). If @cb returns non-zero, iteration stops immediately. @ud: Opaque user data pointer forwarded to @cb unchanged.
Reads all direct blocks of the directory inode and iterates ext2_dirent_t records within each block. Skips entries with inode == 0 (deleted entries). Handles variable-length records via rec_len. Direct blocks only.
Context: Single-threaded; uses static g_block_buf. Not reentrant.
ext2_readdir() - Iterate directory entries in all direct blocks of a directory inode. @dir_ino: Directory inode number. @cb: Called for each valid entry (inode != 0) with name (not null-terminated), name_len, child inode, file_type, and @ud. @ud: Forwarded to @cb unchanged.
Reads each direct block (i_block[0..11]) of the directory inode. Within each block, walks ext2_dirent_t records by incrementing a byte pointer by rec_len. Skips entries with inode==0 (deleted or padding entries). Stops block iteration when the block pointer address reaches block_end. Returns early if @cb returns non-zero.


ext2_readlink() - Read the target of a symlink inode (POSIX: not null-terminated). @ino: Inode number of the symlink. @buf: Output buffer. @len: Maximum bytes to copy.
ext2_readlink() - Read the target string of a symlink inode. @ino: Inode number of the symlink (i_mode must have EXT2_S_IFLNK set). @buf: Output buffer. NOT null-terminated (POSIX readlink semantics). @len: Maximum bytes to copy into buf.
Fast-link (i_blocks == 0): target stored inline in i_block[0..14] bytes. Block-link (i_blocks > 0): target stored in data block i_block[0].

| int ext2_rmdir | ( | uint32_t | parent_ino, |
| const char * | name ) |

| int ext2_symlink | ( | uint32_t | parent_ino, |
| const char * | name, | ||
| const char * | target ) |

ext2_truncate_inode() - Truncate a regular file inode to zero bytes. @ino: Inode number of the file to truncate (must be a regular file).
Frees all data blocks referenced by the inode, clears i_block[0..14], resets i_size = 0 and i_blocks = 0, and writes the inode back to disk. Updates block bitmap, superblock s_free_blocks_count, and BGD bg_free_blocks_count for each freed block.
ext2_truncate_inode() - Truncate a regular file to zero bytes. @ino: Inode number of the file to truncate.
Walks i_block[0..11] (direct blocks) and i_block[12..14] (indirect pointers, treated as direct block references — single-group, small files only use direct blocks). Frees each allocated block via free_block(). Clears all block pointer entries in the inode (i_block[0..14] = 0). Resets i_size = 0 and i_blocks = 0. Writes the updated inode back to disk.
Only truncates regular files (i_mode & EXT2_S_IFREG). Returns -1 for directories or other non-regular types.

ext2_write_file() - Write bytes into an existing inode's data blocks. @ino: Inode number of the target regular file. @off: Byte offset within the file to start writing at. @buf: Source buffer containing bytes to write. @len: Number of bytes to write.
Allocates new data blocks as needed when the write extends past existing allocated blocks. Updates i_size if (off + len) > current i_size. Does NOT flush to disk — caller must call ext2_flush_inode() then ata_flush().
ext2_write_file() - Write bytes to an inode's data blocks, allocating as needed. @ino: Inode number of the target regular file. @off: Byte offset within the file. @buf: Source data. @len: Number of bytes to write.
For each block touched by the range [off, off+len):
