|
| static int | read_block (uint32_t block_no, void *buf) |
| static int | write_block (uint32_t block_no, const void *buf) |
| static int | read_inode (uint32_t ino, ext2_inode_t *out) |
| static int | write_inode (uint32_t ino, const ext2_inode_t *in) |
| static int | free_block (uint32_t block_no) |
| int | ext2_truncate_inode (uint32_t ino, uint64_t new_size) |
| static int | allocate_block (uint32_t *block_no) |
| static int | allocate_inode (uint32_t *ino) |
| static int | free_inode (uint32_t ino) |
| static uint8_t | inode_vfs_type (const ext2_inode_t *inode) |
| static int | inode_data_block (const ext2_inode_t *inode, uint32_t block_idx, uint32_t *block_no) |
| int | ext2_mount (uint64_t part_lba_start, uint64_t part_lba_end) |
| int | ext2_readdir (uint32_t dir_ino, uint64_t *offset, vfs_dirent_cb_t cb, void *ud) |
| static int | find_entry_cb (const char *name, uint8_t nlen, uint32_t ino, uint8_t ftype, void *ud) |
| static int | names_match (const char *name, uint8_t nlen, const char *target) |
| static int | dir_empty_cb (const char *name, uint8_t nlen, uint32_t ino, uint8_t ftype, void *ud) |
| static int | ext2_dir_is_empty (uint32_t dir_ino) |
| static int | ext2_remove_dirent (uint32_t parent_ino, const char *name, uint32_t *removed_ino_out, uint8_t *removed_ftype_out) |
| 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) |
ext2_create() - Allocate a new inode and add a directory entry to @parent_ino. @parent_ino: Inode number of the parent directory.
@out_ino: Set to the new inode number on success.
Algorithm:
- Allocate a new inode number via allocate_inode().
- Initialise the inode struct: i_mode=EXT2_S_IFREG|0644, i_links_count=1, i_size=0, i_blocks=0, all i_block[]=0. Zero all other fields.
- Write the new inode to disk via write_inode().
- Insert a new ext2_dirent_t in the parent directory: a. Iterate parent directory blocks; find the last block with space. "Space" = last entry's actual size (8 + name_len rounded up to 4) is less than its rec_len (meaning the last entry was padded). b. Shrink the last entry's rec_len to its minimal size (8 + name_len aligned up to 4 bytes), then append the new entry using the freed space. c. The new entry's rec_len fills to the end of the block. d. If no space in existing blocks, allocate a new block, update i_block[k] and i_blocks in the parent inode, write parent inode back, then place the new entry at the start of the new block with rec_len=g_block_size.
- Write the modified directory block back to disk.
- Returns
- : 0 on success, -1 on I/O error, -2 on ENOSPC (no free inodes/blocks).
|
| int | ext2_create (uint32_t parent_ino, const char *name, uint16_t mode, uint32_t *out_ino) |
| int | ext2_readlink (uint32_t ino, char *buf, uint32_t len) |
ext2_symlink() - Create a new symlink inode and directory entry. @parent_ino: Inode number of the parent directory.
@target: Symlink target string (null-terminated; stored as-is).
Fast-link used when strlen(target) <= 60; target stored inline in i_block[]. Block-link used when strlen(target) > 60; allocates one data block. Directory entry file_type set to 7 (EXT2_FT_SYMLINK).
- Returns
- : 0 on success, -1 on I/O error, -2 on ENOSPC.
|
| int | ext2_symlink (uint32_t parent_ino, const char *name, const char *target) |
| int | ext2_write_file (uint32_t ino, uint64_t off, const void *buf, uint32_t len) |
| int | ext2_flush_inode (uint32_t ino) |
|
ext2_mkdir() - Create a new directory inode and add a directory entry in @parent_ino. @parent_ino: Inode number of the parent directory.
@out_ino: Set to the new directory inode number on success.
Algorithm:
- Allocate a new inode and a data block.
- Initialise the new inode: i_mode=EXT2_S_IFDIR|0755, i_links_count=2 (one for the parent's dirent, one for the '.' entry inside the new dir), i_size=g_block_size, i_blocks=g_block_size/512, i_block[0]=new_block.
- Write the new inode's data block with '.' (points to new_ino) and '..' (points to parent_ino) directory entries filling the full block.
- Insert a new ext2_dirent_t (file_type=EXT2_FT_DIR) in the parent directory, using the same split-and-append or new-block logic as ext2_create().
- Increment the parent inode's i_links_count (the '..' hard link).
- Increment bg_used_dirs_count in the block group descriptor.
- Returns
- : 0 on success, -1 on I/O error, -2 on ENOSPC (no free inodes/blocks).
|
| static vfs_ops_t | g_ext2_vfs_ops |
| int | ext2_mkdir (uint32_t parent_ino, const char *name, uint32_t *out_ino) |
| int | ext2_rmdir (uint32_t parent_ino, const char *name) |
| static int | ext2_add_dirent (uint32_t parent_ino, const char *name, uint32_t ino, uint8_t ftype) |
| static uint8_t | ext2_mode_to_ft (uint16_t mode) |
| static int | ext2_rename (uint32_t old_parent_ino, const char *old_name, uint32_t new_parent_ino, const char *new_name) |
| static int | ext2_unlink (uint32_t parent_ino, const char *name) |
| int | ext2_chmod (uint32_t ino, uint16_t mode) |
| int | ext2_mknod (uint32_t parent_ino, const char *name, uint16_t mode, uint32_t dev, uint32_t *out_ino) |
| static int | ext2_statfs (vfs_statfs_t *out) |
| static int | ext2_fs_mount (const char *source, const char *target, const void *data) |
| 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.
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).
- Returns
- : 0 on success, -1 on ATA I/O error or invalid magic.
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.
- Returns
- : 0 when all entries visited, or first non-zero return value from @cb.
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.
- Returns
- : 0 on success, -1 on type mismatch or I/O error.