landisk 改造メモ


IODATAのNAS HDLPシリーズ(HDLP-G***, HDLP-S***, HDL2-G**) は内部でLinux が動いている。ファームウェアを少々改造することで、ログインが可能となり、 コンパクト大容量なLinux マシンとして使うことができるようになる。
ここでは、HDLPシリーズをLinuxマシンとして使う手順等を書いていく。

CONTENTS


1. ログイン可能化

まずはログインできるようにすることが不可欠ですが、やりかたは、 「あーそーだったのか」「超簡単にHDLP-S500の sshを起動する方法 [HDLP-S]」を参考にしてください。

2. 共有ファイルコピー(読み出し)が失敗する問題について

私が使っているHDLP-G320とHDL2-G2.0は、共有フォルダからPCへファイルをコ ピー(読み出し)していると、よく途中でエラーで止まってしまうということが あって困っていた。(エクスプローラでコピーしていると「XXXX をコピーでき ません。指定されたネットワーク名は利用できません。」というダイアログが 出る。なぜかNASへの書き込みのときは失敗しない)
調べていくと、どうもlandiskのTCPの再送(RTOタイムアウト後の再送) があま り行われていないようで、パケロスがあってもなかなか再送がなされない場合 があり、運が悪いとクライアント側PCのSMBがTCPコネクションを切断してしま うようだった。
いろいろ調べて、TCPのRTOタイムアウト後の再送をしやすくするパッチを作った。
パッチをインストールするには、NASにログインして、
# perl hack_tcp_hdls.pl
patch installed.
パッチをアンインストールするには、
# perl hack_tcp_hdls.pl -u
patch uninstalled.
とする。動いているカーネルにパッチを当てるので、NASを再起動したらま た実行する必要がある。
HDLP-G*** のfirmware 1.16 と、HDL2-G** のfirmware 1.11に当たることを確 認した。このシリーズのlandisk(linux-2.6.15を使っているもの)なら他の ファームウェアバージョンにも当たるのではないかと思うが試せてはいない。
私の環境ではこれでファイル読み出しが失敗しなくなったように思う。
downloadhack_tcp_hdls.zip

このパッチは何をしているのか
linux-2.6.15 の net/ipv4/tcp_output.c のtcp_retransmit_skb()の先頭にあ るif文(★印のガード条件)をNOPでつぶしています。/dev/kmem でカーネルの メモリに直接NOPを書き込んでいます。このif文にひっかかって、再送が起き ないように思えたので。こんなことしていいのかどうかよくわからないけ ど。。。
int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
{
        struct tcp_sock *tp = tcp_sk(sk);
        unsigned int cur_mss = tcp_current_mss(sk, 0);
        int err;

        /* Do not sent more than we queued. 1/4 is reserved for possible
         * copying overhead: fragmentation, tunneling, mangling etc.
         */
      ★if (atomic_read(&sk->sk_wmem_alloc) >
            min(sk->sk_wmem_queued + (sk->sk_wmem_queued >> 2), sk->sk_sndbuf))
                return -EAGAIN;
        :
}

2. HDLP HDD交換

ある日、突然NAS(HDLP-G320)が使えなくなった。電源を抜いて再起動したところ、 dmesg(の起動ログ)に次のメッセージがあった。
hdb: dma_timer_expiry: dma status == 0x45
hdb: DMA interrupt recovery
hdb: lost interrupt
hdb: dma_intr: status=0x51 { DriveReady SeekComplete Error }
hdb: dma_intr: error=0x40 { UncorrectableError }, LBAsect=614262308, high=36, low=10282532, sector=614262300
ide: failed opcode was: unknown
end_request: I/O error, dev hdb, sector 614262300
hdb: dma_intr: status=0x51 { DriveReady SeekComplete Error }
hdb: dma_intr: error=0x40 { UncorrectableError }, LBAsect=614262308, high=36, low=10282532, sector=614262308
ide: failed opcode was: unknown
end_request: I/O error, dev hdb, sector 614262308
なにやらエラーが出ている様子。
まだしばらく使えるかもしれないが、壊れないうちにHDDを交換することにし た。ついでに容量を1TBにアップする。

新しいHDDをUSBでつなぎ、初期化スクリプト(tar2disk)を改造してシステ ムを新HDDに複製する。

