mdadm 修復單一區塊/磁區

mdadm 修復單一區塊/磁區

我想建立一個 NAS,使用 mdadm 進行 RAID,使用 btrfs 進行 bitrot 檢測。我有一個相當基本的設置,將 3 個 1TB 磁碟與 mdadm 組合成 RAID5,然後再使用 btrfs。

我知道 mdadm 無法修復 bitrot。它只能告訴我何時存在不匹配,但它不知道哪些數據是正確的,哪些數據是錯誤的。當我在模擬 bitrot 後告訴 mdadm 修復我的 md0 時,它總是會重建奇偶校驗。 Btrfs 使用校驗和,因此它知道哪些數據有錯誤,但它無法修復數據,因為它看不到奇偶校驗。

不過,我可以執行 btrfs 清理並讀取系統日誌以取得與其校驗和不匹配的資料的偏移量。然後我可以將此偏移量轉換為磁碟和該磁碟上的偏移量,因為我知道 md0 的資料起始偏移量(2048 * 512)、區塊大小(512K)和佈局(左對稱)。該佈局意味著在我的第一層中,奇偶校驗位於第三個磁碟上,第二層中位於第二個磁碟上,第三層中位於第一個磁碟上。

結合所有這些資料和更多關於磁碟格式的 btrfs 知識,我可以準確計算出哪個磁碟的哪個區塊有問題。但是,我找不到告訴 mdadm 修復這個特定區塊的方法。

我已經編寫了一個腳本,使用dd 命令交換奇偶校驗和錯誤塊,然後使用mdadm 啟動修復,然後將它們交換回來,但這不是一個好的解決方案,我真的希望mdadm 將此扇區標記為壞扇區,不要再使用它。既然它開始腐爛,它很可能會再次腐爛。

我的問題是:有沒有辦法告訴 mdadm 修復單一區塊(不是奇偶校驗),甚至可能將磁碟區標記為壞磁區?也許會產生讀取 io 錯誤?

(我知道 ZFS 可以自己完成所有這一切,但我不想使用 ECC 記憶體)

編輯:問題/答案是關於 btrfs RAID6 如何不穩定以及 ZFS 如何更加穩定/可用。這並沒有解決我關於如何使用 mdadm 修復單一已知錯誤區塊的問題。

答案1

我找不到告訴 mdadm 修復這個特定區塊的方法。

這是因為當出現靜默資料損壞時,md 沒有足夠的資訊來知道哪個區塊被靜默損壞。

我邀請你閱讀我的在此回答問題#4(“為什麼md繼續使用具有無效資料的設備?”),它更詳細地解釋了這一點。

讓你提議的佈局變得更糟,如果奇偶校驗區塊遭受靜默資料損壞,上面的 Btrfs 層將看不到它! 當具有相應資料塊的磁碟發生故障並且您嘗試更換它時,md 將使用損壞的奇偶校驗並不可逆轉地損壞您的資料。只有當該磁碟發生故障時,Btrfs 才會識別出損壞,但您已經遺失了資料。

這是因為除非陣列降級,否則 md 不會讀取奇偶校驗區塊。


那麼有沒有辦法告訴 mdadm 修復單一區塊(不是奇偶校驗),甚至可能將磁碟區標記為壞磁區?也許會產生讀取 io 錯誤?

對於硬碟本身發現的壞道,md可以輕鬆處理,因為壞道是由md識別的。

從技術上講,您可以使用 來建立壞扇區hdparm --make-bad-sector,但是您如何知道哪個磁碟的區塊受到靜默資料損壞的影響?

考慮這個簡化的例子:

奇偶校驗公式:PARITY = DATA_1 + DATA_2

+--------+--------+--------+
| DATA_1 | DATA_2 | PARITY |
+--------+--------+--------+
|      1 |      1 |      2 | # OK
+--------+--------+--------+

現在讓我們用 值悄悄地破壞每個區塊3

+--------+--------+--------+
| DATA_1 | DATA_2 | PARITY |
+--------+--------+--------+
|      3 |      1 |      2 | # Integrity failed – Expected: PARITY = 4
|      1 |      3 |      2 | # Integrity failed – Expected: PARITY = 4
|      1 |      1 |      3 | # Integrity failed – Expected: PARITY = 2
+--------+--------+--------+

如果您沒有第一個表可供查看,您如何知道哪個區塊已損壞?
你無法確定。

這就是為什麼 Btrfs 和 ZFS 都是校驗和區塊。它需要更多的磁碟空間,但這些額外的資訊可以讓儲存系統找出哪個區塊在撒謊。

Jeff Bonwick 的部落格文章“RAID-Z”

每當您讀取 RAID-Z 區塊時,ZFS 都會將其與其校驗和進行比較。如果資料磁碟沒有回傳正確的答案,ZFS 會讀取奇偶校驗,然後進行組合重建以找出哪個磁碟回傳了錯誤資料。

要在 md 上使用 Btrfs 執行此操作,您必須嘗試重新計算每個區塊,直到 Btrfs 中的校驗和匹配為止,這是一個耗時的過程,沒有向使用者/腳本公開簡單的介面。


我知道 ZFS 可以自己完成所有這一切,但我不想使用 ECC 內存

ZFS 和 Btrfs over md 都不依賴甚至不知道 ECC 記憶體。 ECC 記憶體僅捕獲記憶體中的靜默資料損壞,因此它與儲存系統無關。

我之前在 RAID-5 和 RAID-6 推薦使用 ZFS 而不是 Btrfs(分別類似於 ZFS RAID-Z 和 RAID-Z2)Btrfs 優於 mdadm raid6?當 ATA 停止回應時,md RAID 中的裝置發生故障,但我想藉此機會概述一下 ZFS 的更多優點:

  • 當 ZFS 偵測到靜默資料損壞時,會立即自動當場修正,無需任何人為幹預。
  • 如果您需要重建整個磁碟,ZFS 將僅「重新同步」實際數據,而不是不必要地在整個區塊裝置上運行。
  • ZFS 是邏輯磁碟區和檔案系統的一體化解決方案,這使其管理起來比 md 之上的 Btrfs 更簡單。
  • RAID-Z 和 RAID-Z2 可靠且穩定,與
    • md RAID-5/RAID-6 上的Btrfs,僅對無提示損壞的資料塊提供錯誤檢測(加上無提示損壞的奇偶校驗塊可能無法檢測到,直到為時已晚),並且沒有簡單的方法進行錯誤修正,以及
    • Btrfs RAID-5/RAID-6,其中“存在多個嚴重的資料遺失錯誤」。
  • 如果我使用 ZFS RAID-Z2 悄悄損壞整個磁碟,我將不會丟失任何數據,而在 md RAID-6 上,我實際上丟失了 455,681 個索引節點

答案2

我找到了一種為 mdadm 創建讀取錯誤的方法。

使用 dmsetup,您可以從表格建立邏輯設備。

設備是透過載入一個表格來建立的,該表指定每個磁區的目標(512 位元組)

從:線上說明頁

在這些表中,您可以指定應傳回 IO 錯誤的偏移量,例如:

0 4096 linear /dev/sdb 0
4096 1 error
4097 2093055 linear /dev/sdb 4097

這將會建立一個在偏移量 4096*512 處有錯誤的裝置 (1GB)。

相關內容