The first thing we are going to start implementing is the Superblock which is always the first block in the allocation group. It contains important information pertaining to the Filesystem. You can read more about all the structures here. For the Superblock you can read on it on page 50. You can then start reading at offset 0 from the device. Important fields are:
As we clarified before everything node can be identifies using an inode number. Let's say for example the root inode has an ID of 256 in binary is 0b100000000. To read it we have to know the disk offset, luckily the inode number itself identifies the disk offset. sb_inopblog tells us that this is the first three bits, which are zero, indicate the order of the inode in its block. The rest of the field can then tell us that the inode is in block 32. If we multiply that by sb_blocksize we will get the disk offset to read the inode.
The inode consists of a core that carries metadata like access time and permissions. And then a Union of one of several structures that we are going to discuss when the time comes. You can have a look at the structure on page 112. Important fields are:
Now, let's talk about the simplest type of structures Short Form directories. Theses are directories where all the information are stored on the 512 Bytes of the inode. We can now this type be reading di_format and matching it with XFS_DINODE_FMT_LOCAL. And then matching di_mode to know for sure that this is a directory. Short form directories do not define “.” or “..”.
Short form directories are structures as a head define as follow:
struct xfs_dir2_sf_hdr {
__uint8_t count;
__uint8_t i8count;
xfs_dir2_inou_t parent;
}
Where:
What follows is a list of entries defining the tuples we talked about earlier. Structures like this:
struct xfs_dir2_sf_entry {
__uint8_t namelen;
xfs_dir2_sf_off_t offset;
__uint8_t name[1];
__uint8_t ftype;
xfs_dir2_inou_t inumber;
}
Where:
Now there are two important operation we should support. Iteration and Lookup.
Iteration is when you add directory entries one after the other. This is easy, all you have to do is iterate of the entries list and add one entry at a time. The tricky part is when the buffer is full you cannot add more entries. So the kernel send another request with the offset of the last entry. The offset usually indicates the offset from the start address of the inode. So, all you have to do is seek and then read the next entry and add it agian.
Lookup is when the kernel gives you an inode and a name and asks you for information about the file name <name>. One solution might be to build a hash table that maps the names to the entry offset. That way when asked about an entry you can know exactly where it is on the disk.
This concludes our second week report.