天天看點

一次調查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曾經修複過一個類似錯誤(http://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核心。重複同樣的測試,我們得到了如下的 結 果:

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檔案系統中的一個缺陷造成的。

(本文作者是阿裡雲核心系統團隊的文卿。)

繼續閱讀