Lecture 21 - Minix Filesystem Structure, Finishing Virtual Memory
A filesystem is just a data structure that organizes files, which is just a collection of stuff. It has:
- The file does not have names, rather just links to these names.
- Unix files are largely untyped (except for files and directory files). But some file systems can be typed. You can even have file systems that are sort-of types, like NTFS on Windows.
- Is it string based or hunk based? Do you read things a byte at a time or a chunk at a time? This will impact the performance of things like text editors (think displaying large files).
Minix Filesystem
Note that assignment 5 is the largest assignment of the class; however, all the code is yours and it is pretty simple.
The basic structure is that you have:
- files: a collection of data
- directories: a file full of links
- Attached to the filesystem by links, which associate a name with an
ino
,ino
is is the index node, which contains the metadata of the file and the contents of it- In minix this contents is the zone numbers (for data).
inodes
are all the same size (it's an array) and we want them as small as possible to reduce wasted space. As such, they have the following fields:mode
: the type of filelinks
: the number of links that point to this file (if its 0 the minix marks it for deletion)uid, gid
: ID numberssize
: The size of the node.atime, mtime, ctime
: Last accessed (last read), modified (last time the contents were changed), changed (metadata or contents were changed) time.
- Then the stuff!
- The data structure part of this has 7 direct-zones (0 indexed) that represent the 7 logical first zones of the file.
- It also has indirect-zones that are blocks with block numbers. (MINIX incorrectly uses blocks here, where really they should be zones). We can index 1024 zones in these blocks!
- What if we have a really big block? Then we have a double-indirect block, which contains indirect-zone numbers.
- ... (this continues for triple-indirect and so on).
An Aside on Disks
Every disk side have a track. Each track is grouped into cylinders, and there are multiple heads for choosing each cylinder. As such then we can think of turning our disk into an array of slots of bytes we can store at.
For partitioning, we may have multiple partitions on one disk. MINIX allows for sub-partitioning! For the partition table in the Master-Boot-Record (MBR) has 4 entries:
- 1 byte of boot indicator (is the partition bootable). For the purposes of reading from it we don't really care.
- 1 byte of the start head
- 1 byte of the start sector
- 1 byte of the start cylinder
- 1 byte for the type
- 1 byte for end head
- 1 byte for the end sector
- 1 byte for the end cylinder
- 4 bytes for the
lfirst
address used - 4 bytes for the size used
But in reality there are more cylinders than sectos, so usually the cylinder part gets like 10 bits while the sector gets like 6 bits.
Now how can we verify that our data is actually valid on the disk (rather than being garbage data). We use the:
- Last 2 bytes are used for a signature that we can check to verify
Here to clarify the filesystem's blocks:
- Boot block: contains OS-boot level code
- Super-block: contains information about the filesystem like:
ninodes
: number ofinodes
1_blocks, 2_blocks
: number of single, double direct blocksfirst_data
,log_zone_size
: Number of bits to shift to get the right number.max_file_size
num_zones
magic
: Signature that marks this as the valid super-block.blocksize
But look! The super-block is the second block! We say that the super-block must start at the start of a page, at a pre-specified offset from the boot block.
In Action
Let's say we want to look for /A/B/C
. For convenience we say inode
1 is the root of our file system (since inode 0
is used for marking files for deletion, and thus our inode
's are 1-indexed).
Now this inode
we get and it has a size
(see above). That means that we can use the zone
number and from that get zone information via the data for the /
directory.
/
- 1: .
- 1: ..
- 2: usr
- 10: home
- 12: A
We see that the next zone number is 12
so we go to that zone and get that file's contents:
/A
- 12: .
- 1: ..
- 0: bogus
- 7: foo
- 123: B
So then we know the next zone number is 123
so we go to that zone number and get that file's contents:
/A/B
- 123: .
- 12: ..
- 100: C
So the idea is to:
- Find the file system
- Find the super-block
- Find the root
inode
- Try to abstract the conept of a file, from the data that it gets in each
zone
- Try to incorporate this iterative process to decode the files on the fly.