linux source code 本身有提供關於 vfs 的文件
https://github.com/torvalds/linux/blob/master/Documentation/filesystems/vfs.rst
這篇文章把 filesystem 的實作跟 source code 做很清楚的連結跟解說
https://developer.ibm.com/tutorials/l-linux-filesystem/
在閱讀 simplefs 的程式碼時需要先理解幾件事情
simplefs 的架構大致上分為
從原始程式的 readme 可以看到程式碼分為幾個區域
每個區域為 4KiB 除了最後的 data blocks 外.
superblock : 存放 superblock 中的全部資訊,細節可以參考 superblock
inode store: 這個 block 存放全部的 inode 資訊,大小會隨著儲存裝置大小而有變化
inode free bitmap: 用來記錄哪些 inode 已經被使用
block free bitmap: 用來記錄哪些 block 已經被使用
data blocks: 存放檔案內容的地方
superblock 包含整個檔案系統所需要的資訊,同時也是同步 inode 的地方
要更簡化的看出資料結構對應的數字,產生一個只有 404k (檔案系統要求的最小空間) 大小的空間,
然後再用 mkfs.simplefs 去輸出 superblock 寫的資料
magic number 是用來判斷檔案系統是哪一種檔案系統.
最通常的 ext4 magic number 是 0xEF53
下面的連結可以知道目前的檔案系統相對應的 magic number 是哪一個
https://github.com/torvalds/linux/blob/master/include/uapi/linux/magic.h
如果知道 magic number,就可以用 dd 找出 magic number 在檔案系統的那個 block.
以 ext4 為例,則可以透過以下命令找到 magic number 的位置
可以看到 53ef 大約落在 00000430 的地方.而這邊也是 superblock 的位置.如果有原始碼,就有辦法知道鄰近的編碼是什麼意思.
以 simplefs 為例,magic number 為 DEADCELL
可以看到 magic number 是從第一個 block 開始(00000000).
因為 mkfs.simplefs 第一個寫入的是 superblock
這兩個變數是指 記錄 bitmap 需要多少個 blocks
透過前面的 mkfs 的輸出可以知道
由於 201 跟 95 小於 4096 (simplefs block 最小單位)
所以 nr_ifree_blocks 跟 nr_bfree_blocks 都為 1
從這邊也可以知道,如果檔案系統空間越大,所需要的 blocks 就會越大,同時也會在 map 中產生閒置的空間.
以 inode free blocks 為例,在 4096 個 bits 中,實際上只用了 201 個 bits 剩下的都沒有被使用.
想理解 inode 怎麼同步到硬碟上,以及怎麼產生.可以參考這個部分
bitmap 有點像是一個紀錄表,上面記錄著那些 inode 跟 blocks 已經被使用了.如果沒有 bitmap,可能要搜尋整個檔案系統的 inode,或者是硬碟上的 blocks 來找出沒有用到空間或 inode
結構大概就像是一長串的 0 跟 1, 0 表示 inode/block 已經使用,1 則相反.
以 inode 為例,如果檔案系統下建立 3 個檔案,在 bitmap 上面會這樣表示
第一個 0 是 superblock
後面三個 0 則為新建立的 3 個檔案
建立 inode 是檔案系統中最基本的操作.不論是檔案或資料夾或 link 都需要建立一個 inode.
在進入程式碼前要先知道這幾件事情
建立新的 inode 基本上會做以下事情
透過實作可以看到 linux 的記憶體跟儲存裝置是非同步的運行
透過把記憶體區塊標記為 dirty ,然後再一次同步到儲存裝置上.
printk 印出來的結果
可以看到 simplefs_alloc_inode 跟 simplefs_write_inode 中間相差了 5 秒,從這邊可以知道 linux 的硬碟寫入不是即時的.
也可以看到 unmount 後,為了確保資料正確,會一次寫回硬碟.
同時也可以看到一開始 alloc 的 cache 其實不是馬上就會做 destory
simplefs_inode: 是 simplefs 用來讀取寫入儲存裝置時的特有的 inode 格式
simplefs_inode_info: 負責記錄額外資訊,像是 block idx 跟 link
inode 則是 vfs 所提供的 inode
他們之間的關係如下 (to do)
simplefs 的操作主要是在從記憶體,寫回硬碟
所以主要是這三個
simplefs_write_begin #準備把資料寫進 page cache 中
simplefs_write_end #當資料被寫進 cache 後,處理 inode 更新
simplefs_writepage #把 page cache 的資料寫回硬諜
問題
當使用者輸入時,是輸入到哪裡 ?
userspace memory ?
某處的 buffer ?
所以流程會變成
buffer/userspace memory
-> page cache (write)
-> disk (writepage)
寫了一個簡單的寫入程式去測試何時發生,
答案是當呼叫 fclose 的時候, 也就是當使用者結束編輯檔案,在關檔前一次寫回去的時候發生
不過 vim 並不會這樣做,vim 在每一次的檔案更動都會去做開檔關檔案,以確保文件就算是寫到一半 crash 了也能找回之前寫的內容.
請參考 https://hackmd.io/@fwfly/Bka0w4n3Y
那實際上 simplefs 在硬碟上看起來是怎麼樣的?
container_of
? (Linux 的 linked list 實作會用到)