Try   HackMD

Playing with ext4


tags: linux

目錄


簡介

本文件記錄建立一個 ext4 檔案系統的過程和觀察其空間分配機制而進行的實驗。
使用 ubuntu 18.04 為作業系統,在 Transcend 64GB 隨身碟上建立一個 ext4 檔案系統。


建立 ext4

找到儲存裝置

第一步是找出用於建立 ext4 的儲存裝置,這邊使用的是隨身碟。

$ lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 465.8G 0 disk ├─sda1 8:1 0 300M 0 part ├─sda2 8:2 0 100M 0 part /boot/efi ├─sda3 8:3 0 128M 0 part ├─sda4 8:4 0 149.5G 0 part ├─sda5 8:5 0 95.4G 0 part / ├─sda6 8:6 0 95.4G 0 part /home ├─sda7 8:7 0 3.8G 0 part [SWAP] └─sda8 8:8 0 121.2G 0 part ... ... sdc 8:32 1 58.8G 0 disk #用作實驗的隨身碟

建立分區

然後可以使用 gdisk 分割出所需要的大小。gdisk 提供 GPT 分割,若需要使用 MBR 分割,可以使用 fdisk,兩者使用方法基本相同。

$ sudo gdisk /dev/sdc GPT fdisk (gdisk) version 1.0.3 Partition table scan: MBR: protective BSD: not present APM: not present GPT: present Found valid GPT with protective MBR; using GPT. Command (? for help):

使用 n 新增磁區,為減少 ext 的 group block 數量,只提供 200MB 的空間。

Command (? for help): n #新增磁區 Partition number (1-128, default 1): #使用預設 First sector (34-123207646, default = 2048) or {+-}size{KMGTP}: #起始 sector ,使用預設 Last sector (2048-123207646, default = 123207646) or {+-}size{KMGTP}: +200M #預設為使用所有空間,這邊改為使用 200MB Current type is 'Linux filesystem' Hex code or GUID (L to show codes, Enter = 8300): #使用預設,8300 是 Linux 檔案系統 Changed type of partition to 'Linux filesystem'

設定完成後可以使用 p 預覽分割結果,確認無誤後使用 w 實際開始分割。

Command (? for help): p#印出當前分割狀況 Disk /dev/sdc: 123207680 sectors, 58.8 GiB Model: Transcend 64GB Sector size (logical/physical): 512/512 bytes ... Number Start (sector) End (sector) Size Code Name 1 2048 411647 200.0 MiB 8300 Linux filesystem Command (? for help): w#確認進行以上操作

完成後再次使用lsblk即可發現新分割的磁區。

$ lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 465.8G 0 disk ... sdc 8:32 1 58.8G 0 disk └─sdc1 8:33 1 200M 0 part #新的分割區

格式化

此時分割區尚未進行格式化,使用mkfs格式化並設定 block size 為 4096 bytes,以最少化 block group 的數量。

$ sudo mkfs.ext4 -b 4096 /dev/sdc1#格式化為 ext4 mke2fs 1.44.1 (24-Mar-2018) ...

觀察和實驗

使用 dumpe2fs 吧!

此時 ext4 已建立完畢,使用 dumpe2fs 可觀察 ext4 的詳細資訊。如 Free blocks 的數量,建立時設定的 block size等。
其中 superblock, Group descriptors 等資料佔用了第 0-25 blocks,但 free blocks 並不是從 26 開始,而是 5732。

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

$ sudo dumpe2fs /dev/sdc1 dumpe2fs 1.44.1 (24-Mar-2018) Filesystem volume name: <none> ... Errors behavior: Continue Filesystem OS type: Linux Inode count: 51200 Block count: 51200 Reserved block count: 2560 Free blocks: 45442 Free inodes: 51189 First block: 0 Block size: 4096 #mkfs 中設定的 4096 block size Fragment size: 4096 Group descriptor size: 64 Reserved GDT blocks: 24 Blocks per group: 32768 Fragments per group: 32768 Inodes per group: 25600 Inode blocks per group: 800 ... Group 0: (Blocks 0-32767) csum 0x37d3 Primary superblock at 0, Group descriptors at 1-1 Reserved GDT blocks at 2-25 Block bitmap at 26 (+26), csum 0x32cade1f Inode bitmap at 28 (+28), csum 0x004f98e0 Inode table at 30-829 (+30) 27036 free blocks, 25589 free inodes, 2 directories, 25589 unused inodes Free blocks: 5732-32767 #並不是從 26 開始 Free inodes: 12-25600 Group 1: (Blocks 32768-51199) csum 0x360c [INODE_UNINIT] Backup superblock at 32768, Group descriptors at 32769-32769 Reserved GDT blocks at 32770-32793 Block bitmap at 27 (bg #0 + 27), csum 0x20557c35 Inode bitmap at 29 (bg #0 + 29), csum 0x00000000 Inode table at 830-1629 (bg #0 + 830) 18406 free blocks, 25600 free inodes, 0 directories, 25600 unused inodes Free blocks: 32794-51199 Free inodes: 25601-51200

