運維同事回報:24 TB XFS 備份分區明顯剩餘 2.4 TB 空間、inode 使用率僅 1%,卻在寫入新檔案時拋出 No space left on device 錯誤。經排查,罪魁禍首是 **XFS 預設 32 位元 inode 模式將所有 inode 強制集中在分區前 1 TB 區域**,導致前 1 TB inode 表耗盡而資料區仍大量閒置。本文深度解析成因、驗證方法與 inode64 掛載選項徹底解決方案。
[root@imysql ~]# df -hT /backup
Filesystem Type Size Used Avail Use% Mounted on
/dev/sdb1 xfs 19T 16T 2.4T 88% /backup
[root@imysql ~]# df -hi /backup
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/sdb1 9.3G 3.4M 9.3G 1% /backup
空間與 inode 總量均顯示充足,但實際寫入失敗。
XFS 預設採用 32 位元 inode 編號(inode32),為了相容舊版 32 位元 userspace(如舊版 NFS client、32 位元 stat()),**將所有 inode 分配在檔案系統前 1 TB 空間(AG 0–AG N)**。
# 查看 AG (Allocation Group) 分佈與 inode 使用
xfs_db -r -c 'agf' /dev/sdb1 | head -20
# 或使用 xfs_info 觀察 agcount、agsize
xfs_info /backup
若輸出顯示 agcount=4 且 agsize 對應前 1 TB 範圍,即確認 inode 侷限於前段。
inode64 讓 XFS 使用 64 位元 inode 編號,**inode 可分佈於整個檔案系統任意位置(靠近其資料區塊)**,徹底消除前 1 TB 瓶頸,同時減少磁碟尋道延遲。
mount -o remount,inode64,noatime,nodiratime,nobarrier /dev/sdb1 /backup
注意: remount 僅改變掛載選項,**不會自動遷移既有 inode 位置**;既有檔案 inode 仍留在前 1 TB,新檔案將分散分配。若需徹底重新分佈,需備份資料、重新 mkfs.xfs、還原資料。
/dev/sdb1 /backup xfs defaults,noatime,nodiratime,inode64,nobarrier 0 0
重新掛載或重開機後生效。
| 場景 | 建議 | 說明 |
|---|---|---|
| 分區 < 1 TB | 無需啟用 | 預設 inode32 覆蓋全分區,無瓶頸 |
| 分區 > 1 TB,大量小檔案 | 必須啟用 inode64 | 避免 inode 耗盡假象,提升效能 |
| 分區 > 1 TB,大檔案為主 | 建議啟用 | 雖 inode 壓力小,但分散分佈減少尋道 |
| 透過 NFS 匯出給 32 位元客戶端 | 謹慎評估 | 極舊 32 位元 NFS client 可能無法正確處理 64 位元 inode 編號(現代 64 位元客戶端無問題) |
| 使用 32 位元應用程式直接 stat() 本地檔案 | 極罕見 | 現代發行版預設 64 位元 userspace,stat64 系統呼叫支援 64 位元 inode |
xfs_quota -x -c 'report -p' /backup 檢查專案配額;repquota 檢查使用者/群組配額。realtime 子卷,df -h 不顯示即時區使用量,需 xfs_info 確認。ENOSPC,執行 xfs_fsr 線上去碎片緩解。XFS inode64 是大容量分區(>1 TB)的**必加掛載選項**。它不僅解決「空間明明足卻報滿」的經典誤報,更透過 inode 就近分佈降低中繼資料操作延遲。現代 64 位元 Linux 環境下,**預設應啟用 inode64**,僅在極罕見 32 位元相容場景考慮保留 inode32。建議將 inode64 納入基礎架構標準化模板(Ansible role、Kickstart、cloud-init),從源頭杜絕此類隱性故障。
