HOME / 日記 / SSDをSolarisのrpoolにしてみる

Date: 2011/01/09 |  このエントリーをはてなブックマークに追加  |  Tags: Solaris, OpenSolaris, Howto, 利用法, SSD, 4k, GPT

SSDをSolarisのrpoolにしてみる

まえおき

OpenSolaris系OSで、SSDのプールに移動するまでの一手間をまとめてみました。

OpenSolaris系OSでは、SSDを直接使わずにZILやL2ARCの方が良いとは思います。

一般的にSSDを使う場合は、@tokuhyさんが、色々情報をまとめてくれています。

  • http://d.hatena.ne.jp/tokuhy/20101108

とはいえThinkpad T61pの場合、ウルトラベイに入れることがSATAベイはIDE接続なのです。そして実はOpenSolaris系OSでは、AHCIとIDEで大分速度が違うんですよね。

ベイのHDDバスがIDEになると、そこにSSDいれてもむしろパフォーマンスが遅くなったりしてるんじゃないの?(By @satokaz

ということで、iostatを見るんですが、どーにもHDDもSSDも、どっちともIOの%bが飽和しがちなのです。この%bは、マニュアルをみると次のようになっています。

  • %b
    • ディスクのビジー時間率(トランザクションが進行中の)

簡単に言うと、ディスクがおれいま、いっぱいいっぱい!といってる状態になると、100%に近づきます。kr/sやkw/sをみるんじゃなくて、ディスクの速度が十分なマシンなのかどうかは、%b%w*svc_tを見てみましょう。詳しくは→ http://blogs.sun.com/yappri/entry/iostat

今回の計画

さて、今回の計画を整理します

最終的には、SATA(Hitachi HTS72505)に作られたrpoolから、rpool/ROOTのzfsツリーだけ、SSDに持っていくというもの。

  1. ウルトラベイにSSD(SAMSUNG MCCOE64)をつける
  2. そこにROOT以下をzfs sendする
  3. HDDスロットからHDD(Hitachi HTS72505)を取り外し、SSD(SAMSUNG MCCOE64)をHDDのスロットにつける
  4. HDD(Hitachi HTS72505)を、ウルトラベイにつける。HDDのrpoolをdpoolにリネームして、dpool/ROOT以外をマウントする。

途中でSolaris11 Express のLiveCDを利用し、そこからrpoolを触るため、 LiveCDやLiveUSBを作っておく必要があります。

また、細かいところで、ZFS周りの細かいTipsがあります。だって、@hasegawくんが、ZFSはまだ細かい例があまりWEBに出ていないというから(笑)

SSDに新しいpoolをつくる

では、現在のバスの接続です。ウルトラベイにSAMSUNGのSSDがついています。

iostat -En 
c3d0             Soft Errors: 0 Hard Errors: 0 Transport Errors: 0 
Model: SAMSUNG MCCOE64 Revision:  Serial No: SE816A4959      Size: 64.02GB <64022740992 bytes>
Media Error: 0 Device Not Ready: 0 No Device: 0 Recoverable: 0 
Illegal Request: 0 
c4t0d0           Soft Errors: 0 Hard Errors: 0 Transport Errors: 0 
Vendor: ATA      Product: Hitachi HTS72505 Revision: C70E Serial No:  
Size: 500.11GB <500107862016 bytes>
Media Error: 0 Device Not Ready: 0 No Device: 0 Recoverable: 0 
Illegal Request: 13 Predictive Failure Analysis: 0 

こちらのBlogを参考にすると、SSDも4kアラインにして置いた方が良いように見えます。

  • http://wikis.sun.com/display/Performance/How+to+4k+Align+Flash+on+Solaris+x86

そこで4kアラインになるようにformatしますが、EFIボリュームであれば、なんも考えなくても4kアラインのようです。

ただし、ブート用のrpoolはSMIボリュームである必要があるため、fdiskでディスクを切ってあげる必要があります。

パーティション0に対して操作を行います。

pfexec fdisk /dev/rdsk/c3d0p0
No fdisk table exists. The default partition for the disk is:

  a 100% "SOLARIS System" partition

Type "y" to accept the default partition,  otherwise type "n" to edit the
 partition table.

まずは、全部確保します。

y

次に、もう一度起動します。

pfexec fdisk /dev/rdsk/c3d0p0
            Total disk size is 7783 cylinders
            Cylinder size is 16065 (512 byte) blocks
                                              Cylinders
     Partition   Status    Type          Start   End   Length    %
     =========   ======    ============  =====   ===   ======   ===
         1       Active    Solaris2          1  7782    7782    100
SELECT ONE OF THE FOLLOWING:
   1. Create a partition
   2. Specify the active partition
   3. Delete a partition
   4. Change between Solaris and Solaris2 Partition IDs
   5. Edit/View extended partitions
   6. Exit (update disk configuration and exit)
   7. Cancel (exit without updating disk configuration)

最初のCylinders Endの、7782は後で使うのでメモしておきます。

まずは3でこれを削除します。

Enter Selection: 3
 Specify the partition number to delete (or enter 0 to exit): 1
 Are you sure you want to delete partition 1? This will make all files and
 programs in this partition inaccessible (type "y" or "n"). y

 Partition 1 has been deleted. This was the active partition.

次に、新しいものを作成します。もちろん1。

Enter Selection: 1

もちろんSOLARIS2で1。

Select the partition type to create:
   1=SOLARIS2  2=UNIX        3=PCIXOS     4=Other
   5=DOS12     6=DOS16       7=DOSEXT     8=DOSBIG
   9=DOS16LBA  A=x86 Boot    B=Diagnostic C=FAT32
   D=FAT32LBA  E=DOSEXTLBA   F=EFI        0=Exit? 

シリンダーで設定したいのでc。

Specify the percentage of disk to use for this partition
(or type "c" to specify the size in cylinders). 

先頭は8シリンダーなので、8を入力。ここは0オリジンらしい。

Enter starting cylinder number: 

パーティションサイズは、最初の前確保なので7782なので、7を引いて7775

Enter partition size in cylinders: 

y

Should this become the active partition? If yes, it  will be activated
each time the computer is reset or turned on.
Please type "y" or "n". 

最後は6で抜けます。

Enter Selection: 6

最終的には、こうなっています。

            Total disk size is 7783 cylinders
            Cylinder size is 16065 (512 byte) blocks

                                              Cylinders
     Partition   Status    Type          Start   End   Length    %
     =========   ======    ============  =====   ===   ======   ===
         1       Active    Solaris2          8  7782    7775    100

Cylinders Start8から始まることに注目。

次はformat。

pfexec format /dev/rdsk/c3d0p0

pを2回叩くと、Partition -> printとなります。

partition> p
Current partition table (original):
Total disk cylinders available: 7773 + 2 (reserved cylinders)

Part      Tag    Flag     Cylinders        Size            Blocks
  0 unassigned    wm       0               0         (0/0/0)            0
  1 unassigned    wm       0               0         (0/0/0)            0
  2     backup    wu       0 - 7772       59.54GB    (7773/0/0) 124873245
  3 unassigned    wm       0               0         (0/0/0)            0
  4 unassigned    wm       0               0         (0/0/0)            0
  5 unassigned    wm       0               0         (0/0/0)            0
  6 unassigned    wm       0               0         (0/0/0)            0
  7 unassigned    wm       0               0         (0/0/0)            0
  8       boot    wu       0 -    0        7.84MB    (1/0/0)        16065
  9 alternates    wm       1 -    2       15.69MB    (2/0/0)        32130

ここでも8の倍数を意識します。

スライス0を作ります。

partition> 0
Part      Tag    Flag     Cylinders        Size            Blocks
  0 unassigned    wm       0               0         (0/0/0)            0

Enter partition id tag[unassigned]: root
Enter partition permission flags[wm]: 
Enter new starting cyl[3]: 8
Enter partition size[0b, 0c, 8e, 0.00mb, 0.00gb]: 7772e

7772eは、エンド・シリンダですが、8で割り切れることを確認しておきます。

labelコマンドで、書き込みます。

partition> label
Ready to label disk, continue? y

おわったらquit。ということで割りと簡単ですね。

こんどは、c3d0s0が確保したボリュームと言うことになります。

コピー先のSSDディスクに、新しいpoolを作成。

まずSSD側に、rpool2を作ります。このrpool2は、最後にrpoolにリネームします。

pfexec  zpool create -f rpool2 /dev/dsk/c3d0s0 

Boot用のgrubも作ります。

pfexec installgrub /boot/grub/stage1 /boot/grub/stage2 /dev/rdsk/c3d0s0

boot時に必要なファイルをコピーします。

pfexec cp -rp /rpool/etc /rpool/boot /rpool2/

ついでにdedupを仕掛ける

新しいZFSにはdedup(重複排除)があります。この機能は、おなじデータがあるときは、おなじ領域を使うことにより、容量を若干節約することができます。

zfsのdedupはpoolに書き込む時に重複チェックを行うため、zfs recvの最中にもdedupがかかります。構造的にはrecordsize単位のハッシュがあり、書き込み時におなじ物であれば再利用をするという仕組みです。

このために、書き込み時にはディスクのrecordの数だけのハッシュテーブルのチェックを行うのですが・・・・。

  • ディスクの実体がとても大きいと、ハッシュテーブルも巨大になる。
    • ハッシュテーブルの検索時間がかかるので、ディスクへの書き込みも遅くなる。CPUもつかう。
  • メモリが足りなくなると、ハッシュテーブルをディスクへ落とすので、とてつもなく遅くなる。
  • 容量の空きが増えるが、書き込み速度は総じて遅くなるため、利用には注意。
  • ON/OFFは、fs毎に設定することができる。
  • 読み込みにはコストがほとんど発生しない。
    • フラグメントが発生しやすいのでは?と考えられるが、そもそもZFSはCopy on Writeなので、部分書き換えが発生すると、フラグメントは発生する。フラグメントより、安全性ってことで。

そこで、今回は、転送するときにdedupをONにします。

pfexec zfs set dedup=on rpool2

zfs recvが終わったらOFFにします。

rpoolのデータ転送

rpool直下、rpool/ROOTがbootに必要なデータです。まずは、ROOT以下の転送をします。

pfexec zfs snapshot -r rpool/ROOT@send
pfexec zfs send -R rpool/ROOT@send | pfexec zfs recv -Fd rpool2 

-Rをつけるのは、プロパティまで転送する必要があるためです。

転送中、別のターミナルで色々様子を見てみます。

vmstat
kthr      memory            page            disk          faults      cpu
r b w   swap  free  re  mf pi po fr de sr bk cd s0 --   in   sy   cs us sy id
0 0 0 5267864 4244572 110 413 8 0 0  0 52  0  4 71  0 1302 26774 1851 6  8 86
7 0 0 1660652 611592 21 292 0  0  0  0  0  0 130 565 0 8785 6238 4823 8 63 29
0 0 0 1632404 585680 0   7  0  0  0  0  0  0 454 770 0 6008 9078 6438 6 44 51
0 0 0 1598904 552148 0   9  0  0  0  0  0  0  0 812 0 2701 10180 8800 5 28 67
14 0 0 1570388 523612 0  5  0  0  0  0  0  0 129 538 0 8399 6472 11649 4 76 20

想像通り、sysを結構食ってます。

prstat 
  PID USERNAME  SIZE   RSS STATE  PRI NICE      TIME  CPU PROCESS/NLWP       
12138 root        0K    0K cpu1    99  -20   0:01:11  24% zpool-rpool2/138
    5 root        0K    0K cpu1    99  -20   0:04:49  15% zpool-rpool/138

書き込み側の方がCPU食ってますね。

prstat -mL
  PID USERNAME USR SYS TRP TFL DFL LCK SLP LAT VCX ICX SCL SIG PROCESS/LWPID 
12138 root     0.0  19 0.0 0.0 0.0 0.0  76 4.8 246  20   0   0 zpool-rpool2/12
12138 root     0.0  17 0.0 0.0 0.0 0.0  78 5.1 264  19   0   0 zpool-rpool2/14
    5 root     0.0 9.8 0.0 0.0 0.0 0.0  84 5.8 311   7   0   0 zpool-rpool/137
    5 root     0.0 6.8 0.0 0.0 0.0 0.0  85 8.4 287   4   0   0 zpool-rpool/12

書き込み側のsysの利用率がけっこうなものです。

iostat-Yn
                   extended device statistics              
   r/s    w/s   kr/s   kw/s wait actv wsvc_t asvc_t  %w  %b device
  98.6  427.8  256.0 29102.4  3.6  1.7    6.9    3.2  78  88 c3d0
 413.3    0.0 31233.7    0.0  2.5  0.6    6.2    1.4  46  56 c4t0d0

ディスクの書き込み速度は30MB/sec弱。%bが90%弱なので、ディスクは割りと一杯一杯です。

pfexec intrstat 
     device |      cpu0 %tim      cpu1 %tim
  • +------------------------------
     ahci#0 |       198  0.7         0  0.0
      ata#0 |         0  0.0      1109  4.4

書き込み側のataは結構CPUの割り込みが多いようです。

転送が終わったら、dedupをoffにしておきます。

pfexec zfs set dedup=off rpool2

dedupの具合を確認します。

zpool list rpool2
NAME    SIZE  ALLOC   FREE    CAP  DEDUP  HEALTH  ALTROOT
rpool2   59G  31.3G  27.7G    53%  1.09x  ONLINE  -

システムだけで10%弱の効率があることがわかりました。

zfs recv時に再圧縮がかかるのか?

zfs sendはfs毎に、fsを丸ごとコピーします。compressionはfsに書き込む時に行ってるはずなので、zfs recv時には再圧縮はかからないはずです。

そこで実験のために、受け取り側のcompressionをgzip-9にして転送します。gzipは圧縮はそれなりに時間がかかるが、展開は速いアルゴリズムで、またZFSはCopy on Writeです。転送後に設定を変えておけばgzipでシステムが圧縮され、書き換えが始まったところから、圧縮無しにておけば、システムの中でほとんどreadonlyの部分だけがgzipで圧縮されていて、メリットがでます。

そこで、転送先をgzip-9にしておき、転送時に圧縮されないだろうなぁ・・とおもいつつ、念のため、やってみました。

pfexec zfs set compression=gzip-9 rpool2

転送後、確認。

zfs list -o name,used,avail,compressratio rpool/ROOT rpool2/ROOT  

NAME USED AVAIL RATIOrpool/ROOT 33.6G 112G 2.08xrpool2/ROOT 33.6G 26.8G 2.08x

思った通り圧縮率は変わりませんでした。残念(笑)

ということで再圧縮をするためには、rsyncをしてコピーしなおすしかないでしょう。

ディスクの付け替え

ウルトラベイにつけていたSSDをHDDベイに移動します。ここでは、ウルトラベイにDVDドライブをつけ、そこから、LiveCDでOSを起動しました。

rpool2を新しいrpoolとしてimportします。

sudo zpool import -f rpool2 rpool

mountpointをlegacyにかえて、mount

sudo zfs set mountpoint=legacy rpool/ROOT/Solaris11Express
sudo mount -F zfs rpool/ROOT/Solaris11Express /mnt

boot_archiveの作成

sudo bootadm update-archive -R /mnt

umountします。

sudo zfs set mountpoint=/ rpool/ROOT/Solaris11Express
sudo umount /mnt

今のバージョンでは関係なかったかもしれないけれど、念のため。rpool/ROOT/Solaris11Expressが起動用のbootfsとします。

sudo zpool set bootfs=rpool/ROOT/Solaris11Express rpool

rpoolを解放します。

sudo zpool export rpool

ブート時にrpoolをmountするが、付け所を変えるとboot_archiveと実態のディスクの間に不整合がおきてしまいます。そこで、一度importをして、上記のようにboot_archiveを作り直せば、たいていの場合は場所の移動ができます。

これって、まめちしきね。

ちなみに、Solaris 11の起動シーケンスは、おおざっぱに言うと、次のような感じになっています。

  1. grubを読む(installgrubでインストールする)
  2. menu.lstを読む。
    • bootfsは、zfsの場合はbeadmによって複数あり得うるので、これはzbeの外にある。OSブート後は、rpool/ROOT/〜が/にマウントされるため、それ以外の箇所、rpool/grub/menu.lstがSolarisのmenu.lst
  3. menu.lstからboot_archiveをよむ。
  4. boot_archiveでramdiskが展開される。
  5. ramdisk内に設定されているpoolをimportする
    • これに失敗すると、起動途中でCrashする。
  6. ramdiskからboot処理で指定されているzfsをマウントする
    • Solaris10やの場合、zpool set bootfsで指定した物・・・だとおもう。vfstabもみていたかもしれない。
    • Solaris11は、ramdisk内に入ってる物をみてるのかなぁ・・・ちょっと未調査。

こんな感じです。状態に合わせて、トラブルシューティングができますが、これはOpenSolarisの勉強会で一度まとめたほうがいいんですかね?トラブルシューティングのために・・・。

HDDのマウント

これで、起動ができるようになったはずですが、大事なデータはほとんどHDDに入っているので、HDD(Hitachi HTS72505)をウルトラベイにつけ起動しなおし、これをdpoolとします。起動は普通に終わりますが、HOMEはHDDに残っており、通常のgnomeのログインはできません。そこで、ログイン時にxtermに変えれば、ログイン出来ます。

HDDもrpoolのままなので、import時にdpoolに名前を変えます。名前でimportすると混乱があるのでpoolのguidでimportします。guidは、zpool importと行うだけでわかります。

pfexec zpool import -f 8087097575917017089 dpool

これで、root系以外が全てマウントできるので、リログをすれば普通に環境が帰ってくるはずです。

最後の後処理

ゴミ消去

rpool2のディレクトリがあるので、ゴミを削除します。

pfexec rmdir /rpool2/ 

dumpの指定

pfexec dumpadm 
      Dump content: kernel pages

Dump device: none (dumps disabled)

Savecore directory: /var/crash/hadriel
  Savecore enabled: はい
   Save compressed: オン

今回のrpoolのSSDはたったの64GBしかないので、dumpはdpoolのままでいいかなと考え、dumpデバイスの設定をします。

もし、dpool/dumpが無ければ作ります。

pfexec zfs create -V 4G -o compression=off dpool/dump 
pfexec zfs set com.sun:auto-snapshot=false dpool/dump

dumpデバイスに設定します。

pfexec dumpadm -d /dev/zvol/dsk/dpool/dump       
mkdir -p /var/crash/hadriel

swapの設定

必要であれば、swapデバイスを設定します。

速度を重視すればSSD、SSDの寿命を重視すればHDDですが・・・。

pfexec zfs create -V 8G -o compression=off dpool/swap 
pfexec zfs set com.sun:auto-snapshot=false dpool/swap

日記

Recent Updates