HDLP-* HDD交換手順
  1. 空のHDDを接続
    用意したHDDは Western Digital WD10JPVT 1.0TB。
    2.5インチHDDをUSBにつなぐHDDケース的なものを使って、landisk 本体に接続 する。USBバスパワーだと電源容量が足りないかもしれないので、電源付の USB-HUB経由でつないだ方がよいかもしれない。
    私の環境では、/dev/sda として認識された。
    # cat /sys/block/sda/size
    1953525168

  2. 作業用ディレクトリの準備
    どこかに作業用ディレクトリを作る。たとえば、/mnt/hda6/disk/kanso
    # mkdir /mnt/hda6/disk/kanso
    # cd /mnt/hda6/disk/kanso/
    # mkdir mnt
    # cp /boot/.landisk/tar2disk .
    # ls -l
    drwxrwxrwx  1 nobody nobody    4096 2012-10-20 11:35 mnt
    -rwxrwxrwx  1 nobody nobody   20106 2012-10-20 11:34 tar2disk

  3. tar2diskスクリプトの修正
    tar2diskを公開するのは差し障りがあるかもしれないので、修正差分だけを ここ(tar2disk.diff.ed.zip)に置く。これをDLして、zipを展開し て、landiskに置いて、差分を適用する。
    # md5sum tar2disk 
    f5f0d9365c1032f09edd6e73631e5caf  tar2disk
    # ed tar2disk <tar2disk.diff.ed
    # ls -l
    drwxrwxrwx 1 nobody nobody     0 2012-10-21 19:55 mnt/
    -rwxrwxrwx 1 nobody nobody 20511 2012-10-21 12:51 tar2disk
    -rwxrwxrwx 1 nobody nobody  1330 2012-10-21 19:55 tar2disk.diff.ed
    # md5sum tar2disk
    5616609d2547166b61fb7202cf306669  tar2disk
    ちなみに、オリジナルのtar2diskのmd5の値が上記と違う場合(そういうこと があるのかどうかわからないが)、差分が正しく適用できないと思う。その場 合は、firmwareのバージョンを上げるとよいかも。

    tar2diskを公開するのは差し障りがあるかもしれないので、修正差分だけを ここ(tar2disk.diff.zip)に置く。これをDLして、zipを展開し て、landiskに置いて、差分を適用する。
    patchを持っていない人のためにpatchも同梱しておく。(debianのpackageか ら持ってきたバイナリです)
    # ls -l
    drwxrwxrwx 1 nobody nobody     0 2012-10-21 19:55 mnt/
    -rwxrwxrwx 1 nobody nobody 91956 2012-12-15 11:57 patch
    -rwxrwxrwx 1 nobody nobody 20106 2012-10-21 12:44 tar2disk
    -rwxrwxrwx 1 nobody nobody  2340 2012-10-21 12:53 tar2disk.diff
    # ./patch tar2disk <tar2disk.diff
    patching file tar2disk
    # ls -l
    drwxrwxrwx 1 nobody nobody     0 2012-10-21 19:55 mnt/
    -rwxrwxrwx 1 nobody nobody 91956 2012-12-15 11:57 patch
    -rwxrwxrwx 1 nobody nobody 20511 2012-10-21 12:51 tar2disk
    -rwxrwxrwx 1 nobody nobody  2340 2012-10-21 12:53 tar2disk.diff
    -rwxrwxrwx 1 nobody nobody 20106 2012-10-21 12:44 tar2disk.orig
    ちなみに、ある方からメールをもらったところでは、tar2diskにはバージョ ン違いがあるようだ。バージョンが異なってもpatchが差分を当てるよう努力 する。
    # ls -l
    -rwxrwxrwx 1 nobody nobody 18856 2012-12-15 10:59 tar2disk
    # ./patch tar2disk <tar2disk.diff 
    patching file tar2disk
    Hunk #5 succeeded at 394 (offset -8 lines).
    Hunk #6 succeeded at 611 (offset -7 lines).
     <中略>
    Hunk #14 succeeded at 752 (offset -38 lines).
    Hunk #15 succeeded at 765 (offset -38 lines).
    #
    上記のような Hunk 〜 メッセージが出た場合、出来上がったtar2diskがどう なっているかは、私はわからず、未検証です。
    # ./patch tar2disk <tar2disk.diff 
    patching file tar2disk
    Hunk #3 FAILED at 399.
    Hunk #4 succeeded at 608 (offset -7 lines).
    Hunk #5 succeeded at 635 (offset -7 lines).
     <中略>
    Hunk #10 succeeded at 746 with fuzz 1 (offset -38 lines).
    Hunk #11 succeeded at 762 (offset -38 lines).
    1 out of 11 hunks FAILED -- saving rejects to file tar2disk.rej
    # ls -l *.rej
    -rw-rw-rw- 1 nobody nobody   423 2012-12-15 17:22 tar2disk.rej
    上記のように失敗してrejectファイルが生成された場合は、パッチが当たって いないのであきらめてください。

  4. tar2diskスクリプトを実行
    引数にはUSBに接続したdiskのデバイス名を指定する。
    ちなみに、修正前のオリジナルのtar2diskを実行すると、本体のHDDが消去 されてしまうと思うので注意すること。
    # ./tar2disk sda
        :
        :
    + umount ./mnt
    + break
    + '[' 0 -ne 0 ']'
    + exit 0
    #
    このスクリプトは、以下のことを行う。 ちゃんとdiskが構築できたか確認する。
    # mount /dev/sda1 mnt
    # ls mnt
    # umount mnt
    # mount /dev/sda2 mnt
    # ls mnt
    # umount mnt
    # mount /dev/sda5 mnt
    # ls mnt
    # umount mnt
    # mount -t ufsd /dev/sda6 mnt
    # ls mnt
    # umount mnt
    なお、オリジナルのtar2diskでは、setmaxコマンドでSET_MAX_ADDR的なこと をしているが、USB diskに対してはsetmaxが動作しなかったため、コメントア ウトしている。setmaxで何をしようとしているのか、それをしないとどんな影 響があるのかは不明。

  5. HDD換装
    shutdownし、HDDを交換する。本体の分解方法は、nana1451さんの「たぶん日記」 が詳しい。

    WD10JPVT に交換したHDLP-G320 と 元の MK3255GSX

  6. 完了
    電源を入れるとそれまでと同じ設定で立ち上がるはず。
    # df
    Filesystem           1K-blocks      Used Available Use% Mounted on
    rootfs                  396623    237799    154728  61% /
    /dev/root               396623    237799    154728  61% /
    tmpfs                    30412       808     29604   3% /mnt/tmpfs
    tmpfs                    30412         0     30412   0% /lib/init/rw
    tmpfs                    30412         0     30412   0% /dev/shm
    /dev/hdb1               303432    146772    153528  49% /boot
    /dev/hdb5               196271     15961    169868   9% /mnt/hda5
    /dev/hdb6            970663364  55513764 915149600   6% /mnt/hda6
補足
ちなみに、この後、firmware を 1.16から1.18にバージョンアップしたが、 普通に成功したっぽい。
ちなみに、HDLP-S* でも同じ手順が使えると思う。
トップページはこちら
Last modified: Sat Dec 15 17:37:24 JST 2012