清空檔案及資料夾

這時候先觀察一下 ext4 內的檔案,發現格式化時預留了一塊lost+found的空間,總共佔用 16384 bytes。

$ ls -las total 24 4 drwxrwxrwx 3 root root 4096 . 4 drwxr-x---+ 4 root root 4096 .. 16 drwxrwxrwx 2 root root 16384 lost+found

移除掉lost+found

$ rm -rf ./lost+found $ ls -las total 8 4 drwxrwxrwx 3 root root 4096 . 4 drwxr-x---+ 4 root root 4096 ..

再次使用 dumpe2fs,因為

40964=16384 bytes,即lost+found應該佔用 4 個 blocks。移除lost+foundGroup 0也空出 4 個 blocks,符合預期。
然而無法得知被佔用的 1635-5731 blocks 的具體用途,應為維持 ext4 運作的保留區域。

$ sudo dumpe2fs /dev/sdc1 dumpe2fs 1.44.1 (24-Mar-2018) ... Group 0: (Blocks 0-32767) csum 0x9296 [ITABLE_ZEROED] ... 27040 free blocks, 25590 free inodes, 1 directories, 25589 unused inodes Free blocks: 1631-1634, 5732-32767 #空出來 4 個 blocks 了 Free inodes: 11-25600 Group 1: (Blocks 32768-51199) csum 0xc745 [INODE_UNINIT, ITABLE_ZEROED] ... 18406 free blocks, 25600 free inodes, 0 directories, 25600 unused inodes Free blocks: 32794-51199 Free inodes: 25601-51200

空間分配方式

為了得知 ext4 分配空間的方式,以下對 ext4 進行多種不同的寫入、刪除操作並進行觀察。


排除 last freed first

為 ext4 建立檔案。

$ echo "hello" >> ./1.txt

再次觀察 ext4。
新的檔案佔用了最前面的 data block 及 inode。
在使用 group 0 的 inode 的同時。
使用了 group 1 的 data block 而不是 group 0 的 data block。

$ sudo dumpe2fs /dev/sdc1 dumpe2fs 1.44.1 (24-Mar-2018) ... Group 0: (Blocks 0-32767) csum 0x595d [ITABLE_ZEROED] ... 27040 free blocks, 25589 free inodes, 1 directories, 25589 unused inodes Free blocks: 1631-1634, 5732-32767 Free inodes: 12-25600 #11 被佔用了! Group 1: (Blocks 32768-51199) csum 0x29cc [INODE_UNINIT, ITABLE_ZEROED] ... 18405 free blocks, 25600 free inodes, 0 directories, 25600 unused inodes Free blocks: 32795-51199 #32794 被佔用了! Free inodes: 25601-51200

繼續建立檔案並觀察。系統持續使用 group 0 最前面的 inode 和 group 1 最前面的 data block。
此時可以確認並不是使用 last freed first 的空間分配機制。

$ echo "hello" >> ./2.txt $ echo "hello" >> ./3.txt $ echo "hello" >> ./4.txt $ echo "hello" >> ./5.txt $ sudo dumpe2fs /dev/sdc1 dumpe2fs 1.44.1 (24-Mar-2018) ... Group 0: (Blocks 0-32767) csum 0x595d [ITABLE_ZEROED] ... 27040 free blocks, 25585 free inodes, 1 directories, 25585 unused inodes Free blocks: 1631-1634, 5732-32767 Free inodes: 16-25600 #12-15 被佔用了! Group 1: (Blocks 32768-51199) csum 0x29cc [INODE_UNINIT, ITABLE_ZEROED] ... 18401 free blocks, 25600 free inodes, 0 directories, 25600 unused inodes Free blocks: 32799-51199 #32795-32798 被佔用了! Free inodes: 25601-51200

