added more to writeup

This commit is contained in:
Om Raheja 2024-08-16 14:50:09 -04:00
parent 2738f75a68
commit 5f7987ba20
2 changed files with 78 additions and 1 deletions

6
README
View File

@ -1 +1,5 @@
openbsd-ext4
# openbsd-ext4
Support for the ext4 filesystem format on OpenBSD. Currently, ext3 is supported in 32-bit mode.
`writeup/` contains my learnings, which I want to document in a book. There is unfortunately no good guides on making an ext4 filesystem except the Linux Kernel Specification.

View File

@ -59,10 +59,83 @@ Each block is a fragment of 1024 bytes at minimum. ext4 was likely designed with
The maximum length of a mount point is 512 characters. You can test this with `mount -t ext2fs <filesystem>`. Even on other systems, it's not likely to work beyond 512 bytes.
```c
#define MINFREE 5
```
As the comment explains pretty well, 5% of blocks should be free. Read the comment from lines 89-100 for the full details.
```c
struct ext2fs {
u_int32_t e2fs_icount; /* Inode count */
u_int32_t e2fs_bcount; /* blocks count */
u_int32_t e2fs_rbcount; /* reserved blocks count */
u_int32_t e2fs_fbcount; /* free blocks count */
u_int32_t e2fs_ficount; /* free inodes count */
u_int32_t e2fs_first_dblock; /* first data block */
u_int32_t e2fs_log_bsize; /* block size = 1024*(2^e2fs_log_bsize) */
u_int32_t e2fs_log_fsize; /* fragment size log2 */
```
This is the beginning of the actual super block. We can break down the information line by line. inodes are data structures to hold the necessary information about a file, except the file name or the actual data itself; on some filesystems, the first few blocks after the inode are reserved for the file, and then the next few blocks contain pointers to other blocks on the disk, and the next few after that contain pointers to pointers to other blocks, etc. This allows for a much larger maximum file size. Momentarily, we will see if the case is such with ext4 as well.
The amount of reserved blocks is the amount of blocks the filesystem needs for journaling, etc. This would depend on what version of the ext filesystem it is, and so forth.
The block size is stored as powers of 2, so the `e2fs_log_xsize` hold just that.
```c
u_int32_t e2fs_bpg; /* blocks per group */
u_int32_t e2fs_fpg; /* frags per group */
u_int32_t e2fs_ipg; /* inodes per group */
u_int32_t e2fs_mtime; /* mount time */
u_int32_t e2fs_wtime; /* write time */
u_int16_t e2fs_mnt_count; /* mount count */
u_int16_t e2fs_max_mnt_count; /* max mount count */
u_int16_t e2fs_magic; /* magic number */
u_int16_t e2fs_state; /* file system state */
u_int16_t e2fs_beh; /* behavior on errors */
```
These lines are quite self explanatory; the only thing worth pointing out is that a group is an amount of bytes that can be read easily by the disk- exact amounts depend on whether its solid state, spinning disk, how old it is, etc. The mount and write time are stored as unix timestamps, and are held to check if the current timestamp match the recorded time, checking if the filesystem was modified externally. This is also useful in journal replay, so we know which transactions to start from. The last 3 are flags/values to differentiate filesystems.
```c
u_int16_t e2fs_minrev; /* minor revision level */
```
The minimum revision level that the filesystem needs- for example, if it's ext4, then the `e2fs_minrev` field would guarantee that it needs at least the features of ext4 (or if its 32-bit, ext3) to be read and mounted
```c
u_int32_t e2fs_lastfsck; /* time of last fsck */
u_int32_t e2fs_fsckintv; /* max time between fscks */
u_int32_t e2fs_creator; /* creator OS */
u_int32_t e2fs_rev; /* revision level */
```
This is to ensure fsck(3) works properly.
> fsck filesystem consistency check and interactive repair
As my manual page likes to call it. This is to replay journaling, or whatever else the filesystem requires to be cleaned up.
```c
u_int16_t e2fs_ruid; /* default uid for reserved blocks */
u_int16_t e2fs_rgid; /* default gid for reserved blocks */
```
The default user and group ID that processes need to have to access reserved blocks. As there isn't much information available online, let's just keep going for now.
```c
/* EXT2_DYNAMIC_REV superblocks */
u_int32_t e2fs_first_ino; /* first non-reserved inode */
u_int16_t e2fs_inode_size; /* size of inode structure */
u_int16_t e2fs_block_group_nr; /* block grp number of this sblk*/
u_int32_t e2fs_features_compat; /* compatible feature set */
u_int32_t e2fs_features_incompat; /* incompatible feature set */
u_int32_t e2fs_features_rocompat; /* RO-compatible feature set */
u_int8_t e2fs_uuid[16]; /* 128-bit uuid for volume */
char e2fs_vname[16]; /* volume name */
char e2fs_fsmnt[64]; /* name mounted on */
u_int32_t e2fs_algo; /* For compression */
u_int8_t e2fs_prealloc; /* # of blocks to preallocate */
u_int8_t e2fs_dir_prealloc; /* # of blocks to preallocate for dir */
u_int16_t e2fs_reserved_ngdb; /* # of reserved gd blocks for resize */
```
These look like what are meant to be the other part of the superblock if the revision number is 3 or higher. Probably added after ext2 support was initially added. The feature set are flags to be defined later. The UUID, name, where it's mounted, algorithm or whatever are informational flags to remain consistent, and this likely means ext2 didn't have these features. `e2fs_prealloc` must be for each file. `gd` likely stands for group descriptor. With that in mind, let's keep moving down the superblock.