RAIDのsuperblockを編集して壊れたハードディスクをRAIDに参加させる荒療治

Ubuntu LinkStation

Windows10からアクセスしているうちに、壊れてしまったLinkStation。

前回はphysical sector boundaryの警告メッセージを無視する所まで書きました。

今回は、いよいよRAID5デバイスの再構築です。
基本的にmdadmを使って認識させるだけですが、私の場合はすんなり行きませんでしたので、長文となります。
ご容赦ください。

作業概要

作業内容は、前回こちら↓で行ったことの上級編となっています。
LinkStationのハードディスクをRAID5の最低本数で読めるようにする方法

この時は4本のうち3本を認識させ、デグレードモードで復活させました。

ところが、ハードディスクの損傷が大きく、サルベージすることが出来なかったため、以下の手順を目指します。

1. 物理的に壊れているハードディスクはDisk Copyで新品に移し替える
2. 3本より4本の方が救えるファイルが多いと信じて、4本でRAID5を再起動させる ← イマココ!
3. ファイルシステムチェックをかけて不良セクタを除外させる
4. フォルダにマウントさせる
5. データをサルベージする

では、1つ1つ行っていきます。

mdadmの入手

Disk Copyは終わって、パソコン立ち上げも終わっていますので、RAID5への組み込みです。

まずソフトウェアのインストール

# apt-get -y install mdadm

これで、RAID用のコマンドmdadmが使えるようになりました。

Disk1のsuperblock確認

次に組み込む4本のハードディスクのRAID状態の表示を行っていきます。
まずは1本目です。
これは「superblock」と呼ばれる情報です。

# mdadm --examine /dev/sda6
/dev/sda6:
          Magic : a92b4efc
        Version : 0.90.00
           UUID : 82ca5ba8:77319326:bd54f990:2edf8a42
  Creation Time : Sun Jun 21 17:07:49 2009
     Raid Level : raid5
  Used Dev Size : 968759552 (923.88 GiB 992.01 GB)
     Array Size : 2906278656 (2771.64 GiB 2976.03 GB)
   Raid Devices : 4
  Total Devices : 3
Preferred Minor : 2

    Update Time : Sun Dec 27 07:06:56 2015
          State : clean
 Active Devices : 3
Working Devices : 3
 Failed Devices : 1
  Spare Devices : 0
       Checksum : 69d8d2ef - correct
         Events : 26

         Layout : left-symmetric
     Chunk Size : 64K

      Number   Major   Minor   RaidDevice State
this     0       8        6        0      active sync   /dev/sda6

   0     0       8        6        0      active sync   /dev/sda6
   1     1       0        0        1      faulty removed
   2     2       8       38        2      active sync   /dev/sdc6
   3     3       8       54        3      active sync   /dev/sdd6

1本目は正常に見えます。Events番号が26番です。

Disk2のsuperblock確認

次に2本目を検査します。

# mdadm --examine /dev/sdb6
/dev/sdb6:
          Magic : a92b4efc
        Version : 0.90.00
           UUID : 82ca5ba8:77319326:bd54f990:2edf8a42
  Creation Time : Sun Jun 21 17:07:49 2009
     Raid Level : raid5
  Used Dev Size : 968759552 (923.88 GiB 992.01 GB)
     Array Size : 2906278656 (2771.64 GiB 2976.03 GB)
   Raid Devices : 4
  Total Devices : 3
Preferred Minor : 2

    Update Time : Tue Dec 15 19:06:21 2015
          State : clean
 Active Devices : 3
Working Devices : 3
 Failed Devices : 0
  Spare Devices : 0
       Checksum : 69c9a9a0 - correct
         Events : 20

         Layout : left-symmetric
     Chunk Size : 64K

      Number   Major   Minor   RaidDevice State
this     1       8       22        1      active sync   /dev/sdb6

   0     0       0        0        0      removed
   1     1       8       22        1      active sync   /dev/sdb6
   2     2       8       38        2      active sync   /dev/sdc6
   3     3       8       54        3      active sync   /dev/sdd6

こちらもcleanになっており3本syncしていますが、Events番号が20番です。

Disk3のsuperblock確認

続いて3本目のsuperblockを確認します。

