あなたの天然記念物
ホーム更新雑談Perl鉄ゲタランドナーコースガイド自転車Linuxリンク経歴連絡先
Daily Full Backup (2006.01.23)

Amiga(=Amithlon)として使っているパソコンではRAID1が使えません。そこでAmigaを使い終わってLANからLinuxを起動した際にハー
ドディスクを1台まるごと別のハードディスクにバックアップすることにしました。通常側が故障したらバックアップ側と交換すれ
ばすぐ使えて便利です。
2006.01.23 オンボードのRAID1からAmithlonを起動することに成功しました。詳細は下記ページで。 AmithlonでRAID1
考えるのと実際にやってみるのはエラい違いがあって俗にいう経験というものはこういう所に現れてくるんだなぁと思いました。
いやぁー今回はキツかったです。その分は皆さんのお役に立てるとよいのですが。

通常側の容量は80GBありますけれど頭30GBしか使っていません。実は30GBのハードディスクから色々と移行した事情があります。
RAID1をしないのでバックアップ側に型番の異なるハードディスクを持って来れますからとりあえず30GBのハードディスクに戻しま
しょう。

dd cbs=512 count=60058656 if=/dev/hda of=/dev/hdb

/dev/hdaが80GBのほうで/dev/hdbが30GBのほうです。初っぱなからヤっちゃいましてコマンドddの仕様をよく知らないで使ってし
まったので間違えてました。正しくはたぶんこんな感じ。1文字の違いがまるで異なる動作になります。

dd bs=512 count=60058656 if=/dev/hda of=/dev/hdb

これで動作する(と思う)けれど性能面で非常によろしくないので末尾までよく読んでね。
30GBにコピーした後でAmigaを起動できることも確認してこれを通常側とします。バックアップ側には床に転がってる奴で良さそう
なのをと…。あ、同型のがあるじゃん(笑)。これに決定。30GBのコピーにエラい時間がかかってたので性能を上げることにします。
ハードディスクの性能と言えばPIOからDMAへの変更があります。さっそくやってみました。

hdparm -d1 /dev/hda

HDIO_SET_DMAが許可されていないそうです。メッセージにパーミッション(パーミットだっけ?)という単語が入っているのでファイ
ルシステムの0777と勘違いしてる人がいるけれど/dev/hdaを操作できるのはスーパユーザだからhdparmで/dev/hdaにアクセスしてエ
ラーにならない点からすでにスーパユーザだとわかります。

HDIO_SET_DMAの許可は0777のように設定するものではなくチップセットのドライバをカーネルに入れることで実現します。メッセー
ジを出す側は最終結果として「許可されない」になってるけどユーザから見れば「ドライバがありません。」がわかりやすいと思い
ます。ちなみに私はAmigaのユーザであってLinuxのユーザではありません。�BR>
私のPCはチップセットを趣味でVIAにしています。インテル用のドライバは最初からカーネルに入っているのですけれど

          VIA用のドライバは最初入っていないしオプションで追加もできません(RedHat7.3Jにて)

そこでVIAのホームページVIA ARENA(覚え方「VIA、アレな。」なんちて)からKernelのソースコード修正用パッチをダウンロードし
てソースコードを書き換えてからコンパイルしてブート用のフォルダにbzImageをコピーしました。起動してみるとハードディスク
内のパーティションをチェックした際にエラーが山ほど出てくるためIDE関係の余計(と思った)なオプションを削ったら無事起動で
きました。オプションを見ると「自動でDMAにする」という便利なのもあるので指定しておきます。うまくいけば/proc/ide/viaにド
ライバからの報告が出ます。

さてDMAにできたので性能を確認しましょう。

hdparm -t /dev/hda
hdparm -t /dev/hdb

おぉ。50MB/sだって。PIOなら5MB/sだから10倍速になりました。これなら10分ちょいでバックアップできそう。では実験。
ハードディスクが同型なのでコピーする量を指定しなくて済みます。

dd if=/dev/hda of=/dev/hdb

