一次調查centos 6.2上xfs文件係統宕機後文件數據丟失的經曆
阿裏雲每天都會接到大量的客戶工單,工單問題千奇百怪,不少問題調查起來頗費周折。下麵的這個問題很有意思,一開始我們以為是ECS的bug,導致用戶數據丟失,嚇出一身冷汗,後來發現問題出在操作係統。一次次與底層係統的交手,慢慢的讓阿裏雲的產品變得更加透明。
今天接到用戶工單,反饋說他的雲服務器發生了宕機遷移,奇怪的是遷移後部分文件長度變成0了,但是之前升級應用的時候確認過這些文件肯定是正常的。粗看現象確實比較奇怪,根據用戶提供的操作,可以抽象為向xfs文件係統上寫了一些文件數據,然後係統宕機。係統恢複後文件長度為0。 據此,我們編寫了一個複現腳本程序來模擬此問題。腳 本如下:
#!/bin/bash
dst=${1}
for ((i=1;i<=10000;i++)); do tmpfile=${dst}/file.$(date ‘+%T’).${i} echo ${tmpfile} dd if=/dev/zero of=${tmpfile} bs=1M count=8 &>/dev/null
done
該腳本通過dd(1)命 令在 指定的目錄下創建10000個8M大 小的文件用來模擬用戶的行為。在centos 6.2上(2.6.32-220.23.1) 上運行此腳本:
$ ./xfs-bug.sh ${XFS_MNT} # XFS_MNT為xfs文 件係統的掛載點
在持續運行一段時間,比如拷貝到2000+個 文件的時候我們強製係統重啟(sudo sh -c “echo b >/proc/sysrq-trigger”)。在 重啟 後我們會看到如下結果:
$ ls -l ${XFS_MNT} | less
total 15785984
-rw-rw-r– 1 wenqing.lz wenqing.lz 8388608 Mar 13 14:23 file.14:23:01.1
-rw-rw-r– 1 wenqing.lz wenqing.lz 8388608 Mar 13 14:23 file.14:23:01.10
-rw-rw-r– 1 wenqing.lz wenqing.lz 8388608 Mar 13 14:23 file.14:23:01.11
…
-rw-rw-r– 1 wenqing.lz wenqing.lz 8388608 Mar 13 14:24 file.14:24:35.1240
-rw-rw-r– 1 wenqing.lz wenqing.lz 45056 Mar 13 14:24 file.14:24:35.1241
-rw-rw-r– 1 wenqing.lz wenqing.lz 6373376 Mar 13 14:24 file.14:24:35.1242
-rw-rw-r– 1 wenqing.lz wenqing.lz 8388608 Mar 13 14:24 file.14:24:35.1243
-rw-rw-r– 1 wenqing.lz wenqing.lz 6311936 Mar 13 14:24 file.14:24:35.1244
…
-rw-rw-r– 1 wenqing.lz wenqing.lz 8388608 Mar 13 14:24 file.14:24:42.1304
-rw-rw-r– 1 wenqing.lz wenqing.lz 28672 Mar 13 14:24 file.14:24:42.1305
-rw-rw-r– 1 wenqing.lz wenqing.lz 8388608 Mar 13 14:24 file.14:24:42.1306
-rw-rw-r– 1 wenqing.lz wenqing.lz 77824 Mar 13 14:24 file.14:24:42.1307
-rw-rw-r– 1 wenqing.lz wenqing.lz 8388608 Mar 13 14:24 file.14:24:42.1308
-rw-rw-r– 1 wenqing.lz wenqing.lz 8388608 Mar 13 14:24 file.14:24:43.1309
…
-rw-rw-r– 1 wenqing.lz wenqing.lz 4198400 Mar 13 14:25 file.14:25:17.1596
-rw-rw-r– 1 wenqing.lz wenqing.lz 4198400 Mar 13 14:25 file.14:25:17.1597
-rw-rw-r– 1 wenqing.lz wenqing.lz 0 Mar 13 14:25 file.14:25:17.1598
-rw-rw-r– 1 wenqing.lz wenqing.lz 0 Mar 13 14:25 file.14:25:17.1599
…
-rw-rw-r– 1 wenqing.lz wenqing.lz 0 Mar 13 14:26 file.14:26:21.2146
-rw-rw-r– 1 wenqing.lz wenqing.lz 0 Mar 13 14:26 file.14:26:21.2147
-rw-rw-r– 1 wenqing.lz wenqing.lz 0 Mar 13 14:26 file.14:26:21.2148
-rw-rw-r– 1 wenqing.lz wenqing.lz 0 Mar 13 14:26 file.14:26:21.2149
可以看到,很多已經拷貝了2、3分鍾的文件的文件長度是不正確的,而很多文件的長度均為0。這一結果是不符合預期的。即操作係統在 用戶沒有執行sync(1)命令的情況下,會默認將超過30s的髒數據寫回磁盤。而這裏很多長度不對的文件的創建時間已經超過這 一時 間。 說明此腳本可以基本複現用戶的問題,並且2.6.32-220.23.1內核上的xfs確實存在缺陷。
根據搜索網上的相關信息,可以看到redhat針 對2.6.32-220內核上的xfs曾經修複過一個類似錯誤(https://rhn.redhat.com/errata/RHSA-2012-1401.html)。 我把相關說明粘貼在此:
“
* Under certain circumstances, a system crash could result in data loss on
XFS file systems. If files were created immediately before the file system
was left to idle for a long period of time and then the system crashed,
those files could appear as zero-length once the file system was remounted.
This occurred even if a sync or fsync was run on the files. This was
because XFS was not correctly idling the journal, and therefore it
incorrectly replayed the inode allocation transactions upon mounting after
the system crash, which zeroed the file size. This problem has been fixed
by re-instating the periodic journal idling logic to ensure that all
metadata is flushed within 30 seconds of modification, and the journal is
updated to prevent incorrect recovery operations from occurring.
(BZ#856685)
”
大意是說在某些特定條件下或者係統宕機後會造成xfs文件係統上文件數據的丟失(文件長度為0)。為了驗證此問題是否在後續版本中 已經得到修複,我們測試了最新的2.6.32-358.14.1內核。重複同樣的測試,我們得到了如下的 結 果:
$ ls -l ${XFS_MNT} | less
total 15982592
-rw-rw-r– 1 wenqing.lz wenqing.lz 8388608 Mar 13 14:39 file.14:39:11.1
-rw-rw-r– 1 wenqing.lz wenqing.lz 8388608 Mar 13 14:39 file.14:39:11.10
-rw-rw-r– 1 wenqing.lz wenqing.lz 8388608 Mar 13 14:39 file.14:39:11.11
…
-rw-rw-r– 1 wenqing.lz wenqing.lz 8388608 Mar 13 14:40 file.14:40:16.1019
-rw-rw-r– 1 wenqing.lz wenqing.lz 8388608 Mar 13 14:40 file.14:40:16.1020
-rw-rw-r– 1 wenqing.lz wenqing.lz 8388608 Mar 13 14:40 file.14:40:16.1021
-rw-rw-r– 1 wenqing.lz wenqing.lz 8388608 Mar 13 14:40 file.14:40:16.1022
…
-rw-rw-r– 1 wenqing.lz wenqing.lz 8388608 Mar 13 14:41 file.14:41:09.1513
-rw-rw-r– 1 wenqing.lz wenqing.lz 8388608 Mar 13 14:41 file.14:41:09.1514
-rw-rw-r– 1 wenqing.lz wenqing.lz 8388608 Mar 13 14:41 file.14:41:09.1515
…
-rw-rw-r– 1 wenqing.lz wenqing.lz 8388608 Mar 13 14:42 file.14:42:09.2067
-rw-rw-r– 1 wenqing.lz wenqing.lz 8388608 Mar 13 14:42 file.14:42:09.2068
-rw-rw-r– 1 wenqing.lz wenqing.lz 8388608 Mar 13 14:42 file.14:42:09.2069
-rw-rw-r– 1 wenqing.lz wenqing.lz 8388608 Mar 13 14:42 file.14:42:09.2070
…
-rw-rw-r– 1 wenqing.lz wenqing.lz 8388608 Mar 13 14:42 file.14:42:22.2187
-rw-rw-r– 1 wenqing.lz wenqing.lz 8388608 Mar 13 14:42 file.14:42:22.2188
-rw-rw-r– 1 wenqing.lz wenqing.lz 0 Mar 13 14:42 file.14:42:22.2189
可以看到,隻有最後一小部分文件的長度為0。 這一結果是符合預期的。可以說明在2.6.32-358內核中, 此問 題已經得到修複。 為了確認358內核上xfs確實修複了此問題,我們對比了358和220內 核的changlog。 對比中我們發現了幾個和XFS相關的補丁。 這裏一並列舉出來:
xfs: log the inode in ->write_inode calls for kupdate
xfs: log all dirty inodes in xfs_fs_sync_fs
根據xfs郵件列表裏的 記 錄,這兩個補丁是作為一個整體提交給社區的。我們知道Linux內 核 的髒數據回寫是由內核 writeback機製來保證的。第 一個補丁 的作用是修複xfs在Linux內 核嚐試回寫超過30s的 髒數據時的一個bug。即在此補丁 之前,有可能在某些條件下xfs無法正確回寫超過已經超過30s的 髒數據。此補丁是在xfs_fs_write_inode()函 數中 判 斷wbc->for_kupdate變量。而這 一變量在Linux kernel嚐試刷新超過30s髒 數據時會被置為1。 第二個補丁修複的則是由於Linux Kernel中writeback路 徑的修改引起的xfs回寫行為的不正常。根據描述,由於writeback路徑的修改造成 older_than_this變量的檢查更加嚴格,由此造成有可能被置髒的inode得不到回寫。這裏的 older_than_this恰恰是係統回寫超過30s髒 數據時判斷髒數據時間的標誌。
綜上可以基本確認這次用戶文件數據在宕機後的丟失是由於xfs文件係統中的一個缺陷造成的。
(本文作者是阿裏雲核心係統團隊的文卿。)
最後更新:2017-04-03 12:55:42