contributed by <LinMarc1210
>
專題自己建構一個檔案系統稱為 simplefs,並且連接到 linux VFS (Virtual File System) ,使得我們可以在 kernel 裡面使用 simplefs ,作者首先透過實驗比較 simplefs 與現有的檔案系統,使用 FIO test 工具幾個項目,而作者有提到他原以為 simplefs 的 IOPS(每秒輸入/輸出)應該比更複雜的 ext4 和 btrfs 次數更少,但結果出來效率卻更好,而影片中提到可能是因為 simplefs 還沒有去做額外的處理,比如 journal。
因此我就去查了 journal 是什麼,得知 journal 是一種日誌檔案系統,使用一種叫做 circular log 的資料結構去儲存尚未被提交到檔案系統的變更,而資料必須被寫入才能儲存變更,例如刪除檔案其實有好幾個動作,但我們可能在剛釋放完 inode 結構時,檔案系統 crash 掉,導致後續 inode bitmap 和 block bitmap 沒有釋放而不能使用,因此 journal 可以避免這樣的連續動作被切斷,可以即時紀錄。所以較複雜的 ext4, btrfs 可能就會讀寫的比較慢,因為他們具備 journaling 的功能,但優勢則是因不會每次直接對 disk 做讀寫,而是批次將 journal 的內容寫入 disk,因此這些檔案系統的 CPU 使用量, Issued rwts 都比 simplefs 更好(更低)。
接下來作者介紹 simplefs 的設計,其設計因為講求直觀,所以跟我們在作業系統學習的檔案系統相似,並且用寫檔來逐一解釋檔案系統追蹤檔案的過程。
將 simplefs 掛載上去之後,開始進行測試建立映像檔,而檔案系統中會先透過 root inode ,然後去找 extent block,這時 extent block (metadata) 應該要指向資料實際存放的 raw block ,但若在分配 extent block 時,裡面是亂的值,則無法指向正確的位置,因此在分配之前先清空 extent block,才可以使用 dd if=/dev/random
去初始化。
那如果要刪除檔案,我們要先專注在 dentry 上面,刪除檔案時 dentry 內部也要連帶刪除除存檔案資訊的該 block ,但是這樣會造成後面所有 block 都要往前移動去補位,以維持 dentry 的緊密性,因此作者只使用 mark=non-used 的方式去標記此檔案已被刪除,這樣就可以在刪除檔案時只須更改一個 block。
simplefs 在實作 journal 的設計是將原本寫入檔案的步驟分成三大步:
這樣就是 atomic (不可分割的)的設計,並且在不管什麼時候斷電,都能復原原本的資料,因為在 metadata 被正式寫入 disk 之前都不會正式生效,也就是 disk 還不認為 data 真的被寫入了,因此在 1 和 2 之間斷電,也只需要重寫一次 metadata 到 journal 就好,就像是資料完全沒被寫到 disk 一樣,如果在 2 和 3 之間斷電,也只需要再從已經寫好 metadata 的 journal 繼續將 metadata 寫入至 disk 即可。其 atomic 的點是要等所有的 metadata 都被完成變更後,才會一併被寫進去 disk,因此不會發生前述「剛釋放完 inode 結構時,檔案系統 crash 掉,導致後續 inode bitmap 和 block bitmap 沒有釋放而不能使用」,因為這些都是 metadata 的變更,會一併寫到 journal 才正式寫到 disk。