問:假設 ext4 文件系統中有個 100KiB 的文件,現在程序在文件後面接着寫入了 100KiB ,寫入過程中斷電了,Ext4 如何保證這個寫入是完整的?
短回答: ext4 不保證,ext4 不關心文件的數據是完整的,只關心和保證 ext4 自己的元數據是完整的。
長回答:
假設如上場景,寫入 100KiB 過程中,甚至 100KiB 寫完(write syscall正常返回)之後發生了突然斷電,然後正常啓動系統,在文件系統回放完日誌之後,可能發生如下結果:
1. 文件長度還是 100KiB
2. 文件長度是 130KiB
3. 文件長度是 200KiB ,但是後面 100KiB 內容是全0或者是垃圾數據
4. 文件長度是 200KiB ,後面 100KiB 內容是程序寫入的數據
如上結果都有可能發生。根據具體文件系統記錄日誌的方式,可能一部分情形在特定條件下不會發生。文件系統的一致性保證的是不會發生下述情況:
a. 文件長度增加了 100KiB 變成 200KiB ,但是文件內容的塊列表還是 100KiB 的塊。
b. 文件內容的塊列表多了 100KiB 的塊,總長度變成了 200KiB ,但是文件系統的可用空間沒有減少 100KiB
c. 文件內容的塊列表多了 100KiB 的塊,但是這 100KiB 同時也被別的文件的塊列表引用着,兩個文件同時共享了一部分塊。
上述這些情況是文件系統需要用日誌保證的一致性。另一方面,如果 write syscall 之後,程序調用 fsync 要求文件系統刷新文件內容到盤上,在 fsync 正常返回之前如果發生了突然斷電,那麼仍然可能發生上面 1-4 的寫入一半的情況。如果 fsync 返回之後突然斷電,那麼正常日誌回放之後可以保證文件變成了 200KiB ,內容也是程序寫入的內容。具體 fsync 要求文件系統做出什麼級別的保證取決於具體的文件系統,ext4/xfs/btrfs 之類的實現各有不同。
具體到 ext4 的情況,在默認開啓了日誌並且 data=ordered 的掛載選項的前提下,發生的事情大概是:
1. 程序發出 write syscall ,write 把程序要寫入的內容從程序的內存拷貝到內核的 pagecache 緩衝區中,同時修改了內存中的 inode 的長度,但是不會把 inode 寫入到盤上。
2. 此時因爲 ext4 的 delayed allocation (ext3沒有延遲分配,xfs和btrfs也會延遲分配。一般使用 extent 表達內容地址的文件系統都會有延遲分配策略),這些緩衝區並沒有對應的塊地址,內容就留在內核的內存頁面裏。
3. 內存壓力下,或者超過了 commit_interval ,或者接到了程序的 fsync/fdatasync 請求,分配不能再拖延下去的時候, ext4 調用塊分配器給上面 write 寫入的頁面安排好塊地址,交給 block io 往盤上寫入。
4. 因爲 data=ordered ,寫入完之後開始考慮更新 inode 和文件系統可用空間之類的元數據。在 journal 中開啓一個新事務,把 inode 所在塊,和可用空間記錄(block group 的 block bitmap )寫入 journal ,然後提交事務。
5. 等事務提交完落盤之後,再把 inode 和可用空間記錄慢慢寫回到 ext4 自己的 inode table 和 block group 描述的地方。
如果事務提交之後,發生突然斷電,正常開機並且回放日誌的時候會保證日誌中記錄的事務會再次寫到正確的地方去
fc fs筆記
https://blog.stuffedcow.net/2019/09/hard-disk-geometry-microbenchmarking/
(自己的筆記經常找不到鏈接於是記錄一下) 通過 microbenchmarking 測量 LBA 間跳轉消耗的 seek time 來測量現代 hdd 上 LBA 的具體物理扇區映射關係。可以看出近現代硬盤上扇區佈局已經發展到傳統的柱面之類的概念沒有什麼實際意義了
fc fs筆記
A kernel without buffer heads https://lwn.net/SubscriberLink/930173/c288defca11561e8/
關了 buffer heads 支持會得到一個有 xfs btrfs 沒有 ext4 f2fs jfs ntfs3 fat 和 dm 的內核
https://www.vidarholen.net/contents/blog/?p=479 tl;dr: dd works for reading and writing disks, but it has no "low level I/O" capabilities that make it more suited for this than any other shell utility. Like cat you should use it where it makes sense, e.g. to take advantage of its wide array of options, rather than try to ensure that all disk related commands begin and end with dd out of fear and superstition.
https://lore.kernel.org/linux-btrfs/20231217165359.604246-1-hch@lst.de/ host-aware SMR hdd 從 SCSI / ATA 標準中刪掉了(NVMe 標準中沒有加過),今後就只會有 host-managed 和 device-managed SMR 了。 Linux 內核會把現存少量的 host-aware SMR 設備當作 device-managed SMR (OS 看來是普通的 HDD )用