きっかり1分後にCtrl + Cで中止させてコピー量を確認します。あれれ?7MB/sしか出てなくて30GBのコピーに1時間13分かかるぞ。何
が起きた?うーん。(色々調べる)コマンドddでブロック長を指定しないから512Bになってddがボトルネックになってた。上の方法で
ハードディスクのまるごとコピーをするってIT関係のホームページに掲載しているライターはど素人だな。こんなの1度やれば問題
だとわかるものを検証しないで記事にするから。まぁ日本のパソコン関係のライターは中村正三郎さん以外信用できないのは常識で
すけどね。googleで「dd if=/dev/hda of=/dev/hdb」と検索すればすぐわかりますよ。くすくす。

さてブロック長をいくらにするとよいか考えてみよう。30GBを1ブロックとしてしまうと30GBをまるごとメモリに載せようとして入
らなくて失敗しそうだから30GBの約数の最大でメモリ1GBのLinuxに入りそうな程度にしよう。1セクタ512Bで60,058,656セクタある
から1セクタ=512Bがとりあえず約数と。セクタの倍数を見ていくと1ブロック32セクタ(=16KB)で1,876,833ブロックとなります。
ブロック数を見るとなんとなく素数のような気(未確認。あくまでも見ためで。)がするのでこれがブロック長の限界となります。
2005.12.31 案の定もっと大きくできますね。ハードディスクの構造を思い出したらシリンダの大きさの倍数だということに気がつきました。 このハードディスクは63セクタの16ヘッドだから1シリンダ=16×63=1,008セクタです。59,582シリンダをキリの良いシリンダ数で 分けるとすると2シリンダ29,791ブロックあたり(またもや未確認。29,791は素数かな?)。2シリンダ=32トラック=2,016セクタがブ ロック長の限界ですね。(なんかまた間違えてそう。)2,016セクタ=1,032,192B=1,008KBなのでホントはこんな感じ。 dd bs=1008k if=/dev/hda of=/dev/hdb 約数にする理由は/dev/hdaから読み込んだ際にキリが悪いと足りない分を読もうとしてエラーになりそうだから。なんとなく。そし
て/dev/hdbに書き込む際にも余計な分を書こうとしてエラーになるでしょ。ブロック長をきちんと検討しておくことでトラブルの芽
を摘んでおきます。そもそもハードディスクのコピーはトラブルの対策のためにやっているのだから対策でトラブル起こしちゃ本末
転倒ですよね。ボトルネックを解消したコピー方法はこんな感じ。

dd bs=16k if=/dev/hda of=/dev/hdb

性能を見ると30MB/s程度出ていて実際に30GBを17分でバックアップできました。調子に乗って二度三度とバックアップしていたら
バックアップ側の/dev/hdbがエラーを起こすようになりました。エラーが起きるセクタだけピンポイントで書き込んでみるとやっぱ
りエラーになってしまいます。こりゃ故障ですね。VIAのせいじゃないと良いのですけれど。別のハードディスク40GBをバックアッ
プ側にして同じセクタを書き込んでみると無事なので30GBのが故障と判定しました。バックアップ側の性能は30MB/sと遅いので別の
ケーブルにつけてバックアップ中は2本のケーブルをそれぞれ一方通行(厳密じゃないよ)で使って性能を上げることにしました。

今は倒産しちゃったパソコン屋さんの店長さんは「CD-ROMドライブを接続したIDEケーブルではUDMAはできません」と言ってたけど
/var/log/dmesgとか見る限りそんな挙動はなくて(だってCD-ROMドライブにさえDMAを設定しようとするんだもん。結局設定できない
けどね。)やってみたら普通にUDMAになってました。性能も34MB/sと1割増になったので15分で済みます。CD-ROMドライブとUDMAの件
は素人パソコンライターが何人も記事にしてそうです。暇があったらそんなライターを捜してみてください。くすくす。

さてバックアップの方法も確立したので全自動バックアップの方法としてスクリプトdupdisk.shに上のコマンドを入れて
/etc/rc/rc.localから起動させることにしました。一つ心配なのはハードディスクの入れ換えやバックアップ自体を忘れていて(な
んせ全自動だから)別の用途で取り付けて起動したら壊しちゃうことです。そこでハードディスクがいつもの型番と製造番号かチェ
ックしてからコピーするようにしてみました。スクリプトはこんな感じ。スクリプト名の「dup」はduplicateを略していて80欄の紙
カードをパンチするときにキーボードの「dup」を押している間は直前にパンチしたカード(まだホッパに出ていなくてパンチ機が読
み取られます)の内容を複製(=duplicate)してくれたのを思い出したので。

----------/root/dupdisk.sh----------
#!/bin/bash

