Linux - GPT を使用した RAID1 アレイ上の不良ブロックの修復

Linux - GPT を使用した RAID1 アレイ上の不良ブロックの修復

要約: RAID1 アレイ内の 1 つのディスク上の不良ブロックを修復するにはどうすればよいでしょうか?

しかし、私がすでに試したことや私の方法に起こりうる間違いについては、この文章全体を読んでください。私はできる限り詳細に記述しようと努めました。そして、フィードバックを本当に期待しています。

私の状況は次のとおりです。 によって管理される RAID1 アレイに 2 台の 2TB ディスク (同じモデル) が設定されていますmdadm。約 6 か月前、SMART が報告した最初の不良ブロックに気付きました。今日、さらに多くのことに気付いたため、現在修正を試みています。

このHOWTOページSMART が報告する不良ブロックを修正するために、誰もがリンクしている唯一の記事のようです。これは素晴らしいページで、情報も満載ですが、かなり古く、私の特定の設定には対応していません。私の設定は次のように異なります。

  • 1 つのディスクの代わりに、RAID1 アレイで 2 つのディスクを使用しています。1 つのディスクはエラーを報告していますが、もう 1 つのディスクは正常です。HOWTO は 1 つのディスクのみを念頭に置いて書かれているため、「このコマンドはディスク デバイスで使用するのか、それとも 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 にあることがわかります。HOWTO に従って、gdisk を使用して、後でブロック番号を決定するときに使用する開始セクターを見つけます (fdisk は GPT をサポートしていないため使用できません)。

# 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ブロックが使用中かどうかを確認するように指示されています (EXT ファイルシステムが必要なため RAID デバイスを使用していますが、これは私を混乱させたコマンドの 1 つで、最初は /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ブロック番号に +-5 を繰り返し使用して、不良ブロックの周囲を検索します。すべて機能します。肩をすくめて、先に進み、書き込みと同期をコミットします (/dev/md0 を使用するのは、一方のディスクを変更してもう一方のディスクを変更しないと問題が発生する可能性があると考えたためです。この方法では、両方のディスクが不良ブロックを上書きします)。/dev/sda1/dev/sdb/dev/sdb1/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

振り出しに戻ります。つまり、RAID1 アレイ内の 1 つのディスク上の不良ブロックを修復するにはどうすればいいのでしょうか? 何かを正しく行っていないのは確かです...

お時間を割いていただき、ありがとうございます。


編集1:

長い SMART テストを実行してみましたが、同じ LBA が不良として返されました (唯一の違いは、残りが 90% ではなく 30% であると報告されることです)。

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

また、次の出力で badblocks も使用しました。出力は奇妙で、フォーマットが間違っているようですが、ブロックとして出力された数値をテストしようとしましたが、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。Current_Pending_Sector が 1 個、Offline_Uncorrectable が 0 個あります。

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

回答の 1 つによると、どうやら私は switchseekskipfor を実行したようですdd。HOWTO で使用されている seek を使用していました。このコマンドを使用するとddハングします: # dd if=/dev/sda1 of=/dev/null bs=4096 count=1 skip=401594986

その周辺のブロック (..84、..85、..87、..88) を使用すると問題なく動作するようです。401594986また、/dev/sdb1 をブロックと共に使用しても問題なく読み取れます (ディスクが SMART テストに合格したので予想どおり)。ここで疑問なのは、この領域に書き込んでブロックを再割り当てする場合、 と のどちらを使用すればよいか/dev/sda1ということ/dev/md0です。1 つのディスクに直接書き込んで他のディスクを更新しないことで、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

適切なデバイスをそこに配置する必要があります (例: mdX ではなく md0)。デフォルトでは配列全体を実行するため、これにはしばらく時間がかかります。十分に新しいカーネルでは、最初にセクター番号を 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 アレイでほぼ同じ問題に遭遇しました。不良セクタは、パーティションの 1 つの先頭、つまり /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)

この場合、データ オフセットは 512 バイトの 262144 セクターです。/dev/md0 から dd を実行して、オフセットが 131072K の raw パーティションのデータと比較すると、一致することがわかります。したがって、私の場合、/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 毎月第 1 日曜日に実行されます。修正不可能なハードウェア エラーが発生した場合は、書き換えを迅速に行うために手動で実行してください。

答え4

sw-raid1 があり、メンバーの 1 つに直接データを書き込むと、RAID がすぐに破損します。sdaX または sdbX が mdX の一部である場合は、データを書き込まないでください。mdX に書き込むと、両方のドライブにデータがコピーされますが、mdX から読み取ると、ドライブの 1 つからデータが読み取られます。

関連情報