added everything

This commit is contained in:
Om Raheja 2024-08-16 17:47:55 -04:00
parent bc0e7d714b
commit 1600f0b89e
2 changed files with 132 additions and 0 deletions

View File

@ -405,5 +405,76 @@ No one is using that anymore. I'm pretty sure all operating systems just use the
This is the "dirty bit" you'll sometimes hear `fsck` talk about. This is the "dirty bit" you'll sometimes hear `fsck` talk about.
```c
/* ext2 file system block group descriptor */
struct ext2_gd {
u_int32_t ext2bgd_b_bitmap; /* blocks bitmap block */
u_int32_t ext2bgd_i_bitmap; /* inodes bitmap block */
u_int32_t ext2bgd_i_tables; /* inodes table block */
u_int16_t ext2bgd_nbfree; /* number of free blocks */
u_int16_t ext2bgd_nifree; /* number of free inodes */
u_int16_t ext2bgd_ndirs; /* number of directories */
u_int16_t reserved;
u_int32_t reserved2[3];
};
```
This must be the `sparse_super2` block group descriptor. Or, maybe not. We'll see. A bitmap block is quite literally a map of bits (bytes) and which blocks in the group manage how it's allocated. A table block is supposed to resemble a tree of inodes in the group.
```c
/*
* If the EXT2F_ROCOMPAT_SPARSE_SUPER flag is set, the cylinder group has a
* copy of the super and cylinder group descriptors blocks only if it's
* a power of 3, 5 or 7
*/
static __inline__ int cg_has_sb(int) __attribute__((__unused__));
static __inline int
cg_has_sb(int i)
{
int a3 ,a5 , a7;
if (i == 0 || i == 1)
return 1;
for (a3 = 3, a5 = 5, a7 = 7;
a3 <= i || a5 <= i || a7 <= i;
a3 *= 3, a5 *= 5, a7 *= 7)
if (i == a3 || i == a5 || i == a7)
return 1;
return 0;
}
```
For what reason..? I guess we will never know.
Lines 381-397 are just redundant utilities that we don't need to care about too much. They do what they do, so you should read over them, but it's not likely we will touch them anytime throughout the project's development.
```c
/*
* Turn file system block numbers into disk block addresses.
* This maps file system blocks to device size blocks.
*/
#define fsbtodb(fs, b) ((b) << (fs)->e2fs_fsbtodb)
#define dbtofsb(fs, b) ((b) >> (fs)->e2fs_fsbtodb)
```
This shows the purpose of the `fsbtodb` and `dbtofsb` macros. They are used to map the block number of the disk to the block number of the filesystem. But it's worth asking where these values come from; it's not stored in the super block!
Then we have more redundant and fancy utilities to abstract complex math behind converting inodes to disk addresses, block numbers, etc.
At the end of the file, we have one last macro which seems peculiar:
```c
/*
* Number of indirects in a file system block.
*/
#define NINDIR(fs) ((fs)->e2fs_bsize / sizeof(u_int32_t))
```
The size of a block over a size of a disk pointer... huh.
It's actually not that complicated.
Similar to the idea I mentioned above, we first have direct pointers to the disk (12), (1) single indirect, (1) double indirect, (1) triple indirect.[[1]](https://opensource.com/article/17/5/introduction-ext4-filesystem)
With that, I guess we've concluded our first deep dive into the ext4 filesystem.

61
writeup/2.md Normal file
View File

@ -0,0 +1,61 @@
# After our initial dig
After getting all of that understood, we can continue our journey, starting with what looks like it's the most reasonable file:
```
ext2fs_extern.h
```
Immidiately we find a lot of structs, an inode pool and declarations of some functions from line 57 onwards that interest us.
Turns out this is the entire list of functions we have defined and where we will put what we have yet to define.
```c
/* ext2fs_alloc.c */
int ext2fs_alloc(struct inode *, u_int32_t, u_int32_t , struct ucred *,
u_int32_t *);
int ext2fs_inode_alloc(struct inode *, mode_t mode, struct ucred *,
struct vnode **);
daddr_t ext2fs_blkpref(struct inode *, u_int32_t, int, u_int32_t *);
void ext2fs_blkfree(struct inode *, u_int32_t);
void ext2fs_inode_free(struct inode *, ufsino_t, mode_t);
```
Here we have allocations and removals. This is definitely something to do with writing, so we can skip over this for now. We don't care about that. Skip to line 83.
```c
/* ext2fs_lookup.c */
int ext2fs_readdir(void *);
int ext2fs_lookup(void *);
int ext2fs_direnter(struct inode *, struct vnode *, struct componentname *);
int ext2fs_dirremove(struct vnode *, struct componentname *);
int ext2fs_dirrewrite(struct inode *, struct inode *, struct componentname *);
int ext2fs_dirempty(struct inode *, ufsino_t, struct ucred *);
int ext2fs_checkpath(struct inode *, struct inode *, struct ucred *);
```
This looks a little bit more relevant, but it's not very likely to be the chief focus for implementing 64-bit mode, or the checksum seed. So, let's keep going.
```c
/* ext2fs_vfsops.c */
int ext2fs_mountroot(void);
int ext2fs_mount(struct mount *, const char *, void *, struct nameidata *,
struct proc *);
int ext2fs_reload(struct mount *, struct ucred *, struct proc *);
int ext2fs_mountfs(struct vnode *, struct mount *, struct proc *);
int ext2fs_unmount(struct mount *, int, struct proc *);
int ext2fs_flushfiles(struct mount *, int, struct proc *);
int ext2fs_statfs(struct mount *, struct statfs *, struct proc *);
int ext2fs_sync(struct mount *, int, int, struct ucred *, struct proc *);
int ext2fs_vget(struct mount *, ino_t, struct vnode **);
int ext2fs_fhtovp(struct mount *, struct fid *, struct vnode **);
int ext2fs_vptofh(struct vnode *, struct fid *);
int ext2fs_sbupdate(struct ufsmount *, int);
int ext2fs_cgupdate(struct ufsmount *, int);
int ext2fs_sysctl(int *, u_int, void *, size_t *, void *, size_t,
struct proc *);
```
Here we have some information regarding mounts. Obviously, this is the first thing we need to implement. We can try to mount a 64-bit filesystem successfully and having errors on every read first, and then slowly break our way out of that.