HOWTO: Recover damaged FreeBSD UFS2 file systems with damaged master super-block
Copyright © Xin LI, 2006.
All Rights Reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
注意:本文介紹的方法部分,假定讀者對UFS文件系統,以及FreeBSD的日常操作相當熟悉;請勿輕易執行本文介紹的操作,本文中的操作,可能導致fsck_ffs(8)無法修正的嚴重問題。由於在此本人已明確告知讀者這一風險,據此,對於由於執行這些操作導致的任何數據損失,本人明示不承擔任何責任。
FreeBSD的UFS文件系統的布局結構,在設計時已經考慮到了磁盤立體結構上發生各種損壞的可能性。UFS考慮到了磁盤可能發生單軌、整柱面或整面磁盤的數據發生損毀的可能性。
一般而言,文件系統都需要保存帶有“索引”或“描述”性質的關鍵數據,通常這種數據也稱為“元數據”(metadata)。在UFS和UFS2文件系統中,這些元數據包括了超級塊(super-block)、柱面組記帳信息等。在UFS2文件系統中的每個超級塊大約需要占用3個扇區,它包含了對整個文件系統的描述性信息,因此對於文件系統而言,超級塊是非常重要的。在最初的FFS(Berkeley Fast File System,FreeBSD的UFS和UFS2文件系統,事實上是FFS的演化版本)設計中,為了使文件系統在遭到毀滅性打擊,如硬盤發生整軌、整面或全柱面損毀時能夠得以恢復,在文件系統初始化時,會將超級塊復制到整個磁盤的多個位置,以便在發生硬件損壞時能夠讀取。
有時,由於軟件或臨時性的硬件信號干擾,也會導致超級塊損壞。在文件系統掛載時,系統只會讀取主超級塊的內容;此處也會保存一些記帳信息。主超級塊在文件系統的生命周期內,會不斷地發生修改,以反映文件系統目前的狀態。為了確保備份的安全,備份超級塊不會跟進這些變動。在必要時,fsck_ffs(8)程序能夠根據磁盤上的其它元數據,重新計算應該應用到超級塊上的變動。
在FreeBSD中,對於損毀嚴重的主超級塊,系統會給出超級塊不正確的提示而拒絕掛載;fsck_ffs(8)在不指定使用備份超級塊時,也會出現類似的問題(我認為這是一個bug,在大約1994年的時候引入,如果有時間的話我會修正這個問題)。要在fsck_ffs的過程中指定使用哪個超級塊,可以使用fsck_ffs的-b參數來指定。
我個人建議,只要條件允許,在執行任何數據恢復操作之前,第一步是先將整個磁盤分區進行備份。在FreeBSD中,可以使用dd來完成這項任務。然後,所有的操作,都應在副本而不是正本上運行。如果正本屬於硬件損壞,特別是介質損毀,還應從副本復制副本來用於實際操作。
如何確定備份超塊的位置
對於UFS2而言,第一個備份超塊的位置,通常在該文件系統的第160扇區。如果之前沒有記錄超塊的其它備份的位置,可以用下列命令來得到:
newfs -N /dev/da0s1a
注意,如果在執行newfs時指定了任何其它參數,還需要一起指定。注意,-N是必須的,否則newfs將真的創建文件系統,並使恢復超塊不再可能。
這之後,可以嘗試使用fsck_ffs(8)來修復:
fsck_ffs -b 160 -fy /dev/da0s1a
對於損壞非常嚴重的文件系統,則不應使用前述操作,而應在確認備份超塊沒有問題的前提下,直接使用它來覆蓋。
下面的命令,能夠將位於/dev/da0s1a文件系統的備份超塊以類似debug的形式dump出來:
dd if=/dev/da0s1a iseek=160 bs=512 count=3 | hexdump -C
一定要仔細確認這個超塊沒有受到損毀!請參見 sys/ufs/ffs/fs.h 中定義的struct fs結構。
之後,首先備份現有的、占據超塊位置的數據。這一步並非嚴格必須,但很明顯,做事後諸葛亮是沒有意義的。對於UFS2文件系統,主超級塊的起點是文件系統的第128扇區(隨配置不同,這個值可能有所差異)。
dd if=/dev/da0s1a iseek=128 bs=512 count=3 of=bad_superblock
接下來,復制備份超塊到一個文件:
dd if=/dev/da0s1a iseek=160 bs=512 count=3 of=backup_superblock
最後,用該超塊覆蓋主超塊:
dd if=backup_superblock oseek=128 bs=512 count=3 of=/dev/da0s1a
由於統計信息均不正確,此時磁盤不應投入正常使用。由於我們首先要做的是修復數據,因此此時應以只讀方式掛載:
mount -ordonly /dev/da0s1a /mnt/
並從其中復制數據:
cd /mnt
find . -type f [其它條件] | tar cfT - - | tar xf - -C /recovery/
這之後,使用fsck_ffs(8)對其進行處理,可以進一步得到一些數據:
fsck -fy /dev/da0s1a
幾點需要注意的事情:
a) 掛接損壞的文件系統,有可能隨時導致內核以極其慘烈的方式崩潰。目前為止,我發現過的此類問題均已進行了修正,但很難說這類問題已經完全不存在。理想狀況下,應使用NFS掛接一個遠程的文件系統用於寫操作;每處理完一個損壞的文件系統,應重啟一次。
b) 損壞嚴重的文件系統會包含一個甚至大量損壞的柱面組信息。這些信息會使文件信息發生損壞。這種情況幾乎已經沒有可能修正數據了,在復制數據時,應剔除這些數據。
c) 前述操作必須非常小心進行。所有操作均可能導致fsck無法修正的問題。