2013年7月28日日曜日

unknown disk partitionの調査

先日、Touro 4TBを、partprobeでパーティションを認識させて、マウントするようにしたが、そもそも、unknown disk partitionとなる原因を調査。

推定1
HDDではないが、USBメモリで、unknown disk partitionの対策をしたページを見つけた。
http://blog.kmckk.com/archives/2846188.html
セクタ0をHDDからDMAで読み込み、キャッシュをinvalidateするが、キャッシュのラインサイズのアライメントが合っていないため、CPUがライト・バックして、DMA転送いたデータ(マジックナンバー)を上書き、このデータを参照したmsdos_partionが、マジックナンバー不正と判定し、check_partionに1を返し、unknown disk partitionとなっている様。

良くわからなかったので、[1]を読んでみた。

kernel sourceを読んでみようと調べた。
このとき、クロスコンパイルを簡潔にまとめたページがあったので貼っておく。[2]
ソースコードを読むのに、バージョン間比較、識別子へのハイパーリンクが貼られていて、便利なページがあった。[3] LXRというソフトを使っている様。

参考

[1]キャシュは諸刃の剣、DMA対応と言われたら、
http://www.uquest.co.jp/embedded/learning/lecture.html

[2]
http://senta.s112.xrea.com/senta/Tips/000/8a/index.html

[3]
http://lxr.free-electrons.com/source/

2013年7月26日金曜日

ls-qlに4TB USB Touro接続 (4)

起動スクリプト仕上げ

hotplug.shとtouro_mount.shの実行をrcSに追加。

/usr/local/bin/share_delete.sh & 
/etc/init.d/hotplug.sh start
/etc/init.d/touro_mount.sh start test
/usr/sbin/telnetd
再起動して、確認。おつかれさまでした。

隘路 

touro_mount.shだけを追加したところ、/dev/usbdisk1*が消えている状態となり、/dev/usbdisk1_1がマウントされなかった。hotplug.sh startしたら、/dev/usbdisk1*が作成されるので、これを直前に追加した。

ls-qlに4TB USB Touro接続 (3)

起動スクリプト

/etc/init.d/touro_mount.shを作成。/etc/hotplug.d/scsi_device/usb-buffalo.hotplugを参考にする。
ポイントは青字箇所、partprobeで、パーティションを認識させて、mount_usbdiskでマウントする。mount_usbdiskは、libbuffalo.touroで定義している。
#!/bin/sh
#echo "*** $0:$* pid=$$" >/dev/console
LOCK="/var/lock/touro_mount.lock"
. /usr/local/bin/libbuffalo.touro
. /usr/local/lib/libsys
cleanup_exit()
{
        rm -f ${LOCK}
        exit $1
}
mount_touro()
{
        local i
        for i in `seq 1 ${MAX_USBDISK_NUM}`
        do
    TOURO=`grep /dev/usbdisk${i} /var/tmp/usb_list | grep Touro`
    if [ ! -z "${TOURO}" ] ; then
      ##/usr/local/sbin/partprobe /dev/usbdisk${i}
      partprobe /dev/usbdisk${i}
      mount_usbdisk ${i}
    fi
        done
}
##echo "env=(`env`)"
if [ -f ${LOCK} ] ; then
        exit 1
fi
echo $$ > ${LOCK}
#spinlock_file /var/lock/usb-hotplug
        ### USB-Strage devices
        if [ "$1" = "stop" ]; then
                echo "umount USB disks"
                /usr/local/bin/service_control.sh media stop
                /usr/local/bin/service_control.sh share stop
                for i in `seq 1 ${MAX_USBDISK_NUM}`
                do
                        umount -f ${MPT_USBSHARE}${i}
                done
        fi
        #if [ $? -eq 1 -a "$1" != "create" ]; then
        #fi
  if [ "$1" = "start" ]; then
    mount_touro
    echo "*** [$0 $$] Restarting Daemons..." > /dev/console
    # if ${ACTION} is "remove" already servers are killed.
    # so no need to stop servers at here.
    if [ "${2}" != "test" ] ; then
      /usr/local/bin/service_control.sh media stop
      /usr/local/bin/service_control.sh share stop
      sleep 1
      /usr/local/bin/service_control.sh share start
      /usr/local/bin/service_control.sh media start
    fi
  fi