排除 least recently used first, next unused first, Last in first out

2.txt, 3.txt, 4.txt的順序移除檔案,再建立6.txt並觀察。
此時發現,6.txt會佔用最前面的 inode 和 data block。而不是最後被刪除的4.txt所佔用的 data block (last in first out 機制)。或5.txt後面的空間(next unused first, least recently used first 機制)。
至此可以確認並不是使用 last freed first, least recently used first 或 next unused first 的空間分配機制。

$ rm 2.txt $ rm 3.txt $ rm 4.txt $ sudo dumpe2fs /dev/sdc1 dumpe2fs 1.44.1 (24-Mar-2018) ... Group 0: (Blocks 0-32767) csum 0x595d [ITABLE_ZEROED] ... 27040 free blocks, 25587 free inodes, 1 directories, 25585 unused inodes Free blocks: 1631-1634, 5732-32767 Free inodes: 13-14, 16-25600 #13 被佔用了! Group 1: (Blocks 32768-51199) csum 0x29cc [INODE_UNINIT, ITABLE_ZEROED] ... 18403 free blocks, 25600 free inodes, 0 directories, 25600 unused inodes Free blocks: 32796-32797, 32799-51199 #32795 被佔用了! Free inodes: 25601-51200

判別 first fit, best fit

經過以上的觀察後,基本可以確定 ext4 是使用 first unused 機制。但尚未得知是根據 first fit 還是 best fit。

為此進行建立及刪除檔案的操作,產生一個 2 個連續 free data blocks 在前,1 個連續 free data block 在後的結構。

$ sudo dumpe2fs /dev/sdc1 dumpe2fs 1.44.1 (24-Mar-2018) ... Group 0: (Blocks 0-32767) csum 0x595d [ITABLE_ZEROED] ... 27040 free blocks, 25586 free inodes, 1 directories, 25583 unused inodes Free blocks: 1631-1634, 5732-32767 Free inodes: 13-14, 16, 18-25600 Group 1: (Blocks 32768-51199) csum 0x29cc [INODE_UNINIT, ITABLE_ZEROED] ... 18402 free blocks, 25600 free inodes, 0 directories, 25600 unused inodes Free blocks: 32796-32797, 32799, 32801-51199 # 32796-32797 在前,32799 在後 Free inodes: 25601-51200

再次建立一個佔用 1 block size 的檔案,並觀察 data block 的使用狀況。
結果是在後方的單一 data block 被優先使用了,可見 ext4 是使用 best fit 機制。

$ echo "hello" >> ./11.txt $ sudo dumpe2fs /dev/sdc1 dumpe2fs 1.44.1 (24-Mar-2018) ... Group 0: (Blocks 0-32767) csum 0x595d [ITABLE_ZEROED] ... 27040 free blocks, 25585 free inodes, 1 directories, 25583 unused inodes Free blocks: 1631-1634, 5732-32767 Free inodes: 14, 16, 18-25600 Group 1: (Blocks 32768-51199) csum 0x29cc [INODE_UNINIT, ITABLE_ZEROED] ... 18401 free blocks, 25600 free inodes, 0 directories, 25600 unused inodes Free blocks: 32796-32797, 32801-51199 #32799 被佔用了! Free inodes: 25601-51200

結論

ext4 是使用 first best fit 的 data block 分配機制。
值得思考的是,ext4 是屬於索引式檔案系統,資料碎片化對效能影響較小,卻依然選擇速度較慢但資料碎片化較少的 best fit 機制,而不是速度更快但碎片化嚴重的 first fit 機制。這可能是考量 ext4 的 inode 有提供 extend 機制,可以使用單一的指標結構表示多個連續的 data block,。有較多連續的空間時,用於表示 data block 的指標數量就會減少,使用到 inode 的雙重,甚至三重指標的機率就會下降,此時理論效能則會獲得提升。
順帶一提,inode 的分配是采用單純的 first unused 機制,因為每個檔案只會使用一個 inode,因此不存在 best fit 和 first fit 的差別。