echo start $0 `date`

HDD_ORG_DEV='/dev/hda'
HDD_ORG_OK=' Model=Maxtor 6E030L0, FwRev=NAR61590, SerialNo=E10FYERE'

HDD_DUP_DEV='/dev/hdc'
HDD_DUP_OK=' Model=MAXTOR 4K040H2, FwRev=A08.1500, SerialNo=572121419034'

HDD_ORG_ID=`hdparm -i $HDD_ORG_DEV | head --lines 4 | tail --lines 1`
echo $HDD_ORG_ID
if [ "$HDD_ORG_ID" != "$HDD_ORG_OK" ]; then
        echo 'Original disk has changed, cancel for copy.'
        exit
fi

HDD_DUP_ID=`hdparm -i $HDD_DUP_DEV | head --lines 4 | tail --lines 1`
echo $HDD_DUP_ID
if [ "$HDD_DUP_ID" != "$HDD_DUP_OK" ]; then
        echo 'Duplicate disk has changed, cancel for copy.'
        exit
fi

dd bs=16k if=$HDD_ORG_DEV of=$HDD_DUP_DEV

echo stop $0 `date`
--------------------
2005.12.31 実際にバックアップさせてみるとコンソールにコマンドddの結果が出るは起動中の表示のままバックアップ始めてlogin画面でな いはコピー時間が17分間かかるはで色々と改善しました。最大のポイントは「ブロックを大きくすりゃいいってもんじゃない。」 という所ですね。最短時間でコピーできたのは1ブロック8KBで17分38秒でした。最短といっても16KBより3秒間短かい程度です。 物理的なセクタの配置はハードディスクのファームウエアが徹底的に最適化してるでしょうからこれが限界かな。
----------/root/dupdisk.sh----------
#!/bin/bash

LOG_FILE='/root/dupdisk.log'

TIME_START=`date +"%s"`
echo start $0 `date` >>$LOG_FILE

HDD_ORG_DEV='/dev/hda'
HDD_ORG_OK=' Model=Maxtor 6E030L0, FwRev=NAR61590, SerialNo=E10FYERE'

HDD_DUP_DEV='/dev/hdc'
HDD_DUP_OK=' Model=MAXTOR 4K040H2, FwRev=A08.1500, SerialNo=572121419034'

HDD_ORG_ID=`hdparm -i $HDD_ORG_DEV | head --lines 4 | tail --lines 1`
echo Original disk : $HDD_ORG_ID >>$LOG_FILE
if [ "$HDD_ORG_ID" != "$HDD_ORG_OK" ]; then
        echo 'Original disk has changed, cancel for copy.' >>$LOG_FILE
        exit
fi

HDD_DUP_ID=`hdparm -i $HDD_DUP_DEV | head --lines 4 | tail --lines 1`
echo Duplicate disk: $HDD_DUP_ID >>$LOG_FILE
if [ "$HDD_DUP_ID" != "$HDD_DUP_OK" ]; then
        echo 'Duplicate disk has changed, cancel for copy.' >>$LOG_FILE
        exit
fi

dd bs=8k if=$HDD_ORG_DEV of=$HDD_DUP_DEV >>$LOG_FILE 2>&1

TIME_STOP=`date +"%s"`
TIME_SECONDS=$(($TIME_STOP - $TIME_START))
TIME_MINUTE=$(($TIME_SECONDS / 60))
TIME_SECOND=$(($TIME_SECONDS % 60))
TIME_RATE=$((29326 / $TIME_SECONDS))

echo Duplicate time $TIME_MINUTE minutes $TIME_SECOND seconds, $TIME_RATE MB/s. >>$LOG_FILE
echo stop $0 `date` >>$LOG_FILE
--------------------
実行結果はこんな感じ。
----------/root/dupdisk.log----------
start /root/dupdisk.sh Sat Dec 31 07:02:22 GMT+9 2005
Original disk : Model=Maxtor 6E030L0, FwRev=NAR61590, SerialNo=E10FYERE
Duplicate disk: Model=MAXTOR 4K040H2, FwRev=A08.1500, SerialNo=572121419034
3753666+0 records in
3753666+0 records out
Duplicate time 17 minutes 38 seconds, 27 MB/s.
stop /root/dupdisk.sh Sat Dec 31 07:20:00 GMT+9 2005
--------------------