#echo "--- exit pid=$$" >/dev/console
cleanup_exit $?
libbuffalo.touroを読み込む。libbuffalo.touroは、libbuffaloのmount_usbdiskに下記朱記の変更をしたもの。gptパーティションの名前が、touro_xfsであれば、MountXFSを実行するにした。
mount_usbdisk()
{
...
                     xfs)
                             echo "xfs"
                             MountXFS /dev/${BASENAME}_$minor ${MPT}
                             if [ $? -eq 0 ]; then
                                     chmod 777 ${MPT}
                                     rm -rf "${MPT}/lost+found" > /dev/null >&1
                                     return 0
                             fi
                             ;;
     ### begin - Touro mount
                     *)
       PNM=`grep "^${minor}:" /tmp/fdisk_usb|awk -F ":" '{print $6}'`
                             if [ "${PNM}" = "touro_xfs" ] ; then
         echo "touro_xfs"
         MountXFS /dev/${BASENAME}_$minor ${MPT}
         if [ $? -eq 0 ]; then
           chmod 777 ${MPT}
           rm -rf "${MPT}/lost+found" > /dev/null 2>&1
           return 0
         fi
       fi
                             ;;
     ### end - Touro mount 
...
}

隘路

libbuffaloのmount_usbdiskを書き換えたが、再起動したら書き換え前に戻ってしまった。起動の度に、上書きするようなので、libbuffalo.touroを別に作成した。

つづく。

ls-qlに4TB USB Touro接続 (2)

gpt作成

Touroに、gptでパーティションを作成。AFTなので、パーティション境界を8の倍数セクタ、2048sにする。
>parted /dev/usbdisk1
mklabel gpt
mkpart primary xfs 2048s 100%
name 1 touro_xfs
print

Model: HGST  (scsi)
Disk /dev/sde: 4001GB
Sector size (logical/physical): 4096B/4096B
Partition Table: gpt

Number  Start   End     Size    File system  Name       Flags
 1      8389kB  4001GB  4001GB               touro_xfs

quit

mkpartで、File systemとしてxfsを指定しても、指定されない。Nameに、touro_xfsを設定した(あとで使う)。

ls-ql:~# partprobe /dev/usbdisk1
Error: Partition(s) 1, 16 on /dev/sde have been written, but we have been unable
 to inform the kernel of the change, probably because it/they are in use.  As a
result, the old partition(s) will remain in use.  You should reboot now before m
aking further changes.

再起動しないとkernelが認識しないと言われるが、/dev/usbdisk1_1が認識されている。
再起動せずに続行。

隘路

partprobeのメッセージに従い再起動しても、/dev/usbdisk1_1は認識されない(なくなる)。partprobeを実行すると認識される。つまり、partprobe実行して、再起動せずに続行せざるを得ない。

xfs作成

Touroは、論理/物理のセクタサイズが、4096の模様。セクタサイズ4096で、mkfsする。
>mkfs.xfs -s size=4096 -f /dev/usbdisk1_1
>mount /dev/usbdisk1_1 /mnt/usbdisk1
>xfs_info /mnt/usbdisk1
meta-data=/dev/usbdisk1_1        isize=256    agcount=32, agsize=30523504 blks
         =                       sectsz=4096  attr=0
data     =                       bsize=4096   blocks=976752128, imaxpct=25
         =                       sunit=0      swidth=0 blks, unwritten=1
naming   =version 2              bsize=4096
log      =internal               bsize=4096   blocks=32768, version=2
         =                       sectsz=4096  sunit=1 blks, lazy-count=0
realtime =none                   extsz=4096   blocks=0, rtextents=0

あとは、起動スクリプトに、partprobeの実行とmountを組込む。つづく。

ls-qlに4TB USB Touro接続 (1)

ls-qlは、2TB以上のUSBに対応していない。以前、パーティションを切らずに、xfsを作成、手動でmountすることで使用できるようにしたが、手動マウントするのは面倒。
直ディスクでできるなら、gptでパーティションきればできるのでは?と思って、試してみた。
USBディスクは、4TB Touro DX3。結果、できた。

partedの準備

ls-qlの付属のpartedを、Touroに対して使用すると、異常終了した。Touroは、4096 bytes/sectorであり、付属のpartedは、これに対応していないと推測。(googleで調査してそう思った)
付属のpartedは、v1.8.8なので、バージョン上げてみる。
parted v3.0のソースをダウンロード。クロス環境でビルドする。
>./configure --prefix=/usr/arm-linux-gnueabi --host=arm-linux-gnueabi --disable-device-mapper --without-readline --disable-shared
>make
>make install

/usr/arm-linux-gnueabi/sbinに、parted, partprobe が、
/usr/arm-linxu-gnueabi/libに、libparted.{a,so}がインストールされる。

隘路

./configureのときに、libuuidがないとおこられる。xaptでインストールした。
>xapt -a armel libuuid

ls-qlへのインストール

>mv /usr/local/sbin/parted /usr/local/sbin/parted.org
>mv /usr/local/sbin/partprobe /usr/local/sbin/partprobe.org
parted, partprobeを、コピー。

libparted, libuuidもコピー。

ls-ql:~# ldd /usr/local/sbin/parted
        libparted.so.1 => /usr/lib/libparted.so.1 (0x40026000)
        libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x40081000)
        libc.so.6 => /lib/libc.so.6 (0x40095000)
        libuuid.so.1 => /usr/lib/libuuid.so.1 (0x401c4000)
        libdl.so.2 => /lib/libdl.so.2 (0x401d0000)
        /lib/ld-linux.so.3 (0x40000000)
ls-ql:~# ldd /usr/local/sbin/partprobe
        libparted.so.1 => /usr/lib/libparted.so.1 (0x40026000)
        libuuid.so.1 => /usr/lib/libuuid.so.1 (0x40081000)
        libdl.so.2 => /lib/libdl.so.2 (0x4008d000)
        libc.so.6 => /lib/libc.so.6 (0x40098000)
        libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x401c7000)
        /lib/ld-linux.so.3 (0x40000000)

つづく

2013年7月13日土曜日

ls-ql EM

ls-qlにtelnet、find / -type l -exec rm {} \; してしまった。/以下のリンクが消えた。
busybox使っているので、リンク消えると、lsコマンドも使えなくなる。
リンクを作りなおすのが面倒なので、ファームウェアを入れなおすことにする。

buffaloのファームウェアアップデータを使っても更新できず。
ls-qlを再起動したら、EMモードにもならずにハマる。
tftpdでブートできたことを想い出し、tftpd用意したが、再起動してもファイルを取りに来ない。
tftpdがwindows7に対応していない?と思って、更新するが変化なし。

リンクが消えているだけなので、ブートはできてるから、EMにならないのかも。
仕方ないので、データの入っていないdisk2を、usbでwindowsにつないで、パーティションを消す。
その他のディスクは外しておく。
電源入れて、power buttonを押して、橙色が点灯、functionボタンを押したら、tftpdにファイル取りに来て、EMでブートした。
続けて、ファームウェアの更新をfwupdate.iniに、noformat を0→1, debug=1を追加して、fwupdaterを起動、fwの更新を実行したが、途中で失敗。
disk2のスロットを使っているのが悪いかも?disk1のスロットに接続して再度実行して成功。

今度は、linuxにusbで接続して、telnetをenable(①/usr/sbin/telnetdをrcSに追加、②/etc/shadowのrootのパスワードを削除)

RAIDを手動再構成

cat /proc/mdstat
mdadm -D /dev/md1
ディスク4つで、RAID1なので、構成ディスクを2つにする:
mdadm --manage --set-faulty /dev/md1 /dev/sdc1
mdadm /dev/md1 -r /dev/sdc
mdadm --grow --force -n 2 /dev/md1

認識しないディスクをゼロスーパーブロックする
mdadm --misc --zero-superblock /dev/sdc1

構成ディスクを4に戻して、ディスクを追加する:
mdadm --grow -n 4 /dev/md1 ; mdadm /dev/md1 -a /dev/sdc1 ; mdadm /dev/md1 -a /dev/sdd1 ; cat /proc/mdstat

参考