# mdadm --examine /dev/sdc6
/dev/sdc6:
          Magic : a92b4efc
        Version : 0.90.00
           UUID : 82ca5ba8:77319326:bd54f990:2edf8a42
  Creation Time : Sun Jun 21 17:07:49 2009
     Raid Level : raid5
  Used Dev Size : 968759552 (923.88 GiB 992.01 GB)
     Array Size : 2906278656 (2771.64 GiB 2976.03 GB)
   Raid Devices : 4
  Total Devices : 3
Preferred Minor : 2

    Update Time : Sun Dec 27 07:06:56 2015
          State : clean
 Active Devices : 3
Working Devices : 3
 Failed Devices : 1
  Spare Devices : 0
       Checksum : 69d8d313 - correct
         Events : 26

         Layout : left-symmetric
     Chunk Size : 64K

      Number   Major   Minor   RaidDevice State
this     2       8       38        2      active sync   /dev/sdc6

   0     0       8        6        0      active sync   /dev/sda6
   1     1       0        0        1      faulty removed
   2     2       8       38        2      active sync   /dev/sdc6
   3     3       8       54        3      active sync   /dev/sdd6

3本目も大丈夫そうです。1本目の結果と似ています。
Events番号は26番です。

Disk4のsuperblock確認

最後の1本を確認します。

# mdadm --examine /dev/sdd6
/dev/sdd6:
          Magic : a92b4efc
        Version : 0.90.00
           UUID : 82ca5ba8:77319326:bd54f990:2edf8a42
  Creation Time : Sun Jun 21 17:07:49 2009
     Raid Level : raid5
  Used Dev Size : 968759552 (923.88 GiB 992.01 GB)
     Array Size : 2906278656 (2771.64 GiB 2976.03 GB)
   Raid Devices : 4
  Total Devices : 3
Preferred Minor : 2

    Update Time : Sun Dec 27 07:06:56 2015
          State : clean
 Active Devices : 3
Working Devices : 3
 Failed Devices : 1
  Spare Devices : 0
       Checksum : 69d8d325 - correct
         Events : 26

         Layout : left-symmetric
     Chunk Size : 64K

      Number   Major   Minor   RaidDevice State
this     3       8       54        3      active sync   /dev/sdd6

   0     0       8        6        0      active sync   /dev/sda6
   1     1       0        0        1      faulty removed
   2     2       8       38        2      active sync   /dev/sdc6
   3     3       8       54        3      active sync   /dev/sdd6
# 

4本のsuperblockの表示結果を比較すると、

Events : 26

になっているハードディスクと

Events : 20

になっているハードディスクがいます。

これだと4本が1つのRAID5デバイスに組み込まれません。4本とも同じイベント番号じゃないと同じARRAYに組み込めないルールです。

RAIDのsuperblockをhackプログラムで編集

そこでRAIDのsuperblockを無理矢理書き換える、荒療治を実行します。

この荒療治、実際にやったことのある人は少なく、こちら↓のページが我々にとっての神ページとなっています。

無理やりのRAID復旧 | おごちゃんの雑文

おごちゃんに感謝!です。私もこのページ内にあるraidzap.cを使わさせて頂きました!

こちら↓の方も、おごちゃんのプログラムソースの利用者で、詳しく解説されています。

TeraStationのRAID5で2本HDDが壊れた際のデータ復旧に関して。 | spacewalker

プログラムは使いたい内容に沿って修正する必要があります。

このプログラムの中で、do_repair() という関数を環境に合わせて書き換えるのですが、私の場合、かなり行を追加して、以下のようにしています。

        char    *dev = "/dev/sdb6";     /* repair disk */
        char    *devt = "/dev/sda6";    /* other safe disk */

~<中略>~

        if ( super->md_magic == MD_SB_MAGIC ) {
                super = (mdp_super_t *)buff;
                super->this_disk.state = 6;
                i = super->this_disk.number = 1;
                super->disks[0].raid_disk = 0;
                super->disks[i].raid_disk = 1;
                super->disks[0].number = 0;
                super->disks[i].number = 1;
                super->disks[0].state = 6;
                super->disks[i].state = 6;
                super->events_hi = events_hi;
                super->events_lo = events_lo;
                super->sb_csum = calc_sb_csum(super);
                lseek64(fd,y,SEEK_SET);
                write(fd,buff,MD_SB_BYTES);
        } else {

オリジナルでは編集する自身のパーティション、例えば /dev/sdb6 なら super->this_disk.number = 1 にあたる情報のみを、他のパーティション(上記では/dev/sda6)からコピーする形で superblock を修復するように作られています。

修正箇所周辺のプログラムコードを見たい方は、こちらからどうぞ。

しかし、superblockには他のRAIDメンバーのdisk情報についても以下のように記載されています。

      Number   Major   Minor   RaidDevice State
this     1       8       22        1      active sync   /dev/sdb6

   0     0       0        0        0      removed
   1     1       8       22        1      active sync   /dev/sdb6
   2     2       8       38        2      active sync   /dev/sdc6
   3     3       8       54        3      active sync   /dev/sdd6

私が今回やりたいのは、この Disk Number = 0 の行にも情報を入れ、active sync であると騙すことです。

そこで、super->disk[0] の各パラメタにも値を書き込んでいます。そうすると、

      Number   Major   Minor   RaidDevice State
this     1       8       22        1      active sync   /dev/sdb6

   0     0       0        0        0      active sync
   1     1       8       22        1      active sync   /dev/sdb6
   2     2       8       38        2      active sync   /dev/sdc6
   3     3       8       54        3      active sync   /dev/sdd6

このように書き換わります。あとは *devt から *dev に Events 番号もコピーされますので、1本だけ同期が外れていた、私のようなケースでも、このプログラムで基本、復旧可能です。
4本がほぼほぼ同じ情報になれば、RAIDプログラムが簡単に騙せるようになります(笑)。

あと、compiler は必ず gcc を使う必要があります。
make コマンドで標準 cc で compile したら上手く動きませんでした。

あとは、パラメタ無しで ./raidzap と実行するのは止めてください。core dump します。
使い方は以下の通り、必ずパラメタを付けて実行します。

raidzap -l /dev/sdb6 で superblock の表示
raidzap -s /dev/sdb6 で superblock をファイルに保存
raidzap -r で *dev に指定したDiskの superblock を書き換え

私の場合は2本目の /dev/sdb6 を書き換えたかったので *dev に指定しているわけです。

RAID5への再組み込み

raidzapによる書き換えが終わったら、RAID5 の restart です。

# mdadm --stop /dev/md2
# mdadm -A /dev/md2 /dev/sd[abcd]6
mdadm: device 1 in /dev/md2 has wrong state in superblock, but /dev/sdb6 seems ok
mdadm: /dev/md2 has been started with 4 drives.

#

/dev/sdb6 seems ok と出てますね(笑)。
これで騙せました。
まさに無理矢理。
4本の完全RAID5状態に復活です。

だいぶ、希望が出てきましたね。
次はRebuild、Repairと続きます。引き続きお読み下さい。
↓続きの記事
RAIDのRebuild(再計算)が進まない時の対処法【Ubuntu, RAID5】

Windows10にアップグレードしたら、LinkStationのHDDが壊れてEMモードにすらならずにハマってしまったけれど、Linuxの機能を駆使して完全復旧させた私の体験の一部始終を読みたい方は、以下の記事から進んで下さい。

故障したLinkStationから自力でデータ復旧した方法

コメント

  1. kabotya より:

    大変参考になりましたが、コードが良くわからないので、もしよろしければテキストファイルなど公開して頂けないでしょうか

    • fujimori より:

      コメントありがとうございます!
      元のプログラムに著作権がありますので、プログラム全体を公開することは出来ないのですが、私が修正した部分だけで良ければ、テキストでダウンロード出来るようにします。
      どうでしょうか?

      • kabotya より:

        大変助かります。

        何処をどう書き足せば良いかわからず、少しでもヒントを頂けることを感謝いたします。

        よろしくおねがいします!

        • kabotya より:

          お世話になっております。

          コードのDLはどちらから出来るようになりましたでしょうか。

          急かすようで申し訳ないのですが、よろしくおねがいします。

          • fujimori より:

            ちょっと体調を崩しており返信が遅れました。
            本文中にプログラムコードへのリンクを追加しておきましたのでご確認下さい!

  2. kabotya より:

    ありがとうございます。
    お体大事にされてください。

タイトルとURLをコピーしました