TL;DR:我該如何修復 RAID1 陣列中 1 個磁碟上的壞區塊?
但請閱讀整篇文章,了解我已經嘗試過的內容以及我的方法中可能出現的錯誤。我已經盡力盡可能詳細,我真的希望得到一些回饋
這是我的情況:我有兩個 2TB 磁碟(相同型號)設置在由mdadm
.大約 6 個月前,當 SMART 報告它時,我注意到第一個壞塊。今天我注意到了更多,現在正在努力解決它。
本指南頁面似乎是每個人都連結到修復 SMART 報告的壞塊的一篇文章。這是一個很棒的頁面,充滿了信息,但是它相當過時,並且不能解決我的特定設置。這是我的配置的不同之處:
- 我在 RAID1 陣列中使用兩個磁碟,而不是一個磁碟。一個磁碟報告錯誤,而另一個則正常。 HOWTO 只考慮了一個磁碟,這會帶來各種問題,例如「我在磁碟裝置還是 RAID 裝置上使用此命令」?
- 我使用的是 GPT,fdisk 不支援。我一直在使用 gdisk,我希望它能給我我需要的相同信息
那麼,讓我們開始吧。這就是我所做的,但它似乎不起作用。請隨時仔細檢查我的計算和方法是否有錯誤。報錯的磁碟為/dev/sda:
# smartctl -l selftest /dev/sda
smartctl 5.42 2011-10-20 r3458 [x86_64-linux-3.4.4-2-ARCH] (local build)
Copyright (C) 2002-11 by Bruce Allen, http://smartmontools.sourceforge.net
=== START OF READ SMART DATA SECTION ===
SMART Self-test log structure revision number 1
Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error
# 1 Short offline Completed: read failure 90% 12169 3212761936
由此,我們得出錯誤位於 LBA 3212761936 上。
# gdisk -l /dev/sda
GPT fdisk (gdisk) version 0.8.5
Partition table scan:
MBR: protective
BSD: not present
APM: not present
GPT: present
Found valid GPT with protective MBR; using GPT.
Disk /dev/sda: 3907029168 sectors, 1.8 TiB
Logical sector size: 512 bytes
Disk identifier (GUID): CFB87C67-1993-4517-8301-76E16BBEA901
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 3907029134
Partitions will be aligned on 2048-sector boundaries
Total free space is 2014 sectors (1007.0 KiB)
Number Start (sector) End (sector) Size Code Name
1 2048 3907029134 1.8 TiB FD00 Linux RAID
使用tunefs
我發現塊大小為4096
。使用此資訊和 HOWTO 中的計算,我得出結論,有問題的區塊是((3212761936 - 2048) * 512) / 4096 = 401594986
。
然後,HOWTO 指示我debugfs
查看該區塊是否正在使用(我使用 RAID 設備,因為它需要 EXT 檔案系統,這是令我困惑的命令之一,因為我一開始不知道是否應該使用 / dev/sda 或/dev /md0):
# debugfs
debugfs 1.42.4 (12-June-2012)
debugfs: open /dev/md0
debugfs: testb 401594986
Block 401594986 not in use
所以塊 401594986 是空的,我應該可以毫無問題地重寫它。不過,在寫入之前,我試著確保它確實無法被讀取:
# dd if=/dev/sda1 of=/dev/null bs=4096 count=1 seek=401594986
1+0 records in
1+0 records out
4096 bytes (4.1 kB) copied, 0.000198887 s, 20.6 MB/s
如果無法讀取該區塊,我不希望它起作用。然而,確實如此。我重複使用/dev/sda
、/dev/sda1
、/dev/sdb
、/dev/sdb1
、/dev/md0
和 +-5 到區塊號碼來搜尋壞區塊。這一切都有效。我聳聳肩,繼續提交寫入和同步(我使用 /dev/md0 因為我認為修改一個磁碟而不是另一個可能會導致問題,這樣兩個磁碟都會覆蓋壞區塊):
# dd if=/dev/zero of=/dev/md0 bs=4096 count=1 seek=401594986
1+0 records in
1+0 records out
4096 bytes (4.1 kB) copied, 0.000142366 s, 28.8 MB/s
# sync
我希望寫入壞區塊會使磁碟將區塊重新分配給好區塊,但是執行另一個 SMART 測試會顯示不同的結果:
# 1 Short offline Completed: read failure 90% 12170 3212761936
回到方塊 1 那麼基本上,我該如何修復 RAID1 陣列中 1 個磁碟上的壞區塊?我確信我沒有做正確的事...
感謝您的時間和耐心。
編輯1:
我嘗試運行一個長時間的 SMART 測試,相同的 LBA 返回為錯誤(唯一的區別是它報告剩餘 30%,而不是 90%):
SMART Self-test log structure revision number 1
Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error
# 1 Extended offline Completed: read failure 30% 12180 3212761936
# 2 Short offline Completed: read failure 90% 12170 3212761936
我還使用了帶有以下輸出的壞塊。輸出很奇怪,似乎格式錯誤,但我嘗試測試作為區塊輸出的數字,但 debugfs 給出錯誤
# badblocks -sv /dev/sda
Checking blocks 0 to 1953514583
Checking for bad blocks (read-only test): 1606380968ne, 3:57:08 elapsed. (0/0/0 errors)
1606380969ne, 3:57:39 elapsed. (1/0/0 errors)
1606380970ne, 3:58:11 elapsed. (2/0/0 errors)
1606380971ne, 3:58:43 elapsed. (3/0/0 errors)
done
Pass completed, 4 bad blocks found. (4/0/0 errors)
# debugfs
debugfs 1.42.4 (12-June-2012)
debugfs: open /dev/md0
debugfs: testb 1606380968
Illegal block number passed to ext2fs_test_block_bitmap #1606380968 for block bitmap for /dev/md0
Block 1606380968 not in use
不知道從這裡去哪裡。badblocks
肯定發現了一些東西,但我不確定如何處理所提供的資訊...
編輯2
更多命令和資訊。
我覺得自己像個白痴,忘記了最初包含這一點。這是 的 SMART 值/dev/sda
。我有 1 個 Current_Pending_Sector 和 0 個 Offline_Un Correctable。
SMART Attributes Data Structure revision number: 16
Vendor Specific SMART Attributes with Thresholds:
ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE
1 Raw_Read_Error_Rate 0x002f 100 100 051 Pre-fail Always - 166
2 Throughput_Performance 0x0026 055 055 000 Old_age Always - 18345
3 Spin_Up_Time 0x0023 084 068 025 Pre-fail Always - 5078
4 Start_Stop_Count 0x0032 100 100 000 Old_age Always - 75
5 Reallocated_Sector_Ct 0x0033 252 252 010 Pre-fail Always - 0
7 Seek_Error_Rate 0x002e 252 252 051 Old_age Always - 0
8 Seek_Time_Performance 0x0024 252 252 015 Old_age Offline - 0
9 Power_On_Hours 0x0032 100 100 000 Old_age Always - 12224
10 Spin_Retry_Count 0x0032 252 252 051 Old_age Always - 0
11 Calibration_Retry_Count 0x0032 252 252 000 Old_age Always - 0
12 Power_Cycle_Count 0x0032 100 100 000 Old_age Always - 75
181 Program_Fail_Cnt_Total 0x0022 100 100 000 Old_age Always - 1646911
191 G-Sense_Error_Rate 0x0022 100 100 000 Old_age Always - 12
192 Power-Off_Retract_Count 0x0022 252 252 000 Old_age Always - 0
194 Temperature_Celsius 0x0002 064 059 000 Old_age Always - 36 (Min/Max 22/41)
195 Hardware_ECC_Recovered 0x003a 100 100 000 Old_age Always - 0
196 Reallocated_Event_Count 0x0032 252 252 000 Old_age Always - 0
197 Current_Pending_Sector 0x0032 100 100 000 Old_age Always - 1
198 Offline_Uncorrectable 0x0030 252 100 000 Old_age Offline - 0
199 UDMA_CRC_Error_Count 0x0036 200 200 000 Old_age Always - 0
200 Multi_Zone_Error_Rate 0x002a 100 100 000 Old_age Always - 30
223 Load_Retry_Count 0x0032 252 252 000 Old_age Always - 0
225 Load_Cycle_Count 0x0032 100 100 000 Old_age Always - 77
# mdadm -D /dev/md0
/dev/md0:
Version : 1.2
Creation Time : Thu May 5 06:30:21 2011
Raid Level : raid1
Array Size : 1953512383 (1863.01 GiB 2000.40 GB)
Used Dev Size : 1953512383 (1863.01 GiB 2000.40 GB)
Raid Devices : 2
Total Devices : 2
Persistence : Superblock is persistent
Update Time : Tue Jul 3 22:15:51 2012
State : clean
Active Devices : 2
Working Devices : 2
Failed Devices : 0
Spare Devices : 0
Name : server:0 (local to host server)
UUID : e7ebaefd:e05c9d6e:3b558391:9b131afb
Events : 67889
Number Major Minor RaidDevice State
2 8 1 0 active sync /dev/sda1
1 8 17 1 active sync /dev/sdb1
根據答案之一:看來我確實切換了seek
和skip
for dd
。我使用的是 find ,因為這就是 HOWTO 所使用的。使用此指令會導致dd
掛起: # dd if=/dev/sda1 of=/dev/null bs=4096 count=1skip=401594986
使用該區塊周圍的區塊(..84、..85、..87、..88)似乎運作得很好,使用 /dev/sdb1 和區塊401594986
讀取也很好(正如預期的那樣,該磁碟通過了SMART 測試) )。現在,我的問題是:當在該區域上寫入以重新分配區塊時,我是否使用/dev/sda1
或/dev/md0
?我不想直接寫入一個磁碟而不更新另一個磁碟,從而導致 RAID 陣列出現任何問題。
編輯3
寫入區塊會直接產生檔案系統錯誤。我選擇了一個可以快速解決問題的答案:
# 1 Short offline Completed without error 00% 14211 -
# 2 Extended offline Completed: read failure 30% 12244 3212761936
感謝所有提供幫助的人。 =)
答案1
坦白說,所有這些「刺激產業」的答案都是瘋狂的。他們面臨(可能是隱藏的)檔案系統損壞的風險。如果資料已經消失了,因為該磁碟儲存了唯一的副本,這是合理的。但鏡子上有一個完美的副本。
您只需要讓 mdraid 擦洗鏡子即可。它會注意到壞扇區,並自動重寫它。
# echo 'check' > /sys/block/mdX/md/sync_action # use 'repair' instead for older kernels
您需要在其中放置正確的設備(例如,md0 而不是 mdX)。這將需要一段時間,因為預設情況下它會處理整個陣列。在足夠新的核心上,您可以先將磁區號寫入sync_min/sync_max,以將其限制為僅數組的一部分。
這是一個安全的操作。您可以在所有 mdraid 裝置上執行此操作。事實上,你應該定期在所有 mdraid 裝置上執行此操作。您的發行版可能附帶一個 cronjob 來處理這個問題,也許您需要做一些事情來啟用它?
適用於系統上所有 RAID 設備的腳本
不久前,我編寫了這個腳本來「修復」系統上的所有 RAID 裝置。這是為較舊的核心版本編寫的,其中只有“修復”才能修復壞扇區;現在只需進行檢查就足夠了(修復在較新的核心上仍然可以正常工作,但它也會重新複製/重建奇偶校驗,這並不總是您想要的,尤其是在閃存驅動器上)
#!/bin/bash
save="$(tput sc)";
clear="$(tput rc)$(tput el)";
for sync in /sys/block/md*/md/sync_action; do
md="$(echo "$sync" | cut -d/ -f4)"
cmpl="/sys/block/$md/md/sync_completed"
# check current state and get it repairing.
read current < "$sync"
case "$current" in
idle)
echo 'repair' > "$sync"
true
;;
repair)
echo "WARNING: $md already repairing"
;;
check)
echo "WARNING: $md checking, aborting check and starting repair"
echo 'idle' > "$sync"
echo 'repair' > "$sync"
;;
*)
echo "ERROR: $md in unknown state $current. ABORT."
exit 1
;;
esac
echo -n "Repair $md...$save" >&2
read current < "$sync"
while [ "$current" != "idle" ]; do
read stat < "$cmpl"
echo -n "$clear $stat" >&2
sleep 1
read current < "$sync"
done
echo "$clear done." >&2;
done
for dev in /dev/sd?; do
echo "Starting offline data collection for $dev."
smartctl -t offline "$dev"
done
如果你想代替check
,repair
那麼這個(未經測試的)第一個塊應該可以工作:
case "$current" in
idle)
echo 'check' > "$sync"
true
;;
repair|check)
echo "NOTE: $md $current already in progress."
;;
*)
echo "ERROR: $md in unknown state $current. ABORT."
exit 1
;;
esac
答案2
我剛剛在 RAID1 陣列上遇到了幾乎相同的問題。壞磁區位於其中一個分割區的開頭 - /dev/sdb2 的第 16 區。我按照上面的說明進行操作:在驗證檔案系統未使用邏輯區塊 2 並小心地以正確的方式進行 dd 查找和跳過之後,並將 1 個檔案系統區塊歸零:
# dd if=/dev/zero of=/dev/md0 bs=4096 count=1 seek=2
這是做什麼的?它沒有修復壞扇區。我現在知道,這是因為 /dev/md0 沒有直接對應到 /dev/sdb2,您必須考慮 RAID 資料偏移!下面詳細介紹這一點。它所做的只是我的文件系統上的一個小但可能具有毀滅性的糞便。事實證明 /dev/md0 的邏輯區塊 2 包含有用的檔案系統元數據,並且在兩個磁碟上都很好,直到我拉屎了兩個都透過寫入 /dev/md0 進行複製。幸運的是, e2fsck -y /dev/md0 解決了這個問題(在發出大量驚人的輸出之後),沒有明顯的資料遺失。經驗教訓:如果 debugfs icheck 顯示“未找到區塊”,並不一定意味著相應的磁區未被使用。
回到資料偏移量:使用 mdadm 找出偏移量,如下所示:
# mdadm --examine /dev/sdb2
/dev/sdb2:
Magic : a92b4efc
Version : 1.2
Feature Map : 0x0
Array UUID : ef7934b9:24696df9:b89ff03e:b4e5a05b
Name : XXXXXXXX
Creation Time : Sat Sep 1 01:20:22 2012
Raid Level : raid1
Raid Devices : 2
Avail Dev Size : 1953241856 (931.38 GiB 1000.06 GB)
Array Size : 976620736 (931.38 GiB 1000.06 GB)
Used Dev Size : 1953241472 (931.38 GiB 1000.06 GB)
Data Offset : 262144 sectors
Super Offset : 8 sectors
State : clean
Device UUID : f3b5d515:446d4225:c2191fa0:9a9847b8
Update Time : Thu Sep 6 12:11:24 2012
Checksum : abb47d8b - correct
Events : 54
Device Role : Active device 0
Array State : AA ('A' == active, '.' == missing)
在本例中,資料偏移量為 262144 個磁區,每區 512 位元組。如果您從 /dev/md0 進行 dd 並將其與偏移量為 131072K 的原始分割區中的資料進行比較,您會發現它們相符。因此,就我而言,/dev/sdb2 的邏輯區塊 2(磁區 16--23)甚至不在檔案系統中;它們位於 RAID 超級區塊中,您可以在此處閱讀: https://raid.wiki.kernel.org/index.php/RAID_superblock_formats- 對於版本 1.2,它由 256 位元組 + 陣列中每個裝置 2 位元組組成,全部從 4096 位元組開始,所以在我的例子中,沒有使用壞磁區。 /dev/sdc2(RAID1 陣列的另一半)的相應扇區為零,因此我認為這樣做是安全的:
# dd if=/dev/zero of=/dev/sdb2 bs=4096 count=1 seek=2
有效!
答案3
如果運行 debian,您很可能在 /etc/cron.d/mdadm 中有一份工作。這將/usr/share/mdadm/checkarray --cron --all --idle --quiet
在每個月的第一個星期日運行。當出現無法修正的硬體錯誤時,手動執行該錯誤以加快重寫速度。
答案4
如果您有 sw-raid1 並且直接將資料寫入其中一個成員,您將立即獲得損壞的 raid。如果 sdaX 或 sdbX 是 mdX 的一部分,請勿將資料寫入其中。如果您寫入 mdX,您會將資料複製到兩個驅動器,如果您從 mdX 讀取,您將從其中一個驅動器